1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
11 #include "vg/vg_log.h"
13 #define VG_VAR_F32_PERSISTENT( NAME ) \
14 vg_var_push( (struct vg_var){ \
17 .data_type = k_var_dtype_f32, \
21 #define VG_VAR_F32( NAME ) \
22 vg_var_push( (struct vg_var){ \
25 .data_type = k_var_dtype_f32, \
28 #define VG_VAR_I32_PERSISTENT( NAME ) \
29 vg_var_push( (struct vg_var){ \
32 .data_type = k_var_dtype_i32, \
36 #define VG_VAR_I32( NAME ) \
37 vg_var_push( (struct vg_var){ \
40 .data_type = k_var_dtype_i32, \
43 typedef struct vg_var vg_var
;
44 typedef struct vg_cmd vg_cmd
;
77 int persistent
; /* Should this var be stored to cfg/auto.conf? */
83 int (*function
)( int argc
, char const *argv
[] );
84 void (*poll_suggest
)( int argc
, char const *argv
[] );
98 int suggestion_select
,
102 u32 var_count
, function_count
;
106 int cursor_user
, cursor_pos
, string_length
;
108 char history
[32][96];
109 int history_last
, history_pos
, history_count
;
115 VG_STATIC
void vg_var_push( struct vg_var cv
);
116 VG_STATIC
void vg_function_push( struct vg_cmd cmd
);
118 VG_STATIC
void _vg_console_draw( void );
119 void _vg_console_println( const char *str
);
120 VG_STATIC
int _vg_console_list( int argc
, char const *argv
[] );
121 VG_STATIC
void _vg_console_init(void);
122 VG_STATIC
void _vg_console_write_persistent(void);
123 VG_STATIC
void _vg_console_free(void);
124 VG_STATIC
void vg_execute_console_input( const char *cmd
);
129 VG_STATIC
void console_make_selection( int* start
, int* end
);
130 VG_STATIC
void console_move_cursor( int* cursor0
, int* cursor1
,
131 int dir
, int snap_together
);
132 VG_STATIC
int console_makeroom( int datastart
, int length
);
133 VG_STATIC
int console_delete_char( int direction
);
134 VG_STATIC
void console_to_clipboard(void);
135 VG_STATIC
void console_clipboard_paste(void);
136 VG_STATIC
void console_put_char( char c
);
137 VG_STATIC
void console_history_get( char* buf
, int entry_num
);
138 VG_STATIC
int _vg_console_enabled(void);
139 VG_STATIC
void console_proc_key( SDL_Keysym ev
);
144 VG_STATIC
int _vg_console_enabled(void)
146 return vg_console
.enabled
;
149 VG_STATIC
void vg_var_push( vg_var cv
)
151 if( vg_console
.var_count
> vg_list_size(vg_console
.vars
) )
152 vg_fatal_exit_loop( "Too many vars registered" );
154 vg_info( "Console variable '%s' registered\n", cv
.name
);
155 vg_console
.vars
[ vg_console
.var_count
++ ] = cv
;
158 VG_STATIC
void vg_function_push( struct vg_cmd cmd
)
160 if( vg_console
.function_count
> vg_list_size(vg_console
.functions
) )
161 vg_fatal_exit_loop( "Too many functions registered" );
163 vg_console
.functions
[ vg_console
.function_count
++ ] = cmd
;
166 VG_STATIC
void _vg_console_draw( void )
168 if( !vg_console
.enabled
)
171 SDL_AtomicLock( &log_print_sl
);
173 int ptr
= vg_log
.buffer_line_current
;
176 int console_lines
= VG_MIN( log_lines
, vg_log
.buffer_line_count
);
178 vg_uictx
.cursor
[0] = 0;
179 vg_uictx
.cursor
[1] = 0;
180 vg_uictx
.cursor
[3] = log_lines
*fh
;
188 ui_fill_rect( vg_uictx
.cursor
, 0x77181818 );
190 vg_uictx
.cursor
[3] = fh
;
193 for( int i
=0; i
<console_lines
; i
++ )
198 ptr
= vg_list_size( vg_log
.buffer
)-1;
200 ui_text( vg_uictx
.cursor
, vg_log
.buffer
[ptr
], 1, 0 );
201 vg_uictx
.cursor
[1] -= fh
;
209 vg_uictx
.cursor
[1] += 2;
210 vg_uictx
.cursor
[3] = fh
;
214 ui_fill_rect( vg_uictx
.cursor
, 0x77111111 );
215 ui_text( vg_uictx
.cursor
, vg_console
.input
, 1, 0 );
217 int start
= VG_MIN( vg_console
.cursor_pos
, vg_console
.cursor_user
),
218 end
= VG_MAX( vg_console
.cursor_pos
, vg_console
.cursor_user
);
220 vg_uictx
.cursor
[0] = start
* UI_GLYPH_SPACING_X
;
221 vg_uictx
.cursor
[2] = (start
== end
? 0.5f
: (float)(end
-start
))
222 * (float)UI_GLYPH_SPACING_X
;
224 ui_fill_rect( vg_uictx
.cursor
, 0x66ffffff );
230 if( vg_console
.suggestion_count
)
232 vg_uictx
.cursor
[0] += UI_GLYPH_SPACING_X
* vg_console
.suggestion_pastepos
;
233 vg_uictx
.cursor
[1] += 2;
234 vg_uictx
.cursor
[3] = vg_console
.suggestion_count
* fh
;
235 vg_uictx
.cursor
[2] = UI_GLYPH_SPACING_X
* vg_console
.suggestion_maxlen
;
239 ui_fill_rect( vg_uictx
.cursor
, 0x77040404 );
241 vg_uictx
.cursor
[3] = fh
;
242 for( int i
=0; i
<vg_console
.suggestion_count
; i
++ )
244 if( i
== vg_console
.suggestion_select
)
245 ui_fill_rect( vg_uictx
.cursor
, 0x66a0e508 );
247 ui_text( vg_uictx
.cursor
, vg_console
.suggestions
[i
].str
, 1, 0 );
248 vg_uictx
.cursor
[1] += fh
;
254 SDL_AtomicUnlock( &log_print_sl
);
257 VG_STATIC
int _vg_console_list( int argc
, char const *argv
[] )
259 for( int i
=0; i
<vg_console
.function_count
; i
++ )
261 struct vg_cmd
*cmd
= &vg_console
.functions
[ i
];
262 vg_info( "* %s\n", cmd
->name
);
265 for( int i
=0; i
<vg_console
.var_count
; i
++ )
267 struct vg_var
*cv
= &vg_console
.vars
[ i
];
268 vg_info( "%s\n", cv
->name
);
274 int _test_break( int argc
, const char *argv
[] )
276 vg_fatal_exit_loop( "Test crash from main, after loading (console)" );
280 VG_STATIC
void _vg_console_init(void)
282 vg_function_push( (struct vg_cmd
)
285 .function
= _vg_console_list
288 vg_function_push( (struct vg_cmd
)
291 .function
= _test_break
295 VG_STATIC
void vg_console_load_autos(void)
297 /* Read and exec persistent commands */
298 FILE *fp
= fopen( "cfg/auto.conf", "r" );
303 while( fgets( line
, sizeof( line
), fp
) )
305 line
[ strcspn( line
, "\r\n#" ) ] = 0x00;
307 if( line
[0] != 0x00 )
309 vg_execute_console_input( line
);
317 VG_STATIC
void _vg_console_write_persistent(void)
319 FILE *fp
= fopen( "cfg/auto.conf", "w" );
321 for( int i
=0; i
<vg_console
.var_count
; i
++ )
323 struct vg_var
*cv
= &vg_console
.vars
[i
];
327 switch( cv
->data_type
)
329 case k_var_dtype_i32
:
330 fprintf( fp
, "%s %d\n", cv
->name
, *(i32
*)(cv
->data
) );
332 case k_var_dtype_u32
:
333 fprintf( fp
, "%s %u\n", cv
->name
, *(u32
*)(cv
->data
) );
335 case k_var_dtype_f32
:
336 fprintf( fp
, "%s %.5f\n", cv
->name
, *(float *)(cv
->data
) );
345 VG_STATIC
void _vg_console_free(void)
347 _vg_console_write_persistent();
351 * splits src into tokens and fills out args as pointers to those tokens
352 * returns number of tokens
353 * dst must be as long as src
355 VG_STATIC
int vg_console_tokenize( const char *src
, char *dst
,
356 const char *args
[8] )
361 for( int i
=0; 1; i
++ )
365 if( src
[i
] == ' ' || src
[i
] == '\t' )
381 args
[ arg_count
++ ] = &dst
[i
];
396 VG_STATIC vg_var
*vg_console_match_var( const char *kw
)
398 for( int i
=0; i
<vg_console
.var_count
; i
++ )
400 struct vg_var
*cv
= &vg_console
.vars
[ i
];
401 if( !strcmp( cv
->name
, kw
) )
410 VG_STATIC vg_cmd
*vg_console_match_cmd( const char *kw
)
412 for( int i
=0; i
<vg_console
.function_count
; i
++ )
414 struct vg_cmd
*cmd
= &vg_console
.functions
[ i
];
415 if( !strcmp( cmd
->name
, kw
) )
424 VG_STATIC
void vg_execute_console_input( const char *cmd
)
428 int arg_count
= vg_console_tokenize( cmd
, temp
, args
);
436 vg_var
*cv
= vg_console_match_var( args
[0] );
437 vg_cmd
*fn
= vg_console_match_cmd( args
[0] );
439 assert( !(cv
&& fn
) );
443 /* Cvar Matched, try get value */
446 if( (cv
->data_type
== k_var_dtype_u32
) ||
447 (cv
->data_type
== k_var_dtype_i32
) )
449 data_int
= atoi( args
[1] );
451 *((int *)cv
->data
) = cv
->opt_i32
.clamp
?
452 VG_MIN( VG_MAX(data_int
, cv
->opt_i32
.min
), cv
->opt_i32
.max
):
455 else if( cv
->data_type
== k_var_dtype_f32
)
457 data_float
= atof( args
[1] );
458 *((float *)cv
->data
) = cv
->opt_f32
.clamp
?
459 vg_minf( vg_maxf( data_float
, cv
->opt_f32
.min
),
466 if( cv
->data_type
== k_var_dtype_i32
)
467 vg_info( "= %d\n", *((int *)cv
->data
) );
468 else if( cv
->data_type
== k_var_dtype_u32
)
469 vg_info( "= %u\n", *((u32
*)cv
->data
) );
470 else if( cv
->data_type
== k_var_dtype_f32
)
471 vg_info( "= %.4f\n", *((float *)cv
->data
) );
478 fn
->function( arg_count
-1, args
+1 );
482 vg_error( "No command/var named '%s'. Use 'list' to view all\n", args
[0] );
485 u32
str_lev_distance( const char *s1
, const char *s2
)
487 u32 m
= strlen( s1
),
493 assert( n
+1 <= 256 );
497 for( u32 k
=0; k
<=n
; k
++ )
501 for( u32 i
=0; i
<m
; i
++ )
507 for( u32 j
=0; j
<n
; j
++ )
509 u32 upper
= costs
[j
+1];
512 costs
[ j
+1 ] = corner
;
515 u32 t
= (upper
< corner
)? upper
: corner
;
516 costs
[j
+1] = ((costs
[j
] < t
)? costs
[j
]: t
) + 1;
526 u32
str_lcs( const char *s1
, const char *s2
)
528 u32 m
= VG_MIN( 31, strlen( s1
) ),
529 n
= VG_MIN( 31, strlen( s2
) );
534 for( int i
=0; i
<=m
; i
++ )
536 for( int j
=0; j
<=n
; j
++ )
538 if( i
== 0 || j
== 0 )
540 else if( s1
[i
-1] == s2
[j
-1] )
542 suff
[i
][j
] = suff
[i
-1][j
-1] + 1;
543 result
= VG_MAX( result
, suff
[i
][j
] );
553 /* str must not fuckoff ever! */
554 VG_STATIC
void console_suggest_score_text( const char *str
, const char *input
,
557 /* filter duplicates */
558 for( int i
=0; i
<vg_console
.suggestion_count
; i
++ )
559 if( !strcmp( vg_console
.suggestions
[i
].str
, str
) )
563 u32 score
= str_lcs( str
, input
);
565 if( score
< minscore
)
568 int best_pos
= vg_console
.suggestion_count
;
569 for( int j
=best_pos
-1; j
>=0; j
-- )
570 if( score
> vg_console
.suggestions
[j
].lev_score
)
573 /* insert if good score */
574 if( best_pos
< vg_list_size( vg_console
.suggestions
) )
576 int start
= VG_MIN( vg_console
.suggestion_count
,
577 vg_list_size( vg_console
.suggestions
)-1 );
578 for( int j
=start
; j
>best_pos
; j
-- )
579 vg_console
.suggestions
[j
] = vg_console
.suggestions
[j
-1];
581 vg_console
.suggestions
[ best_pos
].str
= str
;
582 vg_console
.suggestions
[ best_pos
].len
= strlen( str
);
583 vg_console
.suggestions
[ best_pos
].lev_score
= score
;
585 if( vg_console
.suggestion_count
<
586 vg_list_size( vg_console
.suggestions
) )
587 vg_console
.suggestion_count
++;
591 VG_STATIC
void console_update_suggestions(void)
593 vg_console
.suggestion_count
= 0;
594 vg_console
.suggestion_select
= -1;
595 vg_console
.suggestion_maxlen
= 0;
598 * - must be typing something
599 * - must be at the end
600 * - prev char must not be a whitespace
601 * - cursors should match
604 if( vg_console
.cursor_pos
== 0 )
607 if( vg_console
.cursor_pos
!= vg_console
.cursor_user
)
610 if( vg_console
.input
[ vg_console
.cursor_pos
] != '\0' )
613 if( (vg_console
.input
[ vg_console
.cursor_pos
-1 ] == ' ') ||
614 (vg_console
.input
[ vg_console
.cursor_pos
-1 ] == '\t') )
620 int token_count
= vg_console_tokenize( vg_console
.input
, temp
, args
);
622 vg_console
.suggestion_pastepos
= args
[token_count
-1]-temp
;
624 /* Score all our commands and cvars */
625 if( token_count
== 1 )
627 for( int i
=0; i
<vg_console
.var_count
; i
++ )
629 vg_var
*cvar
= &vg_console
.vars
[i
];
630 console_suggest_score_text( cvar
->name
, args
[0], 1 );
633 for( int i
=0; i
<vg_console
.function_count
; i
++ )
635 vg_cmd
*cmd
= &vg_console
.functions
[i
];
636 console_suggest_score_text( cmd
->name
, args
[0], 1 );
641 vg_cmd
*cmd
= vg_console_match_cmd( args
[0] );
642 vg_var
*var
= vg_console_match_var( args
[0] );
644 assert( !( cmd
&& var
) );
647 if( cmd
->poll_suggest
)
648 cmd
->poll_suggest( token_count
-1, &args
[1] );
651 /* some post processing */
652 for( int i
=0; i
<vg_console
.suggestion_count
; i
++ )
654 vg_console
.suggestion_maxlen
= VG_MAX( vg_console
.suggestion_maxlen
,
655 vg_console
.suggestions
[i
].len
);
657 if( vg_console
.suggestions
[i
].lev_score
<
658 vg_console
.suggestions
[0].lev_score
/2 )
660 vg_console
.suggestion_count
= i
;
669 VG_STATIC
void console_make_selection( int* start
, int* end
)
671 *start
= VG_MIN( vg_console
.cursor_pos
, vg_console
.cursor_user
);
672 *end
= VG_MAX( vg_console
.cursor_pos
, vg_console
.cursor_user
);
675 VG_STATIC
void console_move_cursor( int* cursor0
, int* cursor1
,
676 int dir
, int snap_together
)
678 *cursor0
= VG_MAX( 0, vg_console
.cursor_user
+ dir
);
681 VG_MIN( vg_list_size(vg_console
.input
)-1, strlen( vg_console
.input
)),
688 VG_STATIC
int console_makeroom( int datastart
, int length
)
690 int move_to
= VG_MIN( datastart
+length
, vg_list_size( vg_console
.input
)-1 );
691 int move_amount
= strlen( vg_console
.input
)-datastart
;
693 VG_MIN( move_to
+move_amount
, vg_list_size( vg_console
.input
)-1 );
694 move_amount
= move_end
-move_to
;
697 memmove( &vg_console
.input
[ move_to
],
698 &vg_console
.input
[ datastart
],
701 vg_console
.input
[ move_end
] = '\0';
703 return VG_MIN( length
, vg_list_size( vg_console
.input
)-datastart
-1 );
706 VG_STATIC
int console_delete_char( int direction
)
709 console_make_selection( &start
, &end
);
711 /* There is no selection */
714 if( direction
== 1 ) end
= VG_MIN( end
+1, strlen( vg_console
.input
) );
715 else if( direction
== -1 ) start
= VG_MAX( start
-1, 0 );
718 /* Still no selction, no need to do anything */
722 /* Copy the end->terminator to start */
723 int remaining_length
= strlen( vg_console
.input
)+1-end
;
724 memmove( &vg_console
.input
[ start
],
725 &vg_console
.input
[ end
],
730 VG_STATIC
void console_to_clipboard(void)
733 console_make_selection( &start
, &end
);
738 memcpy( buffer
, &vg_console
.input
[ start
], end
-start
);
739 buffer
[ end
-start
] = 0x00;
740 SDL_SetClipboardText( buffer
);
744 VG_STATIC
void console_clipboard_paste(void)
746 if( !SDL_HasClipboardText() )
749 char *text
= SDL_GetClipboardText();
754 int datastart
= console_delete_char( 0 );
755 int length
= strlen( text
);
756 int cpylength
= console_makeroom( datastart
, length
);
758 memcpy( vg_console
.input
+ datastart
, text
, cpylength
);
759 console_move_cursor( &vg_console
.cursor_user
,
760 &vg_console
.cursor_pos
, cpylength
, 1 );
763 console_update_suggestions();
766 VG_STATIC
void console_put_char( char c
)
768 if( !vg_console
.enabled
)
771 vg_console
.cursor_user
= console_delete_char(0);
773 if( console_makeroom( vg_console
.cursor_user
, 1 ) )
774 vg_console
.input
[ vg_console
.cursor_user
] = c
;
776 console_move_cursor( &vg_console
.cursor_user
, &vg_console
.cursor_pos
, 1, 1 );
779 VG_STATIC
void console_history_get( char* buf
, int entry_num
)
781 if( !vg_console
.history_count
)
784 int offset
= VG_MIN( entry_num
, vg_console
.history_count
-1 ),
785 pick
= (vg_console
.history_last
- offset
) %
786 vg_list_size( vg_console
.history
);
787 strcpy( buf
, vg_console
.history
[ pick
] );
790 /* Receed secondary cursor */
791 VG_STATIC
void _console_left_select(void)
793 console_move_cursor( &vg_console
.cursor_user
, NULL
, -1, 0 );
796 /* Match and receed both cursors */
797 VG_STATIC
void _console_left(void)
799 int cursor_diff
= vg_console
.cursor_pos
- vg_console
.cursor_user
? 0: 1;
801 console_move_cursor( &vg_console
.cursor_user
,
802 &vg_console
.cursor_pos
, -cursor_diff
, 1 );
805 VG_STATIC
void _console_right_select(void)
807 console_move_cursor( &vg_console
.cursor_user
, NULL
, 1, 0 );
810 VG_STATIC
void _console_right(void)
812 int cursor_diff
= vg_console
.cursor_pos
- vg_console
.cursor_user
? 0: 1;
814 console_move_cursor( &vg_console
.cursor_user
,
815 &vg_console
.cursor_pos
, +cursor_diff
, 1 );
818 VG_STATIC
void _console_down(void)
820 vg_console
.history_pos
= VG_MAX( 0, vg_console
.history_pos
-1 );
821 console_history_get( vg_console
.input
, vg_console
.history_pos
);
823 console_move_cursor( &vg_console
.cursor_user
,
824 &vg_console
.cursor_pos
,
825 vg_list_size(vg_console
.input
)-1, 1 );
828 VG_STATIC
void _console_up(void)
830 vg_console
.history_pos
= VG_MAX
835 vg_console
.history_pos
+1,
838 vg_list_size( vg_console
.history
),
839 vg_console
.history_count
- 1
844 console_history_get( vg_console
.input
, vg_console
.history_pos
);
845 console_move_cursor( &vg_console
.cursor_user
,
846 &vg_console
.cursor_pos
,
847 vg_list_size(vg_console
.input
)-1, 1);
850 VG_STATIC
void _console_backspace(void)
852 vg_console
.cursor_user
= console_delete_char( -1 );
853 vg_console
.cursor_pos
= vg_console
.cursor_user
;
855 console_update_suggestions();
858 VG_STATIC
void _console_delete(void)
860 vg_console
.cursor_user
= console_delete_char( 1 );
861 vg_console
.cursor_pos
= vg_console
.cursor_user
;
863 console_update_suggestions();
866 VG_STATIC
void _console_home_select(void)
868 console_move_cursor( &vg_console
.cursor_user
, NULL
, -10000, 0 );
871 VG_STATIC
void _console_home(void)
873 console_move_cursor( &vg_console
.cursor_user
,
874 &vg_console
.cursor_pos
, -10000, 1 );
877 VG_STATIC
void _console_end_select(void)
879 console_move_cursor( &vg_console
.cursor_user
, NULL
, 10000, 0 );
882 VG_STATIC
void _console_end(void)
884 console_move_cursor( &vg_console
.cursor_user
,
885 &vg_console
.cursor_pos
,
886 vg_list_size(vg_console
.input
)-1, 1 );
889 VG_STATIC
void _console_select_all(void)
891 console_move_cursor( &vg_console
.cursor_user
, NULL
, 10000, 0);
892 console_move_cursor( &vg_console
.cursor_pos
, NULL
, -10000, 0);
895 VG_STATIC
void _console_cut(void)
897 console_to_clipboard();
898 vg_console
.cursor_user
= console_delete_char(0);
899 vg_console
.cursor_pos
= vg_console
.cursor_user
;
902 VG_STATIC
void _console_enter(void)
904 if( !strlen( vg_console
.input
) )
907 vg_info( "%s\n", vg_console
.input
);
909 if( strcmp( vg_console
.input
,
910 vg_console
.history
[ vg_console
.history_last
]) )
912 vg_console
.history_last
= ( vg_console
.history_last
+ 1) %
913 vg_list_size(vg_console
.history
);
914 vg_console
.history_count
=
915 VG_MIN( vg_list_size( vg_console
.history
),
916 vg_console
.history_count
+ 1 );
917 strcpy( vg_console
.history
[ vg_console
.history_last
],
921 vg_console
.history_pos
= -1;
922 vg_execute_console_input( vg_console
.input
);
923 console_move_cursor( &vg_console
.cursor_user
,
924 &vg_console
.cursor_pos
, -10000, 1 );
925 vg_console
.input
[0] = '\0';
927 console_update_suggestions();
931 * Suggestion controls
933 VG_STATIC
void _console_fetch_suggestion(void)
935 char *target
= &vg_console
.input
[ vg_console
.suggestion_pastepos
];
937 if( vg_console
.suggestion_select
== -1 )
939 strcpy( target
, vg_console
.input_copy
);
940 console_move_cursor( &vg_console
.cursor_user
,
941 &vg_console
.cursor_pos
, 10000, 1 );
946 vg_console
.suggestions
[ vg_console
.suggestion_select
].str
,
947 vg_list_size( vg_console
.input
)-1 );
949 console_move_cursor( &vg_console
.cursor_user
,
950 &vg_console
.cursor_pos
, 10000, 1 );
951 console_put_char( ' ' );
955 VG_STATIC
void _console_suggest_store_normal(void)
957 if( vg_console
.suggestion_select
== -1 )
959 char *target
= &vg_console
.input
[ vg_console
.suggestion_pastepos
];
960 strcpy( vg_console
.input_copy
, target
);
964 VG_STATIC
void _console_suggest_next(void)
966 if( vg_console
.suggestion_count
)
968 _console_suggest_store_normal();
970 vg_console
.suggestion_select
++;
972 if( vg_console
.suggestion_select
>= vg_console
.suggestion_count
)
973 vg_console
.suggestion_select
= -1;
975 _console_fetch_suggestion();
979 VG_STATIC
void _console_suggest_prev(void)
981 if( vg_console
.suggestion_count
)
983 _console_suggest_store_normal();
985 vg_console
.suggestion_select
--;
987 if( vg_console
.suggestion_select
< -1 )
988 vg_console
.suggestion_select
= vg_console
.suggestion_count
-1;
990 _console_fetch_suggestion();
997 VG_STATIC
void console_proc_key( SDL_Keysym ev
)
999 /* Open / close console */
1000 if( ev
.sym
== SDLK_BACKQUOTE
)
1002 vg_console
.enabled
= !vg_console
.enabled
;
1004 if( vg_console
.enabled
)
1005 SDL_StartTextInput();
1007 SDL_StopTextInput();
1010 if( !vg_console
.enabled
) return;
1012 struct console_mapping
1017 void (*handler
)(void);
1021 { 0, SDLK_LEFT
, _console_left
},
1022 { KMOD_SHIFT
, SDLK_LEFT
, _console_left_select
},
1023 { 0, SDLK_RIGHT
, _console_right
},
1024 { KMOD_SHIFT
, SDLK_RIGHT
, _console_right_select
},
1025 { 0, SDLK_DOWN
, _console_down
},
1026 { 0, SDLK_UP
, _console_up
},
1027 { 0, SDLK_BACKSPACE
, _console_backspace
},
1028 { 0, SDLK_DELETE
, _console_delete
},
1029 { 0, SDLK_HOME
, _console_home
},
1030 { KMOD_SHIFT
, SDLK_HOME
, _console_home_select
},
1031 { 0, SDLK_END
, _console_end
},
1032 { KMOD_SHIFT
, SDLK_END
, _console_end_select
},
1033 { KMOD_CTRL
, SDLK_a
, _console_select_all
},
1034 { KMOD_CTRL
, SDLK_c
, console_to_clipboard
},
1035 { KMOD_CTRL
, SDLK_x
, _console_cut
},
1036 { KMOD_CTRL
, SDLK_v
, console_clipboard_paste
},
1037 { 0, SDLK_RETURN
, _console_enter
},
1038 { KMOD_CTRL
, SDLK_n
, _console_suggest_next
},
1039 { KMOD_CTRL
, SDLK_p
, _console_suggest_prev
}
1044 if( ev
.mod
& KMOD_SHIFT
)
1047 if( ev
.mod
& KMOD_CTRL
)
1050 if( ev
.mod
& KMOD_ALT
)
1053 for( int i
=0; i
<vg_list_size( mappings
); i
++ )
1055 struct console_mapping
*mapping
= &mappings
[i
];
1057 if( mapping
->key
== ev
.sym
)
1059 if( mapping
->mod
== 0 )
1067 else if( (mod
& mapping
->mod
) == mapping
->mod
)
1077 * Callback for text entry mode
1079 VG_STATIC
void console_proc_utf8( const char *text
)
1081 const char *ptr
= text
;
1086 console_put_char( *ptr
);
1090 console_update_suggestions();
1093 #endif /* VG_CONSOLE_H */