Skip to content

Commit 8bac3e0

Browse files
committed
UI: bump stb_textedit version
1 parent 11c446d commit 8bac3e0

File tree

3 files changed

+117
-73
lines changed

3 files changed

+117
-73
lines changed

src/lib/stb_textedit.h

Lines changed: 74 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// stb_textedit.h - v1.11 - public domain - Sean Barrett
1+
// stb_textedit.h - v1.13 - public domain - Sean Barrett
22
// Development of this library was sponsored by RAD Game Tools
33
//
44
// This C header file implements the guts of a multi-line text-editing
@@ -13,7 +13,7 @@
1313
// texts, as its performance does not scale and it has limited undo).
1414
//
1515
// Non-trivial behaviors are modelled after Windows text controls.
16-
//
16+
//
1717
//
1818
// LICENSE
1919
//
@@ -29,6 +29,8 @@
2929
//
3030
// VERSION HISTORY
3131
//
32+
// 1.13 (2019-02-07) fix bug in undo size management
33+
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
3234
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
3335
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
3436
// 1.9 (2016-08-27) customizable move-by-word
@@ -85,8 +87,8 @@
8587
// moderate sizes. The undo system does no memory allocations, so
8688
// it grows STB_TexteditState by the worst-case storage which is (in bytes):
8789
//
88-
// [4 + sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
89-
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
90+
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
91+
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
9092
//
9193
//
9294
// Implementation mode:
@@ -109,7 +111,7 @@
109111
// Symbols that must be the same in header-file and implementation mode:
110112
//
111113
// STB_TEXTEDIT_CHARTYPE the character type
112-
// STB_TEXTEDIT_POSITIONTYPE small type that a valid cursor position
114+
// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position
113115
// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
114116
// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
115117
//
@@ -198,7 +200,7 @@
198200
// void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
199201
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
200202
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
201-
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key)
203+
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
202204
//
203205
// Each of these functions potentially updates the string and updates the
204206
// state.
@@ -211,29 +213,31 @@
211213
// call this with the mouse x,y on a mouse down; it will update the cursor
212214
// and reset the selection start/end to the cursor point. the x,y must
213215
// be relative to the text widget, with (0,0) being the top left.
214-
//
216+
//
215217
// drag:
216218
// call this with the mouse x,y on a mouse drag/up; it will update the
217219
// cursor and the selection end point
218-
//
220+
//
219221
// cut:
220222
// call this to delete the current selection; returns true if there was
221223
// one. you should FIRST copy the current selection to the system paste buffer.
222224
// (To copy, just copy the current selection out of the string yourself.)
223-
//
225+
//
224226
// paste:
225227
// call this to paste text at the current cursor point or over the current
226228
// selection if there is one.
227-
//
229+
//
228230
// key:
229231
// call this for keyboard inputs sent to the textfield. you can use it
230232
// for "key down" events or for "translated" key events. if you need to
231233
// do both (as in Win32), or distinguish Unicode characters from control
232234
// inputs, set a high bit to distinguish the two; then you can define the
233235
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
234236
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
235-
// clear.
237+
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
238+
// anything other type you wante before including.
236239
//
240+
//
237241
// When rendering, you can read the cursor position and selection state from
238242
// the STB_TexteditState.
239243
//
@@ -292,9 +296,9 @@ typedef struct
292296
{
293297
// private data
294298
STB_TEXTEDIT_POSITIONTYPE where;
295-
short insert_length;
296-
short delete_length;
297-
short char_storage;
299+
STB_TEXTEDIT_POSITIONTYPE insert_length;
300+
STB_TEXTEDIT_POSITIONTYPE delete_length;
301+
int char_storage;
298302
} StbUndoRecord;
299303

300304
typedef struct
@@ -303,7 +307,7 @@ typedef struct
303307
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
304308
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
305309
short undo_point, redo_point;
306-
short undo_char_point, redo_char_point;
310+
int undo_char_point, redo_char_point;
307311
} StbUndoState;
308312

309313
typedef struct
@@ -555,7 +559,6 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
555559

556560
// now scan to find xpos
557561
find->x = r.x0;
558-
i = 0;
559562
for (i=0; first+i < n; ++i)
560563
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
561564
}
@@ -634,11 +637,9 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat
634637
}
635638

