From 2026f6fe648696888762c5b10210191748a6c9de Mon Sep 17 00:00:00 2001 From: hgn Date: Tue, 2 May 2023 15:27:16 +0100 Subject: [PATCH] textbox improvements --- src/fonts/vg_font_thin.png | Bin 4703 -> 8387 bytes vg_imgui.h | 445 +++++++++++++++++++++++++++++++------ vg_pxfont_thin.h | 14 +- 3 files changed, 380 insertions(+), 79 deletions(-) diff --git a/src/fonts/vg_font_thin.png b/src/fonts/vg_font_thin.png index 1239679df0b8f9b88bac51089a558fd557404200..0c661970f11289eb45919946de610fb1b72827ea 100644 GIT binary patch delta 4281 zcmcgv4R93Y8Qud);Any%V3>%k8*GBOw|jg4YmS8cTyhPE5l##;g?zX7-DR8mb9a-w z#KCKlsvtFh5v&QON@=ko*b<8^FqkxCXlyC8RuIyFO&vg_1g6u9C6Ru+7m|Y#&;+_O zH?#Zh^FGh}KHvL&b9-`j`}}ojQLMe%St2b0VLT)RJ-iR%QdJ1zFv5E!+va51o>~9z`siJ*@K4U# z9%^X~96r^O@zG1YkA9r|6C(9vyw1O^#eXPx7ePWd$k|b#io_(t%dE`_jRmT zT=Y}tedqAa>)v3GwN2Xp%O%k_#!t)He)z4r&VSw0sGmJYQ(s%&*0#3et-3WWJCb+Q z;+IrCXM47sAs+mSn)B|ei=X^@R_}T1`4g&~mJggQ>B(<4!YvIGv`x#V)x9%5J9~WE zkJi2V^F#JU>gK+2JzWC`DW>dP0!PEg~u{cu5bvpMJCjk`-eb1gACd-$HRtO;|5m$e=N~E>+Y4Qji`L;e^Jh+Tf(LBdY%i?V|06xKFSmXL@k-7Pb&6$r zah>|u#kwnPy@7*0f7#MBbs<)BZ`W5T<7)S0Zv)Y;lLvNnv#P#Bts9P9JlfcLF8#9? z>!(}C{O7%zHJ{i2?40VAM_NB=(4_86`;u385Eq`YoqTz0LZIewW7o2$XKkI7{oL;F zbYqFnx0bBldDMEMyQ{nFeed!9er(lD;T8P>5M{FNY}tS0GZkl_+r(5By1iOIe`yJ zd@z6`3=3Sr3du?k=skY5K!3>L7^Dw~13pBNB~%22D6NL3{C+AvMU?U@5z9bDgDLSD zq7!XaY7rEJ6#@tID`7xNi>GjNgZZHf!Kd`&<|yccegqXMZB(PZMzg@~C>~6aP4M#m zkdlV{z6L4ro*}!gDNcT)^b=nRN+0BnLq~_YSI`LNaIkqnu0k%*o@XWG0$6vDP`NqQ78LvdttjsYUPy%kUP2v310s9Q&M&rG2}VOJSS3>I1Cj@2 zScwIEpdvE#!pZyLVhPBGYK>+c&FIZ$lgVJwX=6%C_7W(FXdGouEv?b%m2`P!Skw)& z7RbYDC8C3Uvbh2TQc!RPgFY)EbKr8Sl82gQ9cWj%fduk^1Q9FE=vdmo(u`B9Wes{( zZ=6eOSvn3Mbn~97TcM-!9>OzY%U;NfsDLUZ6x&#f;Zw1v*rShEb`*{)TZ08$tO*fR zLbp;V;)=cE%0R#i(J3-8vsdH%b>k3~=fPzHdM%?fk|t;}kb0BFK$;o1mNWyS)8RovHPA98 zA0AhG&ZPdwl}rT?ciN!5SPY$F=v1TzkHrDkP{B99K>v%v=rgLW`cl^8=p!t_RaB6NWn*t*=e0b(9z`aE3YUr)Ht`<$r@|UHrJ!J< zWOw8zo*p+wZKPiKc5f4g-R*C=ph`_HI@viECz4vvO#S}R@2OH|VrTlW=|`|tTMO2n z*wVZe!%kVTLzfShiwy_+`_G;EQ|h1JJ2kd62`k-4kHbn4^PX}{x5itr_WqTomb}S# jsT%%y_mz}Z`bwgI%%#qpUnERL7|fo(FmFdrY3+XjfgKV@ delta 542 zcmV+(0^$9`LEj{hBYy#fX+uL$Nkc;*aB^>EX>4Tx04R}tkvmAkP!xv$rb4OrQsTKu zp+&3*F8AZV=l{9)TtKLonPzpx08O{eR3a{Bva4d?6+R52AAds#%gi$7Bq@oG^>t6( zRCiIH)w%D_>Qi$T1AHQJj2Wg)yg@v(X&apPi9@U?tHkHT6DD1d_>t?1$8VeqE(<&} zWTsQ|#35p_(8fv|v!baHPZLK}O{aVzj(dX-?O#yQueG$u5iqa~TwJ#_We>RA0Y;t-*_2($PfN(> zf%h}|rYtag3-qpeb8DXC^Z`iItdcjt!67hSpzQSy?>16) +#define UI_TEXTBOX_MULTILINE 0x1 +#define UI_TEXTBOX_WRAP 0x2 + struct{ struct ui_vert *vertex_buffer; u16 *indice_buffer; @@ -93,8 +96,13 @@ struct{ k_ui_control_textbox, } focused_control_type; - int cursor_user, cursor_pos, string_length; - u32 textbuf_len; + + struct ui_textbuf{ + int cursor_user, cursor_pos; + u32 len; + u32 flags; + } + textbox; GLuint tex_glyphs, vao, vbo, ebo; @@ -753,7 +761,7 @@ static u32 ui_colourcont( enum ui_scheme_colour id ) else return ui_colour( k_ui_fg+1 ); } -static void ui_text( ui_rect rect, const char *str, ui_px scale, +static u32 ui_ntext( ui_rect rect, const char *str, u32 len, ui_px scale, enum ui_align align, u32 colour ) { ui_rect text_cursor; @@ -769,6 +777,8 @@ static void ui_text( ui_rect rect, const char *str, ui_px scale, text_cursor[2] = 8*scale; text_cursor[3] = 14*scale; + u32 printed_chars = 0; + if( align & (k_ui_align_middle|k_ui_align_bottom) ){ ui_px height = ui_text_string_height( str ) * scale; @@ -779,17 +789,42 @@ static void ui_text( ui_rect rect, const char *str, ui_px scale, } while( (c = *(_c ++)) ){ + if( printed_chars >= len ){ + printed_chars = 0; + text_cursor[1] += 14*scale; + text_cursor[0] = ui_text_aligned_x( _c, rect, scale, align ); + text_cursor[0] -= UI_GLYPH_SPACING_X*scale; + + u8 glyph_base[2]; + u8 glyph_index = '\x90'; + glyph_base[0] = glyph_index & 0xf; + glyph_base[1] = (glyph_index-glyph_base[0])>>4; + glyph_base[0] *= 8; + glyph_base[1] *= 8; + + ui_fill_rect( text_cursor, 0x00ffffff, (ui_px[4]) + { + glyph_base[0]+2, + glyph_base[1]+1, + glyph_base[0]+6, + glyph_base[1]+8 + }); + + text_cursor[0] += UI_GLYPH_SPACING_X*scale; + } + if( c == '\n' ){ text_cursor[1] += 14*scale; text_cursor[0] = ui_text_aligned_x( _c, rect, scale, align ); + printed_chars = 0; continue; } - else if( c >= 33 ){ + else + if( c >= 33 ){ u8 glyph_base[2]; u8 glyph_index = c; glyph_base[0] = glyph_index & 0xf; glyph_base[1] = (glyph_index-glyph_base[0])>>4; - glyph_base[0] *= 8; glyph_base[1] *= 8; @@ -842,11 +877,21 @@ static void ui_text( ui_rect rect, const char *str, ui_px scale, } else if( c == '\t' ){ text_cursor[0] += UI_GLYPH_SPACING_X*scale*4; + printed_chars += 4; continue; } text_cursor[0] += UI_GLYPH_SPACING_X*scale; + printed_chars ++; } + + return printed_chars; +} + +static void ui_text( ui_rect rect, const char *str, ui_px scale, + enum ui_align align, u32 colour ) +{ + ui_ntext( rect, str, 1024, scale, align, colour ); } static void ui_image( ui_rect rect, GLuint image ) @@ -1026,17 +1071,17 @@ static void ui_dev_colourview(void) */ static void _ui_textbox_make_selection( int *start, int *end ) { - *start = VG_MIN( vg_ui.cursor_pos, vg_ui.cursor_user ); - *end = VG_MAX( vg_ui.cursor_pos, vg_ui.cursor_user ); + *start = VG_MIN( vg_ui.textbox.cursor_pos, vg_ui.textbox.cursor_user ); + *end = VG_MAX( vg_ui.textbox.cursor_pos, vg_ui.textbox.cursor_user ); } static void _ui_textbox_move_cursor( int *cursor0, int *cursor1, int dir, int snap_together ) { - *cursor0 = VG_MAX( 0, vg_ui.cursor_user + dir ); + *cursor0 = VG_MAX( 0, vg_ui.textbox.cursor_user + dir ); *cursor0 = VG_MIN( - VG_MIN( vg_ui.textbuf_len-1, strlen( vg_ui.textbuf )), + VG_MIN( vg_ui.textbox.len-1, strlen( vg_ui.textbuf )), *cursor0 ); if( snap_together ) @@ -1045,10 +1090,9 @@ static void _ui_textbox_move_cursor( int *cursor0, int *cursor1, static int _ui_textbox_makeroom( int datastart, int length ) { - int move_to = VG_MIN( datastart+length, vg_ui.textbuf_len-1 ); + int move_to = VG_MIN( datastart+length, vg_ui.textbox.len-1 ); int move_amount = strlen( vg_ui.textbuf )-datastart; - int move_end = - VG_MIN( move_to+move_amount, vg_ui.textbuf_len-1 ); + int move_end = VG_MIN( move_to+move_amount, vg_ui.textbox.len-1 ); move_amount = move_end-move_to; if( move_amount ) @@ -1058,7 +1102,7 @@ static int _ui_textbox_makeroom( int datastart, int length ) vg_ui.textbuf[ move_end ] = '\0'; - return VG_MIN( length, vg_ui.textbuf_len-datastart-1 ); + return VG_MIN( length, vg_ui.textbox.len-datastart-1 ); } static int _ui_textbox_delete_char( int direction ) @@ -1112,101 +1156,203 @@ static void _ui_textbox_clipboard_paste(void) int cpylength = _ui_textbox_makeroom( datastart, length ); memcpy( vg_ui.textbuf + datastart, text, cpylength); - _ui_textbox_move_cursor( &vg_ui.cursor_user, - &vg_ui.cursor_pos, cpylength, 1 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, cpylength, 1 ); SDL_free( text ); } static void _ui_textbox_put_char( char c ) { - vg_ui.cursor_user = _ui_textbox_delete_char(0); + vg_ui.textbox.cursor_user = _ui_textbox_delete_char(0); - if( _ui_textbox_makeroom( vg_ui.cursor_user, 1 ) ) - vg_ui.textbuf[ vg_ui.cursor_user ] = c; + if( _ui_textbox_makeroom( vg_ui.textbox.cursor_user, 1 ) ) + vg_ui.textbuf[ vg_ui.textbox.cursor_user ] = c; - _ui_textbox_move_cursor( &vg_ui.cursor_user, &vg_ui.cursor_pos, 1, 1 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, 1, 1 ); } /* Receed secondary cursor */ static void _ui_textbox_left_select(void) { - _ui_textbox_move_cursor( &vg_ui.cursor_user, NULL, -1, 0 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, NULL, -1, 0 ); } /* Match and receed both cursors */ static void _ui_textbox_left(void) { - int cursor_diff = vg_ui.cursor_pos - vg_ui.cursor_user? 0: 1; + int cursor_diff = vg_ui.textbox.cursor_pos - vg_ui.textbox.cursor_user? 0: 1; + + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, -cursor_diff, 1 ); +} + +static void _ui_textbox_up(void) +{ + if( vg_ui.textbox.flags & UI_TEXTBOX_MULTILINE ){ + int line_begin = vg_ui.textbox.cursor_user; + + while( line_begin ){ + if( vg_ui.textbuf[ line_begin-1 ] == '\n' ){ + break; + } + + line_begin --; + } + + if( line_begin ){ + int line_above_begin = line_begin-1; + + while( line_above_begin ){ + if( vg_ui.textbuf[ line_above_begin-1 ] == '\n' ){ + break; + } + + line_above_begin --; + } + + int offset = vg_ui.textbox.cursor_user - line_begin, + line_length_above = line_begin - line_above_begin -1; - _ui_textbox_move_cursor( &vg_ui.cursor_user, - &vg_ui.cursor_pos, -cursor_diff, 1 ); + offset = VG_MIN( line_length_above, offset ); + + vg_ui.textbox.cursor_user = line_above_begin+offset; + vg_ui.textbox.cursor_pos = line_above_begin+offset; + } + else{ + vg_ui.textbox.cursor_user = line_begin; + vg_ui.textbox.cursor_pos = line_begin; + } + } + else{ + + } +} + +static void _ui_textbox_down(void) +{ + if( vg_ui.textbox.flags & UI_TEXTBOX_MULTILINE ){ + int line_begin = vg_ui.textbox.cursor_user; + + while( line_begin ){ + if( vg_ui.textbuf[ line_begin-1 ] == '\n' ){ + break; + } + + line_begin --; + } + + int line_below_begin = vg_ui.textbox.cursor_user; + + while(1){ + if( vg_ui.textbuf[ line_below_begin ] == '\0' ){ + vg_ui.textbox.cursor_user = line_below_begin; + vg_ui.textbox.cursor_pos = line_below_begin; + return; + } + + if( vg_ui.textbuf[ line_below_begin ] == '\n' ){ + line_below_begin ++; + break; + } + + line_below_begin ++; + } + + int line_below_end = line_below_begin; + while(1){ + if( vg_ui.textbuf[ line_below_end ] == '\0' || + vg_ui.textbuf[ line_below_end ] == '\n' ){ + line_below_end ++; + break; + } + line_below_end ++; + } + + int offset = vg_ui.textbox.cursor_user - line_begin, + line_length_below = line_below_end - line_below_begin -1; + + offset = VG_MIN( line_length_below, offset ); + + vg_ui.textbox.cursor_user = line_below_begin+offset; + vg_ui.textbox.cursor_pos = line_below_begin+offset; + } + else{ + + } } static void _ui_textbox_right_select(void) { - _ui_textbox_move_cursor( &vg_ui.cursor_user, NULL, 1, 0 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, NULL, 1, 0 ); } static void _ui_textbox_right(void) { - int cursor_diff = vg_ui.cursor_pos - vg_ui.cursor_user? 0: 1; + int cursor_diff = vg_ui.textbox.cursor_pos - vg_ui.textbox.cursor_user? 0: 1; - _ui_textbox_move_cursor( &vg_ui.cursor_user, - &vg_ui.cursor_pos, +cursor_diff, 1 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, +cursor_diff, 1 ); } static void _ui_textbox_backspace(void) { - vg_ui.cursor_user = _ui_textbox_delete_char( -1 ); - vg_ui.cursor_pos = vg_ui.cursor_user; + vg_ui.textbox.cursor_user = _ui_textbox_delete_char( -1 ); + vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user; } static void _ui_textbox_delete(void) { - vg_ui.cursor_user = _ui_textbox_delete_char( 1 ); - vg_ui.cursor_pos = vg_ui.cursor_user; + vg_ui.textbox.cursor_user = _ui_textbox_delete_char( 1 ); + vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user; } static void _ui_textbox_home_select(void) { - _ui_textbox_move_cursor( &vg_ui.cursor_user, NULL, -10000, 0 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, NULL, -10000, 0 ); } static void _ui_textbox_home(void) { - _ui_textbox_move_cursor( &vg_ui.cursor_user, - &vg_ui.cursor_pos, -10000, 1 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, -10000, 1 ); } static void _ui_textbox_end_select(void) { - _ui_textbox_move_cursor( &vg_ui.cursor_user, NULL, 10000, 0 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, NULL, 10000, 0 ); } static void _ui_textbox_end(void) { - _ui_textbox_move_cursor( &vg_ui.cursor_user, - &vg_ui.cursor_pos, - vg_ui.textbuf_len-1, 1 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, + vg_ui.textbox.len-1, 1 ); } static void _ui_textbox_select_all(void) { - _ui_textbox_move_cursor( &vg_ui.cursor_user, NULL, 10000, 0); - _ui_textbox_move_cursor( &vg_ui.cursor_pos, NULL, -10000, 0); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, NULL, 10000, 0); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_pos, NULL, -10000, 0); } static void _ui_textbox_cut(void) { _ui_textbox_to_clipboard(); - vg_ui.cursor_user = _ui_textbox_delete_char(0); - vg_ui.cursor_pos = vg_ui.cursor_user; + vg_ui.textbox.cursor_user = _ui_textbox_delete_char(0); + vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user; } static void _ui_textbox_enter(void) { - if( !strlen( vg_ui.textbuf ) ) - return; + if( vg_ui.focused_control_type == k_ui_control_textbox ){ + if( vg_ui.textbox.flags & UI_TEXTBOX_MULTILINE ){ + _ui_textbox_put_char( '\n' ); + } + else{ + ui_defocus_all(); + } + } } /* @@ -1227,11 +1373,11 @@ static void _ui_proc_key( SDL_Keysym ev ) { KMOD_SHIFT, SDLK_LEFT, _ui_textbox_left_select }, { 0, SDLK_RIGHT, _ui_textbox_right }, { KMOD_SHIFT, SDLK_RIGHT, _ui_textbox_right_select }, -#if 0 { 0, SDLK_DOWN, _ui_textbox_down }, { 0, SDLK_UP, _ui_textbox_up }, -#endif { 0, SDLK_BACKSPACE, _ui_textbox_backspace }, + { KMOD_SHIFT, SDLK_BACKSPACE, _ui_textbox_backspace }, + { KMOD_CTRL, SDLK_BACKSPACE, _ui_textbox_backspace }, { 0, SDLK_DELETE, _ui_textbox_delete }, { 0, SDLK_HOME, _ui_textbox_home }, { KMOD_SHIFT, SDLK_HOME, _ui_textbox_home_select }, @@ -1246,9 +1392,13 @@ static void _ui_proc_key( SDL_Keysym ev ) { KMOD_CTRL, SDLK_n, _ui_textbox_suggest_next }, { KMOD_CTRL, SDLK_p, _ui_textbox_suggest_prev } #endif - { 0, SDLK_ESCAPE, ui_defocus_all } + { 0, SDLK_ESCAPE, ui_defocus_all }, }; + if( vg_ui.focused_control_type == k_ui_control_none ){ + return; + } + SDL_Keymod mod = 0; if( ev.mod & KMOD_SHIFT ) @@ -1310,24 +1460,89 @@ VG_STATIC void ui_proc_utf8( const char *text ) - static void _ui_textbox_cursor_rect( ui_rect text_rect, ui_rect cursor ) { - int start = VG_MIN( vg_ui.cursor_pos, vg_ui.cursor_user ), - end = VG_MAX( vg_ui.cursor_pos, vg_ui.cursor_user ); + int start = VG_MIN( vg_ui.textbox.cursor_pos, vg_ui.textbox.cursor_user ), + end = VG_MAX( vg_ui.textbox.cursor_pos, vg_ui.textbox.cursor_user ); cursor[0] = text_rect[0] + start*UI_GLYPH_SPACING_X-1; cursor[1] = text_rect[1]; cursor[2] = start == end? 2: (float)(end-start)*(float)UI_GLYPH_SPACING_X; - cursor[3] = text_rect[3]; - + cursor[3] = 14; +} + +static void _ui_textbox_calc_index_from_grid( int co[3], int char_width ) +{ + int i[3] = {0,0,0}; + + char c; + while( (c = vg_ui.textbuf[i[2]]) ){ + if( i[1]==co[1] && i[0]>=co[0] ) break; + + if( i[0] >= char_width ){ + i[1] ++; + i[0] = 0; + } + + if( c >= 32 && c <= 126 ){ + i[0] ++; + i[2] ++; + } + else if( c == '\n' ){ + i[1] ++; + + if( i[1] > co[1] ) break; + + i[2] ++; + i[0] = 0; + } + else i[2] ++; + } + + co[0] = i[0]; + co[1] = i[1]; + co[2] = i[2]; +} + +static +void _ui_textbox_index_calc_coords( int co[3], int char_width ) +{ + co[0] = 0; + co[1] = 0; + + char c; + int i=0; + + while( (c = vg_ui.textbuf[i ++]) ){ + if( i > co[2] ) break; + if( co[0] >= char_width ){ + co[1] ++; + co[0] = 0; + } + if( c >= 32 && c <= 126 ) co[0] ++; + else if( c == '\n' ){ + co[1] ++; + co[0] = 0; + } + } } +static int _ui_textbox_run_remaining( int index[3], int char_width ) +{ + int i=0, printed_chars=0; + char c; + while( (c = vg_ui.textbuf[index[2] + (i ++)]) ){ + if( index[0]+i >= char_width ) break; + if( c >= 32 && c <= 126 ) printed_chars ++; + else if( c == '\n' ) break; + } + return printed_chars+1; +} -static int ui_textbox( ui_rect rect, char *buf, u32 len ) +static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags ) { int clickup= ui_click_up(), click = ui_clicking() | clickup, @@ -1342,43 +1557,123 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len ) ui_rect text_rect; rect_copy( rect, text_rect ); - text_rect[3] = 14; + + if( flags & UI_TEXTBOX_MULTILINE ) text_rect[3] = rect[3]-16; + else text_rect[3] = 14; + text_rect[2] -= 16; ui_rect_center( rect, text_rect ); + ui_px char_width = 1024; + + if( flags & UI_TEXTBOX_WRAP ) + char_width = text_rect[2] / UI_GLYPH_SPACING_X; + if( hover ){ vg_ui.cursor = k_ui_cursor_ibeam; } if( vg_ui.focused_control_id == buf ){ ui_fill( rect, col_base ); - ui_text( text_rect, buf, 1, k_ui_align_left, 0 ); + ui_ntext( text_rect, buf, char_width, 1, k_ui_align_left, 0 ); if( (clickup||ui_click_down()) && !target ){ ui_defocus_all(); } else{ vg_ui.focused_control_hit = 1; - if( click && target ){ - ui_px d0 = vg_ui.mouse_click[0] - text_rect[0], - d1 = vg_ui.mouse[0] - text_rect[0]; - - int max = strlen( vg_ui.textbuf ); - - vg_ui.cursor_pos = VG_MAX( 0, VG_MIN( max, d0/UI_GLYPH_SPACING_X )), - vg_ui.cursor_user= VG_MAX( 0, VG_MIN( max, d1/UI_GLYPH_SPACING_X )); + int p0[3] ={ + (vg_ui.mouse_click[0] - text_rect[0]) / UI_GLYPH_SPACING_X, + (vg_ui.mouse_click[1] - text_rect[1]) / 14, + -1 + }, + p1[3] = { + (vg_ui.mouse[0] - text_rect[0]) / UI_GLYPH_SPACING_X, + (vg_ui.mouse[1] - text_rect[1]) / 14, + -1 + }; + + if( flags & UI_TEXTBOX_MULTILINE ){ + _ui_textbox_calc_index_from_grid( p0, char_width ); + _ui_textbox_calc_index_from_grid( p1, char_width ); + + vg_ui.textbox.cursor_pos = p0[2]; + vg_ui.textbox.cursor_user = p1[2]; + } + else{ + int max = strlen( buf ); + vg_ui.textbox.cursor_pos = VG_MAX( 0, VG_MIN( max, p0[0] )), + vg_ui.textbox.cursor_user = VG_MAX( 0, VG_MIN( max, p1[0] )); + } } ui_outline( rect, -2, vg_ui.scheme[ k_ui_orange ] ); ui_rect cursor; - _ui_textbox_cursor_rect( text_rect, cursor ); - rect_copy( cursor, vg_ui.click_fader_end ); - if( (vg_ui.click_fade_opacity<=0.0f) && - ui_clip( rect, cursor, cursor ) ){ - ui_fill( cursor, col_cursor ); + int c0 = vg_ui.textbox.cursor_pos, + c1 = vg_ui.textbox.cursor_user, + start = VG_MIN( c0, c1 ), + end = VG_MAX( c0, c1 ), + chars = end-start; + + if( flags & (UI_TEXTBOX_MULTILINE|UI_TEXTBOX_WRAP) ){ + + int pos[3], remaining = chars; + + pos[2] = start; + _ui_textbox_index_calc_coords( pos, char_width ); + + if( start==end ){ + cursor[0] = text_rect[0] + pos[0]*UI_GLYPH_SPACING_X-1; + cursor[1] = text_rect[1] + pos[1]*14; + cursor[2] = 2; + cursor[3] = 13; + ui_fill( cursor, col_cursor ); + rect_copy( cursor, vg_ui.click_fader_end ); + } + else{ + while( remaining ){ + /* TODO: scan for newlines and stuff + * eol or char_width can have line breaks! */ + + int run = _ui_textbox_run_remaining( pos, char_width ); + run = VG_MIN( run, remaining ); + + cursor[0] = text_rect[0] + pos[0]*UI_GLYPH_SPACING_X-1; + cursor[1] = text_rect[1] + pos[1]*14; + cursor[2] = (float)(run)*(float)UI_GLYPH_SPACING_X; + cursor[3] = 13; + + ui_fill( cursor, col_cursor ); + + remaining -= run; + pos[0] = 0; + pos[1] ++; + pos[2] += run; + } + rect_copy( cursor, vg_ui.click_fader_end ); + } + } + else{ + cursor[0] = text_rect[0] + start*UI_GLYPH_SPACING_X-1; + cursor[1] = text_rect[1]; + cursor[3] = 13; + + if( start==end ){ + cursor[2] = 2; + } + else{ + cursor[2] = (float)(chars)*(float)UI_GLYPH_SPACING_X; + } + + if( (vg_ui.click_fade_opacity<=0.0f) && + ui_clip( rect, cursor, cursor ) ){ + ui_fill( cursor, col_cursor ); + } + + rect_copy( cursor, vg_ui.click_fader_end ); } } @@ -1387,16 +1682,22 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len ) if( click ){ if( target && hover ){ + ui_defocus_all(); + ui_fill( rect, col_highlight ); vg_ui.ignore_input_frames = 2; rect_copy( rect, vg_ui.click_fader ); - _ui_textbox_cursor_rect( text_rect, vg_ui.click_fader_end ); - + rect_copy( rect, vg_ui.click_fader_end ); + vg_ui.click_fade_opacity = 1.0f; vg_ui.textbuf = buf; vg_ui.focused_control_hit = 1; vg_ui.focused_control_type = k_ui_control_textbox; - vg_ui.textbuf_len = len; + vg_ui.textbox.len = len; + vg_ui.textbox.flags = flags; + vg_ui.textbox.cursor_pos = 0; + vg_ui.textbox.cursor_user = 0; + vg_info( "SDL_StartTextInput()\n" ); SDL_StartTextInput(); } @@ -1408,7 +1709,7 @@ static int ui_textbox( ui_rect rect, char *buf, u32 len ) ui_outline( rect, -1, col_highlight ); } - ui_text( text_rect, buf, 1, k_ui_align_left, 0 ); + ui_ntext( text_rect, buf, char_width, 1, k_ui_align_left, 0 ); return 0; } diff --git a/vg_pxfont_thin.h b/vg_pxfont_thin.h index 759d66f..9f5d7c6 100644 --- a/vg_pxfont_thin.h +++ b/vg_pxfont_thin.h @@ -1,4 +1,4 @@ -/* Font buffer generated from source file: '/home/harry/Documents/vg/src/fonts/vg_font_thin.png' */ +/* Font buffer generated from source file: 'vg/src/fonts/vg_font_thin.png' */ 0xffff0000,0,0,0,0,0,0,0, 0xffff0000,0,0,0,0,0,0,0, 0xffff0000,0,0,0,0,0,0,0, @@ -148,12 +148,12 @@ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0, +0x400000,0,0,0,0,0,0,0, +0x800000,0,0,0,0,0,0,0, +0x1000000,0,0,0,0,0,0,0, +0x1000000,0,0,0,0,0,0,0, +0x1000000,0,0,0,0,0,0,0, +0xe00000,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, -- 2.25.1