276 #ifndef INCLUDE_STB_TEXTEDIT_H
277 #define INCLUDE_STB_TEXTEDIT_H
288 #ifndef STB_TEXTEDIT_UNDOSTATECOUNT
289 #define STB_TEXTEDIT_UNDOSTATECOUNT 99
291 #ifndef STB_TEXTEDIT_UNDOCHARCOUNT
292 #define STB_TEXTEDIT_UNDOCHARCOUNT 999
294 #ifndef STB_TEXTEDIT_CHARTYPE
295 #define STB_TEXTEDIT_CHARTYPE int
297 #ifndef STB_TEXTEDIT_POSITIONTYPE
298 #define STB_TEXTEDIT_POSITIONTYPE int
369 #endif //INCLUDE_STB_TEXTEDIT_H
382 #ifdef STB_TEXTEDIT_IMPLEMENTATION
384 #ifndef STB_TEXTEDIT_memmove
386 #define STB_TEXTEDIT_memmove memmove
399 int n = STB_TEXTEDIT_STRINGLEN(str);
400 float base_y = 0, prev_x;
409 STB_TEXTEDIT_LAYOUTROW(&r, str, i);
413 if (i==0 &&
y < base_y + r.
ymin)
416 if (
y < base_y + r.
ymax)
436 float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
449 if (STB_TEXTEDIT_GETCHAR(str, i+r.
num_chars-1) == STB_TEXTEDIT_NEWLINE)
463 STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
467 state->
cursor = stb_text_locate_coord(str,
x,
y);
483 STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
490 p = stb_text_locate_coord(str,
x,
y);
503 static void stb_text_makeundo_insert(
STB_TexteditState *state,
int where,
int length);
510 int first_char, length;
516 static void stb_textedit_find_charpos(StbFindState *find,
STB_TEXTEDIT_STRING *str,
int n,
int single_line)
520 int z = STB_TEXTEDIT_STRINGLEN(str);
527 STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
529 find->first_char = 0;
538 STB_TEXTEDIT_LAYOUTROW(&r, str, i);
542 find->first_char = i;
544 find->prev_first = prev_start;
553 STB_TEXTEDIT_LAYOUTROW(&r, str, i);
561 find->first_char = first = i;
564 find->prev_first = prev_start;
568 for (i=0; first+i < n; ++i)
569 find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
572 #define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
577 int n = STB_TEXTEDIT_STRINGLEN(str);
578 if (STB_TEXT_HAS_SELECTION(state)) {
591 stb_text_makeundo_delete(str, state, where, len);
592 STB_TEXTEDIT_DELETECHARS(str, where, len);
599 stb_textedit_clamp(str, state);
600 if (STB_TEXT_HAS_SELECTION(state)) {
625 if (STB_TEXT_HAS_SELECTION(state)) {
626 stb_textedit_sortselection(state);
636 if (STB_TEXT_HAS_SELECTION(state)) {
637 stb_textedit_sortselection(state);
638 stb_textedit_clamp(str, state);
645 #ifdef STB_TEXTEDIT_IS_SPACE
648 return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
651 #ifndef STB_TEXTEDIT_MOVEWORDLEFT
655 while( c >= 0 && !is_word_boundary( str, c ) )
663 #define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous
666 #ifndef STB_TEXTEDIT_MOVEWORDRIGHT
669 const int len = STB_TEXTEDIT_STRINGLEN(str);
671 while( c < len && !is_word_boundary( str, c ) )
679 #define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next
687 if (!STB_TEXT_HAS_SELECTION(state))
696 if (STB_TEXT_HAS_SELECTION(state)) {
697 stb_textedit_delete_selection(str,state);
708 stb_textedit_clamp(str, state);
709 stb_textedit_delete_selection(str,state);
711 if (STB_TEXTEDIT_INSERTCHARS(str, state->
cursor, text, len)) {
712 stb_text_makeundo_insert(state, state->
cursor, len);
723 #ifndef STB_TEXTEDIT_KEYTYPE
724 #define STB_TEXTEDIT_KEYTYPE int
733 int c = STB_TEXTEDIT_KEYTOTEXT(key);
741 if (state->
insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->
cursor < STB_TEXTEDIT_STRINGLEN(str)) {
742 stb_text_makeundo_replace(str, state, state->
cursor, 1, 1);
743 STB_TEXTEDIT_DELETECHARS(str, state->
cursor, 1);
744 if (STB_TEXTEDIT_INSERTCHARS(str, state->
cursor, &ch, 1)) {
749 stb_textedit_delete_selection(str,state);
750 if (STB_TEXTEDIT_INSERTCHARS(str, state->
cursor, &ch, 1)) {
751 stb_text_makeundo_insert(state, state->
cursor, 1);
760 #ifdef STB_TEXTEDIT_K_INSERT
761 case STB_TEXTEDIT_K_INSERT:
767 stb_text_undo(str, state);
772 stb_text_redo(str, state);
778 if (STB_TEXT_HAS_SELECTION(state))
779 stb_textedit_move_to_first(state);
788 if (STB_TEXT_HAS_SELECTION(state))
789 stb_textedit_move_to_last(str, state);
792 stb_textedit_clamp(str, state);
797 stb_textedit_clamp(str, state);
798 stb_textedit_prep_selection_at_cursor(state);
806 #ifdef STB_TEXTEDIT_MOVEWORDLEFT
808 if (STB_TEXT_HAS_SELECTION(state))
809 stb_textedit_move_to_first(state);
812 stb_textedit_clamp( str, state );
817 if( !STB_TEXT_HAS_SELECTION( state ) )
818 stb_textedit_prep_selection_at_cursor(state);
823 stb_textedit_clamp( str, state );
827 #ifdef STB_TEXTEDIT_MOVEWORDRIGHT
829 if (STB_TEXT_HAS_SELECTION(state))
830 stb_textedit_move_to_last(str, state);
833 stb_textedit_clamp( str, state );
838 if( !STB_TEXT_HAS_SELECTION( state ) )
839 stb_textedit_prep_selection_at_cursor(state);
844 stb_textedit_clamp( str, state );
849 stb_textedit_prep_selection_at_cursor(state);
852 stb_textedit_clamp(str, state);
870 stb_textedit_prep_selection_at_cursor(state);
871 else if (STB_TEXT_HAS_SELECTION(state))
872 stb_textedit_move_to_last(str,state);
875 stb_textedit_clamp(str, state);
882 int start = find.first_char + find.length;
884 STB_TEXTEDIT_LAYOUTROW(&row, str, state->
cursor);
887 float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
888 #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
897 stb_textedit_clamp(str, state);
921 stb_textedit_prep_selection_at_cursor(state);
922 else if (STB_TEXT_HAS_SELECTION(state))
923 stb_textedit_move_to_first(state);
926 stb_textedit_clamp(str, state);
930 if (find.prev_first != find.first_char) {
934 state->
cursor = find.prev_first;
935 STB_TEXTEDIT_LAYOUTROW(&row, str, state->
cursor);
938 float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
939 #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
948 stb_textedit_clamp(str, state);
961 if (STB_TEXT_HAS_SELECTION(state))
962 stb_textedit_delete_selection(str, state);
964 int n = STB_TEXTEDIT_STRINGLEN(str);
966 stb_textedit_delete(str, state, state->
cursor, 1);
973 if (STB_TEXT_HAS_SELECTION(state))
974 stb_textedit_delete_selection(str, state);
976 stb_textedit_clamp(str, state);
978 stb_textedit_delete(str, state, state->
cursor-1, 1);
985 #ifdef STB_TEXTEDIT_K_TEXTSTART2
986 case STB_TEXTEDIT_K_TEXTSTART2:
993 #ifdef STB_TEXTEDIT_K_TEXTEND2
994 case STB_TEXTEDIT_K_TEXTEND2:
997 state->
cursor = STB_TEXTEDIT_STRINGLEN(str);
1002 #ifdef STB_TEXTEDIT_K_TEXTSTART2
1006 stb_textedit_prep_selection_at_cursor(state);
1011 #ifdef STB_TEXTEDIT_K_TEXTEND2
1015 stb_textedit_prep_selection_at_cursor(state);
1021 #ifdef STB_TEXTEDIT_K_LINESTART2
1022 case STB_TEXTEDIT_K_LINESTART2:
1025 stb_textedit_clamp(str, state);
1026 stb_textedit_move_to_first(state);
1029 else while (state->
cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->
cursor-1) != STB_TEXTEDIT_NEWLINE)
1034 #ifdef STB_TEXTEDIT_K_LINEEND2
1035 case STB_TEXTEDIT_K_LINEEND2:
1038 int n = STB_TEXTEDIT_STRINGLEN(str);
1039 stb_textedit_clamp(str, state);
1040 stb_textedit_move_to_first(state);
1043 else while (state->
cursor < n && STB_TEXTEDIT_GETCHAR(str, state->
cursor) != STB_TEXTEDIT_NEWLINE)
1049 #ifdef STB_TEXTEDIT_K_LINESTART2
1053 stb_textedit_clamp(str, state);
1054 stb_textedit_prep_selection_at_cursor(state);
1057 else while (state->
cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->
cursor-1) != STB_TEXTEDIT_NEWLINE)
1063 #ifdef STB_TEXTEDIT_K_LINEEND2
1067 int n = STB_TEXTEDIT_STRINGLEN(str);
1068 stb_textedit_clamp(str, state);
1069 stb_textedit_prep_selection_at_cursor(state);
1072 else while (state->
cursor < n && STB_TEXTEDIT_GETCHAR(str, state->
cursor) != STB_TEXTEDIT_NEWLINE)
1091 static void stb_textedit_flush_redo(
StbUndoState *state)
1098 static void stb_textedit_discard_undo(
StbUndoState *state)
1120 static void stb_textedit_discard_redo(
StbUndoState *state)
1139 const char* buf_begin = (
char*)state->
undo_rec; (
void)buf_begin;
1140 const char* buf_end = (
char*)state->
undo_rec +
sizeof(state->
undo_rec); (void)buf_end;
1153 stb_textedit_flush_redo(state);
1158 stb_textedit_discard_undo(state);
1169 stb_textedit_discard_undo(state);
1176 StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
1184 if (insert_len == 0) {
1233 stb_textedit_discard_redo(s);
1313 static void stb_text_makeundo_insert(
STB_TexteditState *state,
int where,
int length)
1315 stb_text_createundo(&state->
undostate, where, 0, length);
1323 for (i=0; i < length; ++i)
1324 p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
1333 for (i=0; i < old_length; ++i)
1334 p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
1339 static void stb_textedit_clear_state(
STB_TexteditState *state,
int is_single_line)
1351 state->
single_line = (
unsigned char) is_single_line;
1356 static void stb_textedit_initialize_state(
STB_TexteditState *state,
int is_single_line)
1358 stb_textedit_clear_state(state, is_single_line);
1361 #if defined(__GNUC__) || defined(__clang__)
1362 #pragma GCC diagnostic push
1363 #pragma GCC diagnostic ignored "-Wcast-qual"
1371 #if defined(__GNUC__) || defined(__clang__)
1372 #pragma GCC diagnostic pop
1375 #endif//STB_TEXTEDIT_IMPLEMENTATION