636639
#ifdef STB_TEXTEDIT_IS_SPACE
637-
static int is_word_boundary( STB_TEXTEDIT_STRING *_str, int _idx )
640+
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
638641
{
639-
return _idx > 0 ? ((STB_TEXTEDIT_IS_SPACE(STB_TEXTEDIT_GETCHAR(_str,_idx-1)) ||
640-
STB_TEXTEDIT_IS_PUNCT(STB_TEXTEDIT_GETCHAR(_str,_idx-1))) &&
641-
!STB_TEXTEDIT_IS_SPACE(STB_TEXTEDIT_GETCHAR(_str, _idx))) : 1;
642+
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
642643
}
643644

644645
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
@@ -687,7 +688,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
687688
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
688689
{
689690
if (STB_TEXT_HAS_SELECTION(state)) {
690-
stb_textedit_delete_selection(str,state); // implicity clamps
691+
stb_textedit_delete_selection(str,state); // implicitly clamps
691692
state->has_preferred_x = 0;
692693
return 1;
693694
}
@@ -713,8 +714,12 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
713714
return 0;
714715
}
715716

717+
#ifndef STB_TEXTEDIT_KEYTYPE
718+
#define STB_TEXTEDIT_KEYTYPE int
719+
#endif
720+
716721
// API key: process a keyboard input
717-
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key)
722+
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
718723
{
719724
retry:
720725
switch (key) {
@@ -735,7 +740,7 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state,
735740
state->has_preferred_x = 0;
736741
}
737742
} else {
738-
stb_textedit_delete_selection(str,state); // implicity clamps
743+
stb_textedit_delete_selection(str,state); // implicitly clamps
739744
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
740745
stb_text_makeundo_insert(state, state->cursor, 1);
741746
++state->cursor;
@@ -751,7 +756,7 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state,
751756
state->insert_mode = !state->insert_mode;
752757
break;
753758
#endif
754-
759+
755760
case STB_TEXTEDIT_K_UNDO:
756761
stb_text_undo(str, state);
757762
state->has_preferred_x = 0;
@@ -766,7 +771,7 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state,
766771
// if currently there's a selection, move cursor to start of selection
767772
if (STB_TEXT_HAS_SELECTION(state))
768773
stb_textedit_move_to_first(state);
769-
else
774+
else
770775
if (state->cursor > 0)
771776
--state->cursor;
772777
state->has_preferred_x = 0;
@@ -815,7 +820,7 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state,
815820

816821
#ifdef STB_TEXTEDIT_MOVEWORDRIGHT
817822
case STB_TEXTEDIT_K_WORDRIGHT:
818-
if (STB_TEXT_HAS_SELECTION(state))
823+
if (STB_TEXT_HAS_SELECTION(state))
819824
stb_textedit_move_to_last(str, state);
820825
else {
821826
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
@@ -893,7 +898,7 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state,
893898
}
894899
break;
895900
}
896-
901+
897902
case STB_TEXTEDIT_K_UP:
898903
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {
899904
StbFindState find;
@@ -970,7 +975,7 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state,
970975
}
971976
state->has_preferred_x = 0;
972977
break;
973-
978+
974979
#ifdef STB_TEXTEDIT_K_TEXTSTART2
975980
case STB_TEXTEDIT_K_TEXTSTART2:
976981
#endif
@@ -987,7 +992,7 @@ static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state,
987992
state->select_start = state->select_end = 0;
988993
state->has_preferred_x = 0;
989994
break;
990-
995+
991996
#ifdef STB_TEXTEDIT_K_TEXTSTART2
992997
case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
993998
#endif
@@ -1091,11 +1096,11 @@ static void stb_textedit_discard_undo(StbUndoState *state)
10911096
if (state->undo_rec[0].char_storage >= 0) {
10921097
int n = state->undo_rec[0].insert_length, i;
10931098
// delete n characters from all other records
1094-
state->undo_char_point = state->undo_char_point - (short) n; // vsnet05
1099+
state->undo_char_point -= n;
10951100
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
10961101
for (i=0; i < state->undo_point; ++i)
10971102
if (state->undo_rec[i].char_storage >= 0)
1098-
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it
1103+
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
10991104
}
11001105
--state->undo_point;
11011106
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
@@ -1109,18 +1114,22 @@ static void stb_textedit_discard_undo(StbUndoState *state)
11091114
static void stb_textedit_discard_redo(StbUndoState *state)
11101115
{
11111116
int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
1117+
11121118
if (state->redo_point <= k) {
11131119
// if the k'th undo state has characters, clean those up
11141120
if (state->undo_rec[k].char_storage >= 0) {
11151121
int n = state->undo_rec[k].insert_length, i;
1116-
// delete n characters from all other records
1117-
state->redo_char_point = state->redo_char_point + (short) n; // vsnet05
1122+
// move the remaining redo character data to the end of the buffer
1123+
state->redo_char_point += n;
11181124
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
1125+
// adjust the position of all the other records to account for above memmove
11191126
for (i=state->redo_point; i < k; ++i)
11201127
if (state->undo_rec[i].char_storage >= 0)
1121-
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05
1128+
state->undo_rec[i].char_storage += n;
11221129
}
1123-
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point-1, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
1130+
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
1131+
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
1132+
// now move redo_point to point to the new one
11241133
++state->redo_point;
11251134
}
11261135
}
@@ -1156,15 +1165,15 @@ static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos,
11561165
return NULL;
11571166

