Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
GSoC
GSoC2018
macOS
vlc
Commits
52af2d54
Commit
52af2d54
authored
Aug 03, 2009
by
Laurent Aimar
Browse files
Converted vout caca to "vout display" API.
parent
de33cab8
Changes
1
Hide whitespace changes
Inline
Side-by-side
modules/video_output/caca.c
View file @
52af2d54
/*****************************************************************************
* caca.c: Color ASCII Art
video output plugin
using libcaca
* caca.c: Color ASCII Art
"vout display" module
using libcaca
*****************************************************************************
* Copyright (C) 2003-2009 the VideoLAN team
* $Id$
*
* Authors: Sam Hocevar <sam@zoy.org>
* Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -31,393 +32,501 @@
#include
<vlc_common.h>
#include
<vlc_plugin.h>
#include
<vlc_vout.h>
#include
<vlc_interface.h>
#include
<vlc_playlist.h>
#include
<vlc_keys.h>
#include
<vlc_vout_display.h>
#include
<vlc_picture_pool.h>
#include
<caca.h>
#ifndef CACA_API_VERSION_1
/* Upward compatibility macros */
typedef
char
cucul_canvas_t
;
typedef
struct
caca_bitmap
cucul_dither_t
;
typedef
char
caca_display_t
;
# define CUCUL_COLOR_DEFAULT CACA_COLOR_LIGHTGRAY
# define CUCUL_COLOR_BLACK CACA_COLOR_BLACK
# define cucul_clear_canvas(x) caca_clear()
# define cucul_create_canvas(x,y) ""
/* kinda hacky */
# define cucul_create_dither caca_create_bitmap
# define cucul_dither_bitmap(x,y,z,t,u,v,w) caca_draw_bitmap(y,z,t,u,v,w)
# define cucul_free_dither caca_free_bitmap
# define cucul_free_canvas(x)
# define cucul_get_canvas_width(x) caca_get_width()
# define cucul_get_canvas_height(x) caca_get_height()
# define cucul_set_color(x,y,z) caca_set_color(y,z)
# define caca_create_display(x) (caca_init() ? NULL : "")
/* hacky, too */
# define caca_free_display(x) caca_end()
# define caca_get_event(x,y,z,t) *(z) = caca_get_event(y)
# define caca_refresh_display(x) caca_refresh()
# define caca_set_display_title(x,y) caca_set_window_title(y)
#endif
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
Create
(
vlc_object_t
*
);
static
void
Destroy
(
vlc_object_t
*
);
static
int
Init
(
vout_thread_t
*
);
static
void
End
(
vout_thread_t
*
);
static
int
Manage
(
vout_thread_t
*
);
static
void
Render
(
vout_thread_t
*
,
picture_t
*
);
static
void
Display
(
vout_thread_t
*
,
picture_t
*
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin
()
set_shortname
(
"Caca"
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_description
(
N_
(
"Color ASCII art video output"
)
)
set_capability
(
"video output"
,
12
)
set_callbacks
(
Create
,
Destroy
)
vlc_module_end
()
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
()
set_shortname
(
"Caca"
)
set_category
(
CAT_VIDEO
)
set_subcategory
(
SUBCAT_VIDEO_VOUT
)
set_description
(
N_
(
"Color ASCII art video output"
))
set_capability
(
"vout display"
,
12
)
set_callbacks
(
Open
,
Close
)
vlc_module_end
()
/*****************************************************************************
* vout_sys_t: libcaca video output method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the libcaca specific properties of an output thread.
* Local prototypes
*****************************************************************************/
struct
vout_sys_t
{
cucul_canvas_t
*
p_cv
;
caca_display_t
*
p_dp
;
cucul_dither_t
*
p_dither
;
static
picture_t
*
Get
(
vout_display_t
*
);
static
void
Prepare
(
vout_display_t
*
,
picture_t
*
);
static
void
Display
(
vout_display_t
*
,
picture_t
*
);
static
int
Control
(
vout_display_t
*
,
int
,
va_list
);
/* */
static
void
Manage
(
vout_display_t
*
);
static
void
Refresh
(
vout_display_t
*
);
static
void
Place
(
vout_display_t
*
,
vout_display_place_t
*
);
/* */
struct
vout_display_sys_t
{
cucul_canvas_t
*
cv
;
caca_display_t
*
dp
;
cucul_dither_t
*
dither
;
picture_pool_t
*
pool
;
};
/*****************************************************************************
* Create: allocates libcaca video output thread
*****************************************************************************
/**
* This function initializes libcaca vout method.
****************************************************************************
*/
static
int
Create
(
vlc_object_t
*
p_this
)
*/
static
int
Open
(
vlc_object_t
*
object
)
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_this
;
vout_display_t
*
vd
=
(
vout_display_t
*
)
object
;
vout_display_sys_t
*
sys
;
#if defined(
WIN32
) && !defined(
UNDER_CE
)
#if defined(WIN32) && !defined(UNDER_CE)
CONSOLE_SCREEN_BUFFER_INFO
csbiInfo
;
SMALL_RECT
rect
;
COORD
coord
;
HANDLE
hstdout
;
if
(
!
AllocConsole
()
)
{
msg_Err
(
p_vout
,
"cannot create console"
);
if
(
!
AllocConsole
())
{
msg_Err
(
vd
,
"cannot create console"
);
return
VLC_EGENERIC
;
}
hstdout
=
CreateConsoleScreenBuffer
(
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
CONSOLE_TEXTMODE_BUFFER
,
NULL
);
if
(
!
hstdout
||
hstdout
==
INVALID_HANDLE_VALUE
)
{
msg_Err
(
p_vout
,
"cannot create screen buffer"
);
CreateConsoleScreenBuffer
(
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
CONSOLE_TEXTMODE_BUFFER
,
NULL
);
if
(
!
hstdout
||
hstdout
==
INVALID_HANDLE_VALUE
)
{
msg_Err
(
vd
,
"cannot create screen buffer"
);
FreeConsole
();
return
VLC_EGENERIC
;
}
if
(
!
SetConsoleActiveScreenBuffer
(
hstdout
)
)
{
msg_Err
(
p_vout
,
"cannot set active screen buffer"
);
if
(
!
SetConsoleActiveScreenBuffer
(
hstdout
))
{
msg_Err
(
vd
,
"cannot set active screen buffer"
);
FreeConsole
();
return
VLC_EGENERIC
;
}
coord
=
GetLargestConsoleWindowSize
(
hstdout
);
msg_Dbg
(
p_vout
,
"SetConsoleWindowInfo: %ix%i"
,
coord
.
X
,
coord
.
Y
);
coord
=
GetLargestConsoleWindowSize
(
hstdout
);
msg_Dbg
(
vd
,
"SetConsoleWindowInfo: %ix%i"
,
coord
.
X
,
coord
.
Y
);
/* Force size for now */
coord
.
X
=
100
;
coord
.
Y
=
40
;
if
(
!
SetConsoleScreenBufferSize
(
hstdout
,
coord
)
)
msg_Warn
(
p_vout
,
"SetConsoleScreenBufferSize %i %i"
,
coord
.
X
,
coord
.
Y
);
if
(
!
SetConsoleScreenBufferSize
(
hstdout
,
coord
)
)
msg_Warn
(
vd
,
"SetConsoleScreenBufferSize %i %i"
,
coord
.
X
,
coord
.
Y
);
/* Get the current screen buffer size and window position. */
if
(
GetConsoleScreenBufferInfo
(
hstdout
,
&
csbiInfo
)
)
{
if
(
GetConsoleScreenBufferInfo
(
hstdout
,
&
csbiInfo
))
{
rect
.
Top
=
0
;
rect
.
Left
=
0
;
rect
.
Right
=
csbiInfo
.
dwMaximumWindowSize
.
X
-
1
;
rect
.
Bottom
=
csbiInfo
.
dwMaximumWindowSize
.
Y
-
1
;
if
(
!
SetConsoleWindowInfo
(
hstdout
,
TRUE
,
&
rect
)
)
msg_Dbg
(
p_vout
,
"SetConsoleWindowInfo failed: %ix%i"
,
rect
.
Right
,
rect
.
Bottom
);
if
(
!
SetConsoleWindowInfo
(
hstdout
,
TRUE
,
&
rect
)
)
msg_Dbg
(
vd
,
"SetConsoleWindowInfo failed: %ix%i"
,
rect
.
Right
,
rect
.
Bottom
);
}
#endif
/* Allocate structure */
p_vout
->
p_sys
=
malloc
(
sizeof
(
vout_sys_t
)
);
if
(
p_vout
->
p_sys
==
NULL
)
{
#if defined( WIN32 ) && !defined( UNDER_CE )
FreeConsole
();
#endif
return
VLC_ENOMEM
;
vd
->
sys
=
sys
=
calloc
(
1
,
sizeof
(
*
sys
));
if
(
!
sys
)
goto
error
;
sys
->
cv
=
cucul_create_canvas
(
0
,
0
);
if
(
!
sys
->
cv
)
{
msg_Err
(
vd
,
"cannot initialize libcucul"
);
goto
error
;
}
p_vout
->
p_sys
->
p_cv
=
cucul_create_canvas
(
0
,
0
);
if
(
!
p_vout
->
p_sys
->
p_cv
)
{
msg_Err
(
p_vout
,
"cannot initialize libcucul"
);
#if defined( WIN32 ) && !defined( UNDER_CE )
FreeConsole
();
#endif
free
(
p_vout
->
p_sys
);
return
VLC_EGENERIC
;
sys
->
dp
=
caca_create_display
(
sys
->
cv
);
if
(
!
sys
->
dp
)
{
msg_Err
(
vd
,
"cannot initialize libcaca"
);
goto
error
;
}
p_vout
->
p_sys
->
p_dp
=
caca_create_display
(
p_vout
->
p_sys
->
p_cv
);
if
(
!
p_vout
->
p_sys
->
p_dp
)
{
msg_Err
(
p_vout
,
"cannot initialize libcaca"
);
cucul_free_canvas
(
p_vout
->
p_sys
->
p_cv
);
#if defined( WIN32 ) && !defined( UNDER_CE )
FreeConsole
();
#endif
free
(
p_vout
->
p_sys
);
return
VLC_EGENERIC
;
if
(
vd
->
cfg
->
display
.
title
)
caca_set_display_title
(
sys
->
dp
,
vd
->
cfg
->
display
.
title
);
else
caca_set_display_title
(
sys
->
dp
,
VOUT_TITLE
"(Colour AsCii Art)"
);
/* Fix format */
video_format_t
fmt
=
vd
->
fmt
;
if
(
fmt
.
i_chroma
!=
VLC_CODEC_RGB32
)
{
fmt
.
i_chroma
=
VLC_CODEC_RGB32
;
fmt
.
i_rmask
=
0x00ff0000
;
fmt
.
i_gmask
=
0x0000ff00
;
fmt
.
i_bmask
=
0x000000ff
;
}
caca_set_display_title
(
p_vout
->
p_sys
->
p_dp
,
VOUT_TITLE
" - Colour AsCii Art (caca)"
);
/* */
sys
->
pool
=
picture_pool_NewFromFormat
(
&
fmt
,
1
);
if
(
!
sys
->
pool
)
goto
error
;
p_vout
->
pf_init
=
Init
;
p_vout
->
pf_end
=
End
;
p_vout
->
pf_manage
=
Manage
;
p_vout
->
pf_render
=
Render
;
p_vout
->
pf_display
=
Display
;
/* TODO */
vout_display_info_t
info
=
vd
->
info
;
/* Setup vout_display now that everything is fine */
vd
->
fmt
=
fmt
;
vd
->
info
=
info
;
vd
->
get
=
Get
;
vd
->
prepare
=
Prepare
;
vd
->
display
=
Display
;
vd
->
control
=
Control
;
vd
->
manage
=
Manage
;
/* Fix initial state */
vout_display_SendEventFullscreen
(
vd
,
false
);
Refresh
(
vd
);
return
VLC_SUCCESS
;
error:
if
(
sys
)
{
if
(
sys
->
pool
)
picture_pool_Delete
(
sys
->
pool
);
if
(
sys
->
dither
)
cucul_free_dither
(
sys
->
dither
);
if
(
sys
->
dp
)
caca_free_display
(
sys
->
dp
);
if
(
sys
->
cv
)
cucul_free_canvas
(
sys
->
cv
);
free
(
sys
);
}
#if defined(WIN32) && !defined(UNDER_CE)
FreeConsole
();
#endif
return
VLC_EGENERIC
;
}
/**
***************************************************************************
*
Init: initialize
libcaca video output
thread
****************************************************************************
*/
static
int
Init
(
vout_thread_t
*
p_vout
)
/**
*
Close a
libcaca video output
*/
static
void
Close
(
vlc_object_t
*
object
)
{
int
i_index
;
picture_t
*
p_pic
=
NULL
;
I_OUTPUTPICTURES
=
0
;
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB32
;
p_vout
->
output
.
i_width
=
p_vout
->
render
.
i_width
;
p_vout
->
output
.
i_height
=
p_vout
->
render
.
i_height
;
p_vout
->
output
.
i_aspect
=
p_vout
->
render
.
i_aspect
;
p_vout
->
output
.
i_rmask
=
0x00ff0000
;
p_vout
->
output
.
i_gmask
=
0x0000ff00
;
p_vout
->
output
.
i_bmask
=
0x000000ff
;
/* Create the libcaca dither object */
p_vout
->
p_sys
->
p_dither
=
cucul_create_dither
(
32
,
p_vout
->
output
.
i_width
,
p_vout
->
output
.
i_height
,
4
*
((
p_vout
->
output
.
i_width
+
15
)
&
~
15
),
p_vout
->
output
.
i_rmask
,
p_vout
->
output
.
i_gmask
,
p_vout
->
output
.
i_bmask
,
0x00000000
);
if
(
!
p_vout
->
p_sys
->
p_dither
)
{
msg_Err
(
p_vout
,
"could not create libcaca dither object"
);
return
VLC_EGENERIC
;
}
vout_display_t
*
vd
=
(
vout_display_t
*
)
object
;
vout_display_sys_t
*
sys
=
vd
->
sys
;
/* Find an empty picture slot */
for
(
i_index
=
0
;
i_index
<
VOUT_MAX_PICTURES
;
i_index
++
)
{
if
(
p_vout
->
p_picture
[
i_index
].
i_status
==
FREE_PICTURE
)
{
p_pic
=
p_vout
->
p_picture
+
i_index
;
break
;
}
}
picture_pool_Delete
(
sys
->
pool
);
if
(
sys
->
dither
)
cucul_free_dither
(
sys
->
dither
);
caca_free_display
(
sys
->
dp
);
cucul_free_canvas
(
sys
->
cv
);
if
(
p_pic
==
NULL
)
{
return
VLC_EGENERIC
;
#if defined(WIN32) && !defined(UNDER_CE)
FreeConsole
();
#endif
free
(
sys
);
}
/**
* Return a direct buffer
*/
static
picture_t
*
Get
(
vout_display_t
*
vd
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
return
picture_pool_Get
(
sys
->
pool
);
}
/**
* Prepare a picture for display */
static
void
Prepare
(
vout_display_t
*
vd
,
picture_t
*
picture
)
{
vout_display_sys_t
*
sys
=
vd
->
sys
;
if
(
!
sys
->
dither
)
{
/* Create the libcaca dither object */
sys
->
dither
=
cucul_create_dither
(
32
,
vd
->
source
.
i_visible_width
,
vd
->
source
.
i_visible_height
,
picture
->
p
[
0
].
i_pitch
,
vd
->
fmt
.
i_rmask
,
vd
->
fmt
.
i_gmask
,
vd
->
fmt
.
i_bmask
,
0x00000000
);
if
(
!
sys
->
dither
)
{
msg_Err
(
vd
,
"could not create libcaca dither object"
);
return
;
}
}
/* Allocate the picture */
p_pic
->
p
->
i_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
;
p_pic
->
p
->
i_pitch
=
4
*
((
p_vout
->
output
.
i_width
+
15
)
&
~
15
);
p_pic
->
p
->
i_pixel_pitch
=
4
;
p_pic
->
p
->
i_visible_pitch
=
4
*
p_vout
->
output
.
i_width
;
p_pic
->
i_planes
=
1
;
p_pic
->
p
->
p_pixels
=
malloc
(
p_pic
->
p
->
i_pitch
*
p_pic
->
p
->
i_lines
);
vout_display_place_t
place
;
Place
(
vd
,
&
place
);
p_pic
->
i_status
=
DESTROYED_PICTURE
;
p_pic
->
i_type
=
DIRECT_PICTURE
;
cucul_set_color_ansi
(
sys
->
cv
,
CUCUL_COLOR_DEFAULT
,
CUCUL_COLOR_BLACK
)
;
cucul_clear_canvas
(
sys
->
cv
)
;
PP_OUTPUTPICTURE
[
I_OUTPUTPICTURES
]
=
p_pic
;
I_OUTPUTPICTURES
++
;
const
int
crop_offset
=
vd
->
source
.
i_y_offset
*
picture
->
p
->
i_pitch
+
vd
->
source
.
i_x_offset
*
picture
->
p
->
i_pixel_pitch
;
cucul_dither_bitmap
(
sys
->
cv
,
place
.
x
,
place
.
y
,
place
.
width
,
place
.
height
,
sys
->
dither
,
&
picture
->
p
->
p_pixels
[
crop_offset
]);
}
return
VLC_SUCCESS
;
/**
* Display a picture
*/
static
void
Display
(
vout_display_t
*
vd
,
picture_t
*
picture
)
{
Refresh
(
vd
);
picture_Release
(
picture
);
}
/**
***************************************************************************
*
End: terminate libcaca video output thread
****************************************************************************
*/
static
void
End
(
vout_thread_t
*
p_vout
)
/**
*
Control for vout display
*/
static
int
Control
(
vout_display_t
*
vd
,
int
query
,
va_list
args
)
{
cucul_free_dither
(
p_vout
->
p_sys
->
p_dither
);
vout_display_sys_t
*
sys
=
vd
->
sys
;
switch
(
query
)
{
case
VOUT_DISPLAY_HIDE_MOUSE
:
caca_set_mouse
(
sys
->
dp
,
0
);
return
VLC_SUCCESS
;
case
VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
:
{
const
vout_display_cfg_t
*
cfg
=
va_arg
(
args
,
const
vout_display_cfg_t
*
);
caca_refresh_display
(
sys
->
dp
);
/* Not quite good but not sure how to resize it */
if
(
cfg
->
display
.
width
!=
caca_get_display_width
(
sys
->
dp
)
||
cfg
->
display
.
height
!=
caca_get_display_height
(
sys
->
dp
))
return
VLC_EGENERIC
;
return
VLC_SUCCESS
;
}
case
VOUT_DISPLAY_CHANGE_ZOOM
:
case
VOUT_DISPLAY_CHANGE_DISPLAY_FILLED
:
case
VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
:
return
VLC_SUCCESS
;
case
VOUT_DISPLAY_CHANGE_SOURCE_CROP
:
if
(
sys
->
dither
)
cucul_free_dither
(
sys
->
dither
);
sys
->
dither
=
NULL
;
return
VLC_SUCCESS
;
default:
msg_Err
(
vd
,
"Unsupported query in vout display caca"
);
return
VLC_EGENERIC
;
}
}
/*****************************************************************************
* Destroy: destroy libcaca video output thread
*****************************************************************************
* Terminate an output method created by AaCreateOutputMethod
*****************************************************************************/
static
void
Destroy
(
vlc_object_t
*
p_this
)
/**
* Refresh the display and send resize event
*/
static
void
Refresh
(
vout_display_t
*
vd
)
{
vout_
thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_thi
s
;
vout_
display_sys_t
*
sys
=
vd
->
sy
s
;
caca_free_display
(
p_vout
->
p_sys
->
p_dp
);
c
ucul_free_canvas
(
p_vout
->
p_sys
->
p_cv
);
/* */
c
aca_refresh_display
(
sys
->
dp
);
#if defined( WIN32 ) && !defined( UNDER_CE )
FreeConsole
(
);
#endif
/* */
const
int
width
=
caca_get_display_width
(
sys
->
dp
);
const
int
height
=
caca_get_display_height
(
sys
->
dp
);
free
(
p_vout
->
p_sys
);
if
(
width
!=
vd
->
cfg
->
display
.
width
||
height
!=
vd
->
cfg
->
display
.
height
)
vout_display_SendEventDisplaySize
(
vd
,
width
,
height
);
}
/*****************************************************************************
* Manage: handle libcaca events
*****************************************************************************
* This function should be called regularly by video output thread. It manages
* console events. It returns a non null value on error.
*****************************************************************************/
static
int
Manage
(
vout_thread_t
*
p_vout
)
/**
* Compute the place in canvas unit.
*/
static
void
Place
(
vout_display_t
*
vd
,
vout_display_place_t
*
place
)
{
#ifdef CACA_API_VERSION_1
struct
caca_event
ev
;
#else
int
ev
;
#endif
vout_display_sys_t
*
sys
=
vd
->
sys
;
vout_display_PlacePicture
(
place
,
&
vd
->
source
,
vd
->
cfg
,
false
);
const
int
canvas_width
=
cucul_get_canvas_width
(
sys
->
cv
);
const
int
canvas_height
=
cucul_get_canvas_height
(
sys
->
cv
);
const
int
display_width
=
caca_get_display_width
(
sys
->
dp
);
const
int
display_height
=
caca_get_display_height
(
sys
->
dp
);
if
(
display_width
>
0
&&
display_height
>
0
)
{
place
->
x
=
place
->
x
*
canvas_width
/
display_width
;
place
->
y
=
place
->
y
*
canvas_height
/
display_height
;
place
->
width
=
(
place
->
width
*
canvas_width
+
display_width
/
2
)
/
display_width
;
place
->
height
=
(
place
->
height
*
canvas_height
+
display_height
/
2
)
/
display_height
;
}
else
{
place
->
x
=
0
;
place
->
y
=
0
;
place
->
width
=
canvas_width
;
place
->
height
=
display_height
;
}
}
while
(
caca_get_event
(
p_vout
->
p_sys
->
p_dp
,
CACA_EVENT_ANY
,
&
ev
,
0
)
)
{
playlist_t
*
p_playlist
;
vlc_value_t
val
;
#ifdef CACA_API_VERSION_1
#ifdef CACA_EVENT_OPAQUE
switch
(
caca_get_event_type
(
&
ev
)
)
#else
switch
(
ev
.
type
)
#endif
/* CACA_EVENT_OPAQUE */
#else
switch
(
ev
)
#endif
{
case
CACA_EVENT_KEY_RELEASE
:
#ifdef CACA_API_VERSION_1
#ifdef CACA_EVENT_OPAQUE
switch
(
caca_get_event_key_ch
(
&
ev
)
)
#else
switch
(
ev
.
data
.
key
.
ch
)
#endif
/* CACA_EVENT_OPAQUE */
#else
switch
(
ev
&
0x00ffffff
)
#endif
{
case
'q'
:
val
.
i_int
=
KEY_MODIFIER_CTRL
|
'q'
;
break
;
case
' '
:
val
.
i_int
=
KEY_SPACE
;
break
;
default:
continue
;
}
/* */
static
const
struct
{
int
caca
;
int
vlc
;
}
keys
[]
=
{
{
CACA_KEY_CTRL_A
,
KEY_MODIFIER_CTRL
|
'a'
},
{
CACA_KEY_CTRL_B
,
KEY_MODIFIER_CTRL
|
'b'
},
{
CACA_KEY_CTRL_C
,
KEY_MODIFIER_CTRL
|
'c'
},
{
CACA_KEY_CTRL_D
,
KEY_MODIFIER_CTRL
|
'd'
},
{
CACA_KEY_CTRL_E
,
KEY_MODIFIER_CTRL
|
'e'
},
{
CACA_KEY_CTRL_F
,
KEY_MODIFIER_CTRL
|
'f'
},
{
CACA_KEY_CTRL_G
,
KEY_MODIFIER_CTRL
|
'g'
},
{
CACA_KEY_BACKSPACE
,
KEY_BACKSPACE
},
{
CACA_KEY_TAB
,
KEY_TAB
},
{
CACA_KEY_CTRL_J
,
KEY_MODIFIER_CTRL
|
'j'
},
{
CACA_KEY_CTRL_K
,
KEY_MODIFIER_CTRL
|
'k'
},