@ -148,6 +148,8 @@
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
// STB_TEXTEDIT_K_UP keyboard input to move cursor up
// STB_TEXTEDIT_K_UP keyboard input to move cursor up
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
@ -170,10 +172,6 @@
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
//
//
// Todo:
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
//
// Keyboard input must be encoded as a single integer value; e.g. a character code
// Keyboard input must be encoded as a single integer value; e.g. a character code
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
@ -337,6 +335,10 @@ typedef struct
// each textfield keeps its own insert mode state. to keep an app-wide
// each textfield keeps its own insert mode state. to keep an app-wide
// insert mode, copy this value in/out of the app state
// insert mode, copy this value in/out of the app state
int row_count_per_page ;
// page size in number of row.
// this value MUST be set to >0 for pageup or pagedown in multilines documents.
/////////////////////
/////////////////////
//
//
// private data
// private data
@ -855,12 +857,16 @@ retry:
break ;
break ;
case STB_TEXTEDIT_K_DOWN :
case STB_TEXTEDIT_K_DOWN :
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT : {
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT :
case STB_TEXTEDIT_K_PGDOWN :
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT : {
StbFindState find ;
StbFindState find ;
StbTexteditRow row ;
StbTexteditRow row ;
int i , sel = ( key & STB_TEXTEDIT_K_SHIFT ) ! = 0 ;
int i , j , sel = ( key & STB_TEXTEDIT_K_SHIFT ) ! = 0 ;
int is_page = ( key & ~ STB_TEXTEDIT_K_SHIFT ) = = STB_TEXTEDIT_K_PGDOWN ;
int row_count = is_page ? state - > row_count_per_page : 1 ;
if ( state - > single_line ) {
if ( ! is_page & & state - > single_line ) {
// on windows, up&down in single-line behave like left&right
// on windows, up&down in single-line behave like left&right
key = STB_TEXTEDIT_K_RIGHT | ( key & STB_TEXTEDIT_K_SHIFT ) ;
key = STB_TEXTEDIT_K_RIGHT | ( key & STB_TEXTEDIT_K_SHIFT ) ;
goto retry ;
goto retry ;
@ -875,17 +881,19 @@ retry:
stb_textedit_clamp ( str , state ) ;
stb_textedit_clamp ( str , state ) ;
stb_textedit_find_charpos ( & find , str , state - > cursor , state - > single_line ) ;
stb_textedit_find_charpos ( & find , str , state - > cursor , state - > single_line ) ;
// now find character position down a row
for ( j = 0 ; j < row_count ; + + j ) {
if ( find . length ) {
float x , goal_x = state - > has_preferred_x ? state - > preferred_x : find . x ;
int start = find . first_char + find . length ;
if ( find . length = = 0 )
break ;
// [DEAR IMGUI]
// [DEAR IMGUI]
// going down while being on the last line shouldn't bring us to that line end
// going down while being on the last line shouldn't bring us to that line end
if ( STB_TEXTEDIT_GETCHAR ( str , find . first_char + find . length - 1 ) ! = STB_TEXTEDIT_NEWLINE )
if ( STB_TEXTEDIT_GETCHAR ( str , find . first_char + find . length - 1 ) ! = STB_TEXTEDIT_NEWLINE )
break ;
break ;
float goal_x = state - > has_preferred_x ? state - > preferred_x : find . x ;
// now find character position down a row
float x ;
int start = find . first_char + find . length ;
state - > cursor = start ;
state - > cursor = start ;
STB_TEXTEDIT_LAYOUTROW ( & row , str , state - > cursor ) ;
STB_TEXTEDIT_LAYOUTROW ( & row , str , state - > cursor ) ;
x = row . x0 ;
x = row . x0 ;
@ -907,17 +915,25 @@ retry:
if ( sel )
if ( sel )
state - > select_end = state - > cursor ;
state - > select_end = state - > cursor ;
// go to next line
find . first_char = find . first_char + find . length ;
find . length = row . num_chars ;
}
}
break ;
break ;
}
}
case STB_TEXTEDIT_K_UP :
case STB_TEXTEDIT_K_UP :
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT : {
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT :
case STB_TEXTEDIT_K_PGUP :
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT : {
StbFindState find ;
StbFindState find ;
StbTexteditRow row ;
StbTexteditRow row ;
int i , sel = ( key & STB_TEXTEDIT_K_SHIFT ) ! = 0 ;
int i , j , prev_scan , sel = ( key & STB_TEXTEDIT_K_SHIFT ) ! = 0 ;
int is_page = ( key & ~ STB_TEXTEDIT_K_SHIFT ) = = STB_TEXTEDIT_K_PGUP ;
int row_count = is_page ? state - > row_count_per_page : 1 ;
if ( state - > single_line ) {
if ( ! is_page & & state - > single_line ) {
// on windows, up&down become left&right
// on windows, up&down become left&right
key = STB_TEXTEDIT_K_LEFT | ( key & STB_TEXTEDIT_K_SHIFT ) ;
key = STB_TEXTEDIT_K_LEFT | ( key & STB_TEXTEDIT_K_SHIFT ) ;
goto retry ;
goto retry ;
@ -932,11 +948,14 @@ retry:
stb_textedit_clamp ( str , state ) ;
stb_textedit_clamp ( str , state ) ;
stb_textedit_find_charpos ( & find , str , state - > cursor , state - > single_line ) ;
stb_textedit_find_charpos ( & find , str , state - > cursor , state - > single_line ) ;
for ( j = 0 ; j < row_count ; + + j ) {
float x , goal_x = state - > has_preferred_x ? state - > preferred_x : find . x ;
// can only go up if there's a previous row
// can only go up if there's a previous row
if ( find . prev_first ! = find . first_char ) {
if ( find . prev_first = = find . first_char )
break ;
// now find character position up a row
// now find character position up a row
float goal_x = state - > has_preferred_x ? state - > preferred_x : find . x ;
float x ;
state - > cursor = find . prev_first ;
state - > cursor = find . prev_first ;
STB_TEXTEDIT_LAYOUTROW ( & row , str , state - > cursor ) ;
STB_TEXTEDIT_LAYOUTROW ( & row , str , state - > cursor ) ;
x = row . x0 ;
x = row . x0 ;
@ -958,6 +977,14 @@ retry:
if ( sel )
if ( sel )
state - > select_end = state - > cursor ;
state - > select_end = state - > cursor ;
// go to previous line
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
prev_scan = find . prev_first > 0 ? find . prev_first - 1 : 0 ;
while ( prev_scan > 0 & & STB_TEXTEDIT_GETCHAR ( str , prev_scan - 1 ) ! = STB_TEXTEDIT_NEWLINE )
- - prev_scan ;
find . first_char = find . prev_first ;
find . prev_first = prev_scan ;
}
}
break ;
break ;
}
}
@ -1081,10 +1108,6 @@ retry:
state - > has_preferred_x = 0 ;
state - > has_preferred_x = 0 ;
break ;
break ;
}
}
// @TODO:
// STB_TEXTEDIT_K_PGUP - move cursor up a page
// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
}
}
}
}
@ -1356,6 +1379,7 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
state - > initialized = 1 ;
state - > initialized = 1 ;
state - > single_line = ( unsigned char ) is_single_line ;
state - > single_line = ( unsigned char ) is_single_line ;
state - > insert_mode = 0 ;
state - > insert_mode = 0 ;
state - > row_count_per_page = 0 ;
}
}
// API initialize
// API initialize