11581167
r->where = pos;
1159-
r->insert_length = (short) insert_len;
1160-
r->delete_length = (short) delete_len;
1168+
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
1169+
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
11611170

11621171
if (insert_len == 0) {
11631172
r->char_storage = -1;
11641173
return NULL;
11651174
} else {
11661175
r->char_storage = state->undo_char_point;
1167-
state->undo_char_point = state->undo_char_point + (short) insert_len;
1176+
state->undo_char_point += insert_len;
11681177
return &state->undo_char[r->char_storage];
11691178
}
11701179
}
@@ -1204,16 +1213,16 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
12041213

12051214
// there's definitely room to store the characters eventually
12061215
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
1207-
// there's currently not enough room, so discard a redo record
1208-
stb_textedit_discard_redo(s);
12091216
// should never happen:
12101217
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
12111218
return;
1219+
// there's currently not enough room, so discard a redo record
1220+
stb_textedit_discard_redo(s);
12121221
}
12131222
r = &s->undo_rec[s->redo_point-1];
12141223

12151224
r->char_storage = s->redo_char_point - u.delete_length;
1216-
s->redo_char_point = s->redo_char_point - (short) u.delete_length;
1225+
s->redo_char_point = s->redo_char_point - u.delete_length;
12171226

12181227
// now save the characters
12191228
for (i=0; i < u.delete_length; ++i)
@@ -1358,38 +1367,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
13581367
------------------------------------------------------------------------------
13591368
ALTERNATIVE A - MIT License
13601369
Copyright (c) 2017 Sean Barrett
1361-
Permission is hereby granted, free of charge, to any person obtaining a copy of
1362-
this software and associated documentation files (the "Software"), to deal in
1363-
the Software without restriction, including without limitation the rights to
1364-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1365-
of the Software, and to permit persons to whom the Software is furnished to do
1370+
Permission is hereby granted, free of charge, to any person obtaining a copy of
1371+
this software and associated documentation files (the "Software"), to deal in
1372+
the Software without restriction, including without limitation the rights to
1373+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1374+
of the Software, and to permit persons to whom the Software is furnished to do
13661375
so, subject to the following conditions:
1367-
The above copyright notice and this permission notice shall be included in all
1376+
The above copyright notice and this permission notice shall be included in all
13681377
copies or substantial portions of the Software.
1369-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1370-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1371-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1372-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1373-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1374-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1378+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1379+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1380+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1381+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1382+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1383+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
13751384
SOFTWARE.
13761385
------------------------------------------------------------------------------
13771386
ALTERNATIVE B - Public Domain (www.unlicense.org)
13781387
This is free and unencumbered software released into the public domain.
1379-
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
1380-
software, either in source code form or as a compiled binary, for any purpose,
1388+
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
1389+
software, either in source code form or as a compiled binary, for any purpose,
13811390
commercial or non-commercial, and by any means.
1382-
In jurisdictions that recognize copyright laws, the author or authors of this
1383-
software dedicate any and all copyright interest in the software to the public
1384-
domain. We make this dedication for the benefit of the public at large and to
1385-
the detriment of our heirs and successors. We intend this dedication to be an
1386-
overt act of relinquishment in perpetuity of all present and future rights to
1391+
In jurisdictions that recognize copyright laws, the author or authors of this
1392+
software dedicate any and all copyright interest in the software to the public
1393+
domain. We make this dedication for the benefit of the public at large and to
1394+
the detriment of our heirs and successors. We intend this dedication to be an
1395+
overt act of relinquishment in perpetuity of all present and future rights to
13871396
this software under copyright law.
1388-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1389-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1390-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1391-
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1392-
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1397+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1398+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1399+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1400+
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1401+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
13931402
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13941403
------------------------------------------------------------------------------
13951404
*/

0 commit comments

Comments
 (0)