stb_textedit.h
Go to the documentation of this file.
1 // [ImGui] this is a slightly modified version of stb_truetype.h 1.8
2 // [ImGui] - fixed some minor warnings
3 // [ImGui] - added STB_TEXTEDIT_MOVEWORDLEFT/STB_TEXTEDIT_MOVEWORDRIGHT custom handler (#473)
4 
5 // stb_textedit.h - v1.8 - public domain - Sean Barrett
6 // Development of this library was sponsored by RAD Game Tools
7 //
8 // This C header file implements the guts of a multi-line text-editing
9 // widget; you implement display, word-wrapping, and low-level string
10 // insertion/deletion, and stb_textedit will map user inputs into
11 // insertions & deletions, plus updates to the cursor position,
12 // selection state, and undo state.
13 //
14 // It is intended for use in games and other systems that need to build
15 // their own custom widgets and which do not have heavy text-editing
16 // requirements (this library is not recommended for use for editing large
17 // texts, as its performance does not scale and it has limited undo).
18 //
19 // Non-trivial behaviors are modelled after Windows text controls.
20 //
21 //
22 // LICENSE
23 //
24 // This software is dual-licensed to the public domain and under the following
25 // license: you are granted a perpetual, irrevocable license to copy, modify,
26 // publish, and distribute this file as you see fit.
27 //
28 //
29 // DEPENDENCIES
30 //
31 // Uses the C runtime function 'memmove', which you can override
32 // by defining STB_TEXTEDIT_memmove before the implementation.
33 // Uses no other functions. Performs no runtime allocations.
34 //
35 //
36 // VERSION HISTORY
37 //
38 // 1.8 (2016-04-02) better keyboard handling when mouse button is down
39 // 1.7 (2015-09-13) change y range handling in case baseline is non-0
40 // 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove
41 // 1.5 (2014-09-10) add support for secondary keys for OS X
42 // 1.4 (2014-08-17) fix signed/unsigned warnings
43 // 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary
44 // 1.2 (2014-05-27) fix some RAD types that had crept into the new code
45 // 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE )
46 // 1.0 (2012-07-26) improve documentation, initial public release
47 // 0.3 (2012-02-24) bugfixes, single-line mode; insert mode
48 // 0.2 (2011-11-28) fixes to undo/redo
49 // 0.1 (2010-07-08) initial version
50 //
51 // ADDITIONAL CONTRIBUTORS
52 //
53 // Ulf Winklemann: move-by-word in 1.1
54 // Fabian Giesen: secondary key inputs in 1.5
55 // Martins Mozeiko: STB_TEXTEDIT_memmove
56 //
57 // Bugfixes:
58 // Scott Graham
59 // Daniel Keller
60 // Omar Cornut
61 //
62 // USAGE
63 //
64 // This file behaves differently depending on what symbols you define
65 // before including it.
66 //
67 //
68 // Header-file mode:
69 //
70 // If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this,
71 // it will operate in "header file" mode. In this mode, it declares a
72 // single public symbol, STB_TexteditState, which encapsulates the current
73 // state of a text widget (except for the string, which you will store
74 // separately).
75 //
76 // To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a
77 // primitive type that defines a single character (e.g. char, wchar_t, etc).
78 //
79 // To save space or increase undo-ability, you can optionally define the
80 // following things that are used by the undo system:
81 //
82 // STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position
83 // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
84 // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
85 //
86 // If you don't define these, they are set to permissive types and
87 // moderate sizes. The undo system does no memory allocations, so
88 // it grows STB_TexteditState by the worst-case storage which is (in bytes):
89 //
90 // [4 + sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
91 // + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
92 //
93 //
94 // Implementation mode:
95 //
96 // If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it
97 // will compile the implementation of the text edit widget, depending
98 // on a large number of symbols which must be defined before the include.
99 //
100 // The implementation is defined only as static functions. You will then
101 // need to provide your own APIs in the same file which will access the
102 // static functions.
103 //
104 // The basic concept is that you provide a "string" object which
105 // behaves like an array of characters. stb_textedit uses indices to
106 // refer to positions in the string, implicitly representing positions
107 // in the displayed textedit. This is true for both plain text and
108 // rich text; even with rich text stb_truetype interacts with your
109 // code as if there was an array of all the displayed characters.
110 //
111 // Symbols that must be the same in header-file and implementation mode:
112 //
113 // STB_TEXTEDIT_CHARTYPE the character type
114 // STB_TEXTEDIT_POSITIONTYPE small type that a valid cursor position
115 // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
116 // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
117 //
118 // Symbols you must define for implementation mode:
119 //
120 // STB_TEXTEDIT_STRING the type of object representing a string being edited,
121 // typically this is a wrapper object with other data you need
122 //
123 // STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1))
124 // STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters
125 // starting from character #n (see discussion below)
126 // STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character
127 // to the xpos of the i+1'th char for a line of characters
128 // starting at character #n (i.e. accounts for kerning
129 // with previous char)
130 // STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character
131 // (return type is int, -1 means not valid to insert)
132 // STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based
133 // STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize
134 // as manually wordwrapping for end-of-line positioning
135 //
136 // STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i
137 // STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
138 //
139 // STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key
140 //
141 // STB_TEXTEDIT_K_LEFT keyboard input to move cursor left
142 // STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
143 // STB_TEXTEDIT_K_UP keyboard input to move cursor up
144 // STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
145 // STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
146 // STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
147 // STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
148 // STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END
149 // STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor
150 // STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor
151 // STB_TEXTEDIT_K_UNDO keyboard input to perform undo
152 // STB_TEXTEDIT_K_REDO keyboard input to perform redo
153 //
154 // Optional:
155 // STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode
156 // STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'),
157 // required for default WORDLEFT/WORDRIGHT handlers
158 // STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to
159 // STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to
160 // STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT
161 // STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT
162 // STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line
163 // STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line
164 // STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
165 // STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
166 //
167 // Todo:
168 // STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
169 // STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
170 //
171 // Keyboard input must be encoded as a single integer value; e.g. a character code
172 // and some bitflags that represent shift states. to simplify the interface, SHIFT must
173 // be a bitflag, so we can test the shifted state of cursor movements to allow selection,
174 // i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
175 //
176 // You can encode other things, such as CONTROL or ALT, in additional bits, and
177 // then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
178 // my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN
179 // bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit,
180 // and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the
181 // API below. The control keys will only match WM_KEYDOWN events because of the
182 // keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN
183 // bit so it only decodes WM_CHAR events.
184 //
185 // STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed
186 // row of characters assuming they start on the i'th character--the width and
187 // the height and the number of characters consumed. This allows this library
188 // to traverse the entire layout incrementally. You need to compute word-wrapping
189 // here.
190 //
191 // Each textfield keeps its own insert mode state, which is not how normal
192 // applications work. To keep an app-wide insert mode, update/copy the
193 // "insert_mode" field of STB_TexteditState before/after calling API functions.
194 //
195 // API
196 //
197 // void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
198 //
199 // void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
200 // void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
201 // int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
202 // int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
203 // void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key)
204 //
205 // Each of these functions potentially updates the string and updates the
206 // state.
207 //
208 // initialize_state:
209 // set the textedit state to a known good default state when initially
210 // constructing the textedit.
211 //
212 // click:
213 // call this with the mouse x,y on a mouse down; it will update the cursor
214 // and reset the selection start/end to the cursor point. the x,y must
215 // be relative to the text widget, with (0,0) being the top left.
216 //
217 // drag:
218 // call this with the mouse x,y on a mouse drag/up; it will update the
219 // cursor and the selection end point
220 //
221 // cut:
222 // call this to delete the current selection; returns true if there was
223 // one. you should FIRST copy the current selection to the system paste buffer.
224 // (To copy, just copy the current selection out of the string yourself.)
225 //
226 // paste:
227 // call this to paste text at the current cursor point or over the current
228 // selection if there is one.
229 //
230 // key:
231 // call this for keyboard inputs sent to the textfield. you can use it
232 // for "key down" events or for "translated" key events. if you need to
233 // do both (as in Win32), or distinguish Unicode characters from control
234 // inputs, set a high bit to distinguish the two; then you can define the
235 // various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
236 // set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
237 // clear.
238 //
239 // When rendering, you can read the cursor position and selection state from
240 // the STB_TexteditState.
241 //
242 //
243 // Notes:
244 //
245 // This is designed to be usable in IMGUI, so it allows for the possibility of
246 // running in an IMGUI that has NOT cached the multi-line layout. For this
247 // reason, it provides an interface that is compatible with computing the
248 // layout incrementally--we try to make sure we make as few passes through
249 // as possible. (For example, to locate the mouse pointer in the text, we
250 // could define functions that return the X and Y positions of characters
251 // and binary search Y and then X, but if we're doing dynamic layout this
252 // will run the layout algorithm many times, so instead we manually search
253 // forward in one pass. Similar logic applies to e.g. up-arrow and
254 // down-arrow movement.)
255 //
256 // If it's run in a widget that *has* cached the layout, then this is less
257 // efficient, but it's not horrible on modern computers. But you wouldn't
258 // want to edit million-line files with it.
259 
260 
267 
268 #ifndef INCLUDE_STB_TEXTEDIT_H
269 #define INCLUDE_STB_TEXTEDIT_H
270 
272 //
273 // STB_TexteditState
274 //
275 // Definition of STB_TexteditState which you should store
276 // per-textfield; it includes cursor position, selection state,
277 // and undo state.
278 //
279 
280 #ifndef STB_TEXTEDIT_UNDOSTATECOUNT
281 #define STB_TEXTEDIT_UNDOSTATECOUNT 99
282 #endif
283 #ifndef STB_TEXTEDIT_UNDOCHARCOUNT
284 #define STB_TEXTEDIT_UNDOCHARCOUNT 999
285 #endif
286 #ifndef STB_TEXTEDIT_CHARTYPE
287 #define STB_TEXTEDIT_CHARTYPE int
288 #endif
289 #ifndef STB_TEXTEDIT_POSITIONTYPE
290 #define STB_TEXTEDIT_POSITIONTYPE int
291 #endif
292 
293 typedef struct
294 {
295  // private data
300 } StbUndoRecord;
301 
302 typedef struct
303 {
304  // private data
307  short undo_point, redo_point;
308  short undo_char_point, redo_char_point;
309 } StbUndoState;
310 
311 typedef struct
312 {
314  //
315  // public data
316  //
317 
318  int cursor;
319  // position of the text cursor within the string
320 
321  int select_start; // selection start point
323  // selection start and end point in characters; if equal, no selection.
324  // note that start may be less than or greater than end (e.g. when
325  // dragging the mouse, start is where the initial click was, and you
326  // can drag in either direction)
327 
328  unsigned char insert_mode;
329  // each textfield keeps its own insert mode state. to keep an app-wide
330  // insert mode, copy this value in/out of the app state
331 
333  //
334  // private data
335  //
336  unsigned char cursor_at_end_of_line; // not implemented yet
337  unsigned char initialized;
338  unsigned char has_preferred_x;
339  unsigned char single_line;
340  unsigned char padding1, padding2, padding3;
341  float preferred_x; // this determines where the cursor up/down tries to seek to along x
344 
345 
347 //
348 // StbTexteditRow
349 //
350 // Result of layout query, used by stb_textedit to determine where
351 // the text in each row is.
352 
353 // result of layout query
354 typedef struct
355 {
356  float x0,x1; // starting x location, end x location (allows for align=right, etc)
357  float baseline_y_delta; // position of baseline relative to previous row's baseline
358  float ymin,ymax; // height of row above and below baseline
361 #endif //INCLUDE_STB_TEXTEDIT_H
362 
363 
370 
371 
372 // implementation isn't include-guarded, since it might have indirectly
373 // included just the "header" portion
374 #ifdef STB_TEXTEDIT_IMPLEMENTATION
375 
376 #ifndef STB_TEXTEDIT_memmove
377 #include <string.h>
378 #define STB_TEXTEDIT_memmove memmove
379 #endif
380 
381 
383 //
384 // Mouse input handling
385 //
386 
387 // traverse the layout to locate the nearest character to a display position
388 static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
389 {
391  int n = STB_TEXTEDIT_STRINGLEN(str);
392  float base_y = 0, prev_x;
393  int i=0, k;
394 
395  r.x0 = r.x1 = 0;
396  r.ymin = r.ymax = 0;
397  r.num_chars = 0;
398 
399  // search rows to find one that straddles 'y'
400  while (i < n) {
401  STB_TEXTEDIT_LAYOUTROW(&r, str, i);
402  if (r.num_chars <= 0)
403  return n;
404 
405  if (i==0 && y < base_y + r.ymin)
406  return 0;
407 
408  if (y < base_y + r.ymax)
409  break;
410 
411  i += r.num_chars;
412  base_y += r.baseline_y_delta;
413  }
414 
415  // below all text, return 'after' last character
416  if (i >= n)
417  return n;
418 
419  // check if it's before the beginning of the line
420  if (x < r.x0)
421  return i;
422 
423  // check if it's before the end of the line
424  if (x < r.x1) {
425  // search characters in row for one that straddles 'x'
426  k = i;
427  prev_x = r.x0;
428  for (i=0; i < r.num_chars; ++i) {
429  float w = STB_TEXTEDIT_GETWIDTH(str, k, i);
430  if (x < prev_x+w) {
431  if (x < prev_x+w/2)
432  return k+i;
433  else
434  return k+i+1;
435  }
436  prev_x += w;
437  }
438  // shouldn't happen, but if it does, fall through to end-of-line case
439  }
440 
441  // if the last character is a newline, return that. otherwise return 'after' the last character
443  return i+r.num_chars-1;
444  else
445  return i+r.num_chars;
446 }
447 
448 // API click: on mouse down, move the cursor to the clicked location, and reset the selection
450 {
451  state->cursor = stb_text_locate_coord(str, x, y);
452  state->select_start = state->cursor;
453  state->select_end = state->cursor;
454  state->has_preferred_x = 0;
455 }
456 
457 // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
458 static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
459 {
460  int p = stb_text_locate_coord(str, x, y);
461  if (state->select_start == state->select_end)
462  state->select_start = state->cursor;
463  state->cursor = state->select_end = p;
464 }
465 
467 //
468 // Keyboard input handling
469 //
470 
471 // forward declarations
474 static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
475 static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
476 static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
477 
478 typedef struct
479 {
480  float x,y; // position of n'th character
481  float height; // height of line
482  int first_char, length; // first char of row, and length
483  int prev_first; // first char of previous row
484 } StbFindState;
485 
486 // find the x/y location of a character, and remember info about the previous row in
487 // case we get a move-up event (for page up, we'll have to rescan)
488 static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
489 {
491  int prev_start = 0;
493  int i=0, first;
494 
495  if (n == z) {
496  // if it's at the end, then find the last line -- simpler than trying to
497  // explicitly handle this case in the regular code
498  if (single_line) {
499  STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
500  find->y = 0;
501  find->first_char = 0;
502  find->length = z;
503  find->height = r.ymax - r.ymin;
504  find->x = r.x1;
505  } else {
506  find->y = 0;
507  find->x = 0;
508  find->height = 1;
509  while (i < z) {
510  STB_TEXTEDIT_LAYOUTROW(&r, str, i);
511  prev_start = i;
512  i += r.num_chars;
513  }
514  find->first_char = i;
515  find->length = 0;
516  find->prev_first = prev_start;
517  }
518  return;
519  }
520 
521  // search rows to find the one that straddles character n
522  find->y = 0;
523 
524  for(;;) {
525  STB_TEXTEDIT_LAYOUTROW(&r, str, i);
526  if (n < i + r.num_chars)
527  break;
528  prev_start = i;
529  i += r.num_chars;
530  find->y += r.baseline_y_delta;
531  }
532 
533  find->first_char = first = i;
534  find->length = r.num_chars;
535  find->height = r.ymax - r.ymin;
536  find->prev_first = prev_start;
537 
538  // now scan to find xpos
539  find->x = r.x0;
540  i = 0;
541  for (i=0; first+i < n; ++i)
542  find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
543 }
544 
545 #define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
546 
547 // make the selection/cursor state valid if client altered the string
549 {
551  if (STB_TEXT_HAS_SELECTION(state)) {
552  if (state->select_start > n) state->select_start = n;
553  if (state->select_end > n) state->select_end = n;
554  // if clamping forced them to be equal, move the cursor to match
555  if (state->select_start == state->select_end)
556  state->cursor = state->select_start;
557  }
558  if (state->cursor > n) state->cursor = n;
559 }
560 
561 // delete characters while updating undo
562 static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
563 {
564  stb_text_makeundo_delete(str, state, where, len);
565  STB_TEXTEDIT_DELETECHARS(str, where, len);
566  state->has_preferred_x = 0;
567 }
568 
569 // delete the section
571 {
572  stb_textedit_clamp(str, state);
573  if (STB_TEXT_HAS_SELECTION(state)) {
574  if (state->select_start < state->select_end) {
575  stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start);
576  state->select_end = state->cursor = state->select_start;
577  } else {
578  stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end);
579  state->select_start = state->cursor = state->select_end;
580  }
581  state->has_preferred_x = 0;
582  }
583 }
584 
585 // canoncialize the selection so start <= end
587 {
588  if (state->select_end < state->select_start) {
589  int temp = state->select_end;
590  state->select_end = state->select_start;
591  state->select_start = temp;
592  }
593 }
594 
595 // move cursor to first character of selection
597 {
598  if (STB_TEXT_HAS_SELECTION(state)) {
600  state->cursor = state->select_start;
601  state->select_end = state->select_start;
602  state->has_preferred_x = 0;
603  }
604 }
605 
606 // move cursor to last character of selection
608 {
609  if (STB_TEXT_HAS_SELECTION(state)) {
611  stb_textedit_clamp(str, state);
612  state->cursor = state->select_end;
613  state->select_start = state->select_end;
614  state->has_preferred_x = 0;
615  }
616 }
617 
618 #ifdef STB_TEXTEDIT_IS_SPACE
619 static int is_word_boundary( STB_TEXTEDIT_STRING *_str, int _idx )
620 {
621  return _idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str,_idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str, _idx) ) ) : 1;
622 }
623 
624 #ifndef STB_TEXTEDIT_MOVEWORDLEFT
625 static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, int c )
626 {
627  while( c >= 0 && !is_word_boundary( _str, c ) )
628  --c;
629 
630  if( c < 0 )
631  c = 0;
632 
633  return c;
634 }
635 #define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous
636 #endif
637 
638 #ifndef STB_TEXTEDIT_MOVEWORDRIGHT
639 static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *_str, int c )
640 {
641  const int len = STB_TEXTEDIT_STRINGLEN(_str);
642  while( c < len && !is_word_boundary( _str, c ) )
643  ++c;
644 
645  if( c > len )
646  c = len;
647 
648  return c;
649 }
650 #define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next
651 #endif
652 
653 #endif
654 
655 // update selection and cursor to match each other
657 {
658  if (!STB_TEXT_HAS_SELECTION(state))
659  state->select_start = state->select_end = state->cursor;
660  else
661  state->cursor = state->select_end;
662 }
663 
664 // API cut: delete selection
666 {
667  if (STB_TEXT_HAS_SELECTION(state)) {
668  stb_textedit_delete_selection(str,state); // implicity clamps
669  state->has_preferred_x = 0;
670  return 1;
671  }
672  return 0;
673 }
674 
675 // API paste: replace existing selection with passed-in text
677 {
679  // if there's a selection, the paste should delete it
680  stb_textedit_clamp(str, state);
682  // try to insert the characters
683  if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
684  stb_text_makeundo_insert(state, state->cursor, len);
685  state->cursor += len;
686  state->has_preferred_x = 0;
687  return 1;
688  }
689  // remove the undo since we didn't actually insert the characters
690  if (state->undostate.undo_point)
691  --state->undostate.undo_point;
692  return 0;
693 }
694 
695 // API key: process a keyboard input
697 {
698 retry:
699  switch (key) {
700  default: {
701  int c = STB_TEXTEDIT_KEYTOTEXT(key);
702  if (c > 0) {
704 
705  // can't add newline in single-line mode
706  if (c == '\n' && state->single_line)
707  break;
708 
709  if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
710  stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
711  STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
712  if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
713  ++state->cursor;
714  state->has_preferred_x = 0;
715  }
716  } else {
717  stb_textedit_delete_selection(str,state); // implicity clamps
718  if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
719  stb_text_makeundo_insert(state, state->cursor, 1);
720  ++state->cursor;
721  state->has_preferred_x = 0;
722  }
723  }
724  }
725  break;
726  }
727 
728 #ifdef STB_TEXTEDIT_K_INSERT
729  case STB_TEXTEDIT_K_INSERT:
730  state->insert_mode = !state->insert_mode;
731  break;
732 #endif
733 
734  case STB_TEXTEDIT_K_UNDO:
735  stb_text_undo(str, state);
736  state->has_preferred_x = 0;
737  break;
738 
739  case STB_TEXTEDIT_K_REDO:
740  stb_text_redo(str, state);
741  state->has_preferred_x = 0;
742  break;
743 
744  case STB_TEXTEDIT_K_LEFT:
745  // if currently there's a selection, move cursor to start of selection
746  if (STB_TEXT_HAS_SELECTION(state))
748  else
749  if (state->cursor > 0)
750  --state->cursor;
751  state->has_preferred_x = 0;
752  break;
753 
755  // if currently there's a selection, move cursor to end of selection
756  if (STB_TEXT_HAS_SELECTION(state))
758  else
759  ++state->cursor;
760  stb_textedit_clamp(str, state);
761  state->has_preferred_x = 0;
762  break;
763 
765  stb_textedit_clamp(str, state);
767  // move selection left
768  if (state->select_end > 0)
769  --state->select_end;
770  state->cursor = state->select_end;
771  state->has_preferred_x = 0;
772  break;
773 
774 #ifdef STB_TEXTEDIT_MOVEWORDLEFT
776  if (STB_TEXT_HAS_SELECTION(state))
778  else {
779  state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor-1);
780  stb_textedit_clamp( str, state );
781  }
782  break;
783 
785  if( !STB_TEXT_HAS_SELECTION( state ) )
787 
788  state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor-1);
789  state->select_end = state->cursor;
790 
791  stb_textedit_clamp( str, state );
792  break;
793 #endif
794 
795 #ifdef STB_TEXTEDIT_MOVEWORDRIGHT
797  if (STB_TEXT_HAS_SELECTION(state))
799  else {
800  state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor+1);
801  stb_textedit_clamp( str, state );
802  }
803  break;
804 
806  if( !STB_TEXT_HAS_SELECTION( state ) )
808 
809  state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor+1);
810  state->select_end = state->cursor;
811 
812  stb_textedit_clamp( str, state );
813  break;
814 #endif
815 
818  // move selection right
819  ++state->select_end;
820  stb_textedit_clamp(str, state);
821  state->cursor = state->select_end;
822  state->has_preferred_x = 0;
823  break;
824 
825  case STB_TEXTEDIT_K_DOWN:
827  StbFindState find;
829  int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
830 
831  if (state->single_line) {
832  // on windows, up&down in single-line behave like left&right
834  goto retry;
835  }
836 
837  if (sel)
839  else if (STB_TEXT_HAS_SELECTION(state))
841 
842  // compute current position of cursor point
843  stb_textedit_clamp(str, state);
844  stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
845 
846  // now find character position down a row
847  if (find.length) {
848  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
849  float x;
850  int start = find.first_char + find.length;
851  state->cursor = start;
852  STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
853  x = row.x0;
854  for (i=0; i < row.num_chars; ++i) {
855  float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
856  #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
858  break;
859  #endif
860  x += dx;
861  if (x > goal_x)
862  break;
863  ++state->cursor;
864  }
865  stb_textedit_clamp(str, state);
866 
867  state->has_preferred_x = 1;
868  state->preferred_x = goal_x;
869 
870  if (sel)
871  state->select_end = state->cursor;
872  }
873  break;
874  }
875 
876  case STB_TEXTEDIT_K_UP:
878  StbFindState find;
880  int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
881 
882  if (state->single_line) {
883  // on windows, up&down become left&right
885  goto retry;
886  }
887 
888  if (sel)
890  else if (STB_TEXT_HAS_SELECTION(state))
892 
893  // compute current position of cursor point
894  stb_textedit_clamp(str, state);
895  stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
896 
897  // can only go up if there's a previous row
898  if (find.prev_first != find.first_char) {
899  // now find character position up a row
900  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
901  float x;
902  state->cursor = find.prev_first;
903  STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
904  x = row.x0;
905  for (i=0; i < row.num_chars; ++i) {
906  float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
907  #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
909  break;
910  #endif
911  x += dx;
912  if (x > goal_x)
913  break;
914  ++state->cursor;
915  }
916  stb_textedit_clamp(str, state);
917 
918  state->has_preferred_x = 1;
919  state->preferred_x = goal_x;
920 
921  if (sel)
922  state->select_end = state->cursor;
923  }
924  break;
925  }
926 
929  if (STB_TEXT_HAS_SELECTION(state))
931  else {
933  if (state->cursor < n)
934  stb_textedit_delete(str, state, state->cursor, 1);
935  }
936  state->has_preferred_x = 0;
937  break;
938 
941  if (STB_TEXT_HAS_SELECTION(state))
943  else {
944  stb_textedit_clamp(str, state);
945  if (state->cursor > 0) {
946  stb_textedit_delete(str, state, state->cursor-1, 1);
947  --state->cursor;
948  }
949  }
950  state->has_preferred_x = 0;
951  break;
952 
953 #ifdef STB_TEXTEDIT_K_TEXTSTART2
954  case STB_TEXTEDIT_K_TEXTSTART2:
955 #endif
957  state->cursor = state->select_start = state->select_end = 0;
958  state->has_preferred_x = 0;
959  break;
960 
961 #ifdef STB_TEXTEDIT_K_TEXTEND2
962  case STB_TEXTEDIT_K_TEXTEND2:
963 #endif
966  state->select_start = state->select_end = 0;
967  state->has_preferred_x = 0;
968  break;
969 
970 #ifdef STB_TEXTEDIT_K_TEXTSTART2
971  case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
972 #endif
975  state->cursor = state->select_end = 0;
976  state->has_preferred_x = 0;
977  break;
978 
979 #ifdef STB_TEXTEDIT_K_TEXTEND2
980  case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT:
981 #endif
984  state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str);
985  state->has_preferred_x = 0;
986  break;
987 
988 
989 #ifdef STB_TEXTEDIT_K_LINESTART2
990  case STB_TEXTEDIT_K_LINESTART2:
991 #endif
993  StbFindState find;
994  stb_textedit_clamp(str, state);
996  stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
997  state->cursor = find.first_char;
998  state->has_preferred_x = 0;
999  break;
1000  }
1001 
1002 #ifdef STB_TEXTEDIT_K_LINEEND2
1003  case STB_TEXTEDIT_K_LINEEND2:
1004 #endif
1005  case STB_TEXTEDIT_K_LINEEND: {
1006  StbFindState find;
1007  stb_textedit_clamp(str, state);
1009  stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
1010 
1011  state->has_preferred_x = 0;
1012  state->cursor = find.first_char + find.length;
1013  if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
1014  --state->cursor;
1015  break;
1016  }
1017 
1018 #ifdef STB_TEXTEDIT_K_LINESTART2
1019  case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:
1020 #endif
1022  StbFindState find;
1023  stb_textedit_clamp(str, state);
1025  stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
1026  state->cursor = state->select_end = find.first_char;
1027  state->has_preferred_x = 0;
1028  break;
1029  }
1030 
1031 #ifdef STB_TEXTEDIT_K_LINEEND2
1032  case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
1033 #endif
1035  StbFindState find;
1036  stb_textedit_clamp(str, state);
1038  stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
1039  state->has_preferred_x = 0;
1040  state->cursor = find.first_char + find.length;
1041  if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
1042  --state->cursor;
1043  state->select_end = state->cursor;
1044  break;
1045  }
1046 
1047 // @TODO:
1048 // STB_TEXTEDIT_K_PGUP - move cursor up a page
1049 // STB_TEXTEDIT_K_PGDOWN - move cursor down a page
1050  }
1051 }
1052 
1054 //
1055 // Undo processing
1056 //
1057 // @OPTIMIZE: the undo/redo buffer should be circular
1058 
1059 static void stb_textedit_flush_redo(StbUndoState *state)
1060 {
1063 }
1064 
1065 // discard the oldest entry in the undo list
1066 static void stb_textedit_discard_undo(StbUndoState *state)
1067 {
1068  if (state->undo_point > 0) {
1069  // if the 0th undo state has characters, clean those up
1070  if (state->undo_rec[0].char_storage >= 0) {
1071  int n = state->undo_rec[0].insert_length, i;
1072  // delete n characters from all other records
1073  state->undo_char_point = state->undo_char_point - (short) n; // vsnet05
1074  STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) ((size_t)state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
1075  for (i=0; i < state->undo_point; ++i)
1076  if (state->undo_rec[i].char_storage >= 0)
1077  state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it
1078  }
1079  --state->undo_point;
1080  STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) ((size_t)state->undo_point*sizeof(state->undo_rec[0])));
1081  }
1082 }
1083 
1084 // discard the oldest entry in the redo list--it's bad if this
1085 // ever happens, but because undo & redo have to store the actual
1086 // characters in different cases, the redo character buffer can
1087 // fill up even though the undo buffer didn't
1088 static void stb_textedit_discard_redo(StbUndoState *state)
1089 {
1090  int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
1091 
1092  if (state->redo_point <= k) {
1093  // if the k'th undo state has characters, clean those up
1094  if (state->undo_rec[k].char_storage >= 0) {
1095  int n = state->undo_rec[k].insert_length, i;
1096  // delete n characters from all other records
1097  state->redo_char_point = state->redo_char_point + (short) n; // vsnet05
1098  STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
1099  for (i=state->redo_point; i < k; ++i)
1100  if (state->undo_rec[i].char_storage >= 0)
1101  state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05
1102  }
1103  ++state->redo_point;
1104  STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
1105  }
1106 }
1107 
1108 static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars)
1109 {
1110  // any time we create a new undo record, we discard redo
1111  stb_textedit_flush_redo(state);
1112 
1113  // if we have no free records, we have to make room, by sliding the
1114  // existing records down
1117 
1118  // if the characters to store won't possibly fit in the buffer, we can't undo
1119  if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
1120  state->undo_point = 0;
1121  state->undo_char_point = 0;
1122  return NULL;
1123  }
1124 
1125  // if we don't have enough free characters in the buffer, we have to make room
1126  while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
1128 
1129  return &state->undo_rec[state->undo_point++];
1130 }
1131 
1132 static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
1133 {
1134  StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
1135  if (r == NULL)
1136  return NULL;
1137 
1138  r->where = pos;
1139  r->insert_length = (short) insert_len;
1140  r->delete_length = (short) delete_len;
1141 
1142  if (insert_len == 0) {
1143  r->char_storage = -1;
1144  return NULL;
1145  } else {
1146  r->char_storage = state->undo_char_point;
1147  state->undo_char_point = state->undo_char_point + (short) insert_len;
1148  return &state->undo_char[r->char_storage];
1149  }
1150 }
1151 
1153 {
1154  StbUndoState *s = &state->undostate;
1155  StbUndoRecord u, *r;
1156  if (s->undo_point == 0)
1157  return;
1158 
1159  // we need to do two things: apply the undo record, and create a redo record
1160  u = s->undo_rec[s->undo_point-1];
1161  r = &s->undo_rec[s->redo_point-1];
1162  r->char_storage = -1;
1163 
1166  r->where = u.where;
1167 
1168  if (u.delete_length) {
1169  // if the undo record says to delete characters, then the redo record will
1170  // need to re-insert the characters that get deleted, so we need to store
1171  // them.
1172 
1173  // there are three cases:
1174  // there's enough room to store the characters
1175  // characters stored for *redoing* don't leave room for redo
1176  // characters stored for *undoing* don't leave room for redo
1177  // if the last is true, we have to bail
1178 
1180  // the undo records take up too much character space; there's no space to store the redo characters
1181  r->insert_length = 0;
1182  } else {
1183  int i;
1184 
1185  // there's definitely room to store the characters eventually
1186  while (s->undo_char_point + u.delete_length > s->redo_char_point) {
1187  // there's currently not enough room, so discard a redo record
1189  // should never happen:
1191  return;
1192  }
1193  r = &s->undo_rec[s->redo_point-1];
1194 
1196  s->redo_char_point = s->redo_char_point - (short) u.delete_length;
1197 
1198  // now save the characters
1199  for (i=0; i < u.delete_length; ++i)
1200  s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i);
1201  }
1202 
1203  // now we can carry out the deletion
1205  }
1206 
1207  // check type of recorded action:
1208  if (u.insert_length) {
1209  // easy case: was a deletion, so we need to insert n characters
1212  }
1213 
1214  state->cursor = u.where + u.insert_length;
1215 
1216  s->undo_point--;
1217  s->redo_point--;
1218 }
1219 
1221 {
1222  StbUndoState *s = &state->undostate;
1223  StbUndoRecord *u, r;
1225  return;
1226 
1227  // we need to do two things: apply the redo record, and create an undo record
1228  u = &s->undo_rec[s->undo_point];
1229  r = s->undo_rec[s->redo_point];
1230 
1231  // we KNOW there must be room for the undo record, because the redo record
1232  // was derived from an undo record
1233 
1236  u->where = r.where;
1237  u->char_storage = -1;
1238 
1239  if (r.delete_length) {
1240  // the redo record requires us to delete characters, so the undo record
1241  // needs to store the characters
1242 
1243  if (s->undo_char_point + u->insert_length > s->redo_char_point) {
1244  u->insert_length = 0;
1245  u->delete_length = 0;
1246  } else {
1247  int i;
1248  u->char_storage = s->undo_char_point;
1250 
1251  // now save the characters
1252  for (i=0; i < u->insert_length; ++i)
1253  s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i);
1254  }
1255 
1257  }
1258 
1259  if (r.insert_length) {
1260  // easy case: need to insert n characters
1262  }
1263 
1264  state->cursor = r.where + r.insert_length;
1265 
1266  s->undo_point++;
1267  s->redo_point++;
1268 }
1269 
1270 static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length)
1271 {
1272  stb_text_createundo(&state->undostate, where, 0, length);
1273 }
1274 
1275 static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
1276 {
1277  int i;
1278  STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
1279  if (p) {
1280  for (i=0; i < length; ++i)
1281  p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
1282  }
1283 }
1284 
1285 static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
1286 {
1287  int i;
1288  STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
1289  if (p) {
1290  for (i=0; i < old_length; ++i)
1291  p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
1292  }
1293 }
1294 
1295 // reset the state to default
1296 static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line)
1297 {
1298  state->undostate.undo_point = 0;
1299  state->undostate.undo_char_point = 0;
1302  state->select_end = state->select_start = 0;
1303  state->cursor = 0;
1304  state->has_preferred_x = 0;
1305  state->preferred_x = 0;
1306  state->cursor_at_end_of_line = 0;
1307  state->initialized = 1;
1308  state->single_line = (unsigned char) is_single_line;
1309  state->insert_mode = 0;
1310 }
1311 
1312 // API initialize
1313 static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
1314 {
1315  stb_textedit_clear_state(state, is_single_line);
1316 }
1317 #endif//STB_TEXTEDIT_IMPLEMENTATION
short char_storage
Definition: stb_textedit.h:299
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
Definition: imgui.cpp:666
GLint y
#define STB_TEXTEDIT_K_LINESTART
Definition: imgui.cpp:7533
GLenum GLenum GLsizei void * row
static ImWchar STB_TEXTEDIT_NEWLINE
Definition: imgui.cpp:7465
static void stb_textedit_move_to_first(STB_TexteditState *state)
Definition: imgui.cpp:597
GLdouble s
static void stb_textedit_discard_redo(StbUndoState *state)
Definition: imgui.cpp:1089
static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
Definition: imgui.cpp:1314
GLfloat GLfloat p
Definition: glext.h:12687
unsigned char initialized
Definition: stb_textedit.h:337
static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
Definition: imgui.cpp:450
float baseline_y_delta
Definition: stb_textedit.h:357
short undo_char_point
Definition: stb_textedit.h:308
static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui.cpp:7462
static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING *obj)
Definition: imgui.cpp:7461
#define STB_TEXTEDIT_K_UNDO
Definition: imgui.cpp:7539
GLdouble GLdouble GLdouble w
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key)
Definition: imgui.cpp:697
#define STB_TEXTEDIT_K_TEXTEND
Definition: imgui.cpp:7536
GLdouble GLdouble z
GLdouble n
Definition: glext.h:1966
#define STB_TEXTEDIT_K_SHIFT
Definition: imgui.cpp:7543
StbUndoState undostate
Definition: stb_textedit.h:342
static void stb_textedit_flush_redo(StbUndoState *state)
Definition: imgui.cpp:1060
#define STB_TEXTEDIT_K_REDO
Definition: imgui.cpp:7540
static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
Definition: imgui.cpp:563
#define STB_TEXTEDIT_K_DOWN
Definition: imgui.cpp:7532
#define STB_TEXTEDIT_K_LINEEND
Definition: imgui.cpp:7534
#define STB_TEXTEDIT_GETWIDTH_NEWLINE
GLenum GLsizei len
Definition: glext.h:3285
GLuint64 key
Definition: glext.h:8966
unsigned char has_preferred_x
Definition: stb_textedit.h:338
static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
Definition: imgui.cpp:571
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
Definition: imgui.cpp:1153
#define STB_TEXTEDIT_MOVEWORDLEFT
Definition: imgui.cpp:7488
static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING *obj, int pos, const ImWchar *new_text, int new_text_len)
Definition: imgui.cpp:7506
const GLubyte * c
Definition: glext.h:12690
GLdouble GLdouble r
static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING *obj, int line_start_idx, int char_idx)
Definition: imgui.cpp:7463
GLdouble x
#define STB_TEXTEDIT_UNDOSTATECOUNT
Definition: stb_textedit.h:281
#define STB_TEXTEDIT_CHARTYPE
Definition: stb_textedit.h:287
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
Definition: imgui.cpp:1286
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]
Definition: stb_textedit.h:306
static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line)
Definition: imgui.cpp:1297
static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
Definition: imgui.cpp:489
static STB_TEXTEDIT_CHARTYPE * stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
Definition: imgui.cpp:1133
unsigned char padding3
Definition: stb_textedit.h:340
unsigned char single_line
Definition: stb_textedit.h:339
GLint GLsizei GLsizei height
static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING *obj, int pos, int n)
Definition: imgui.cpp:7491
#define STB_TEXTEDIT_MOVEWORDRIGHT
Definition: imgui.cpp:7489
def find(dir, mask)
Definition: file.py:25
static void stb_textedit_discard_undo(StbUndoState *state)
Definition: imgui.cpp:1067
GLuint GLfloat x0
Definition: glext.h:9721
GLuint start
#define STB_TEXTEDIT_UNDOCHARCOUNT
Definition: stb_textedit.h:284
static int STB_TEXTEDIT_KEYTOTEXT(int key)
Definition: imgui.cpp:7464
#define STB_TEXT_HAS_SELECTION(s)
Definition: imgui.cpp:546
GLint first
#define STB_TEXTEDIT_K_DELETE
Definition: imgui.cpp:7537
unsigned char insert_mode
Definition: stb_textedit.h:328
static void stb_textedit_sortselection(STB_TexteditState *state)
Definition: imgui.cpp:587
#define STB_TEXTEDIT_K_BACKSPACE
Definition: imgui.cpp:7538
short delete_length
Definition: stb_textedit.h:298
#define STB_TEXTEDIT_K_WORDLEFT
Definition: imgui.cpp:7541
unsigned char cursor_at_end_of_line
Definition: stb_textedit.h:336
static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
Definition: imgui.cpp:677
short redo_point
Definition: stb_textedit.h:307
static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
Definition: imgui.cpp:657
short insert_length
Definition: stb_textedit.h:297
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow *r, STB_TEXTEDIT_STRING *obj, int line_start_idx)
Definition: imgui.cpp:7466
#define STB_TEXTEDIT_POSITIONTYPE
Definition: stb_textedit.h:290
#define STB_TEXTEDIT_memmove
Definition: imgui.cpp:379
#define STB_TEXTEDIT_K_WORDRIGHT
Definition: imgui.cpp:7542
#define STB_TEXTEDIT_K_RIGHT
Definition: imgui.cpp:7530
#define STB_TEXTEDIT_STRING
#define STB_TEXTEDIT_K_UP
Definition: imgui.cpp:7531
short redo_char_point
Definition: stb_textedit.h:308
float rs2_vector::* pos
#define STB_TEXTEDIT_K_TEXTSTART
Definition: imgui.cpp:7535
#define NULL
Definition: tinycthread.c:47
int i
GLenum GLuint GLenum GLsizei length
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length)
Definition: imgui.cpp:1271
static StbUndoRecord * stb_text_create_undo_record(StbUndoState *state, int numchars)
Definition: imgui.cpp:1109
short undo_point
Definition: stb_textedit.h:307
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
Definition: imgui.cpp:459
static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
Definition: imgui.cpp:389
STB_TEXTEDIT_POSITIONTYPE where
Definition: stb_textedit.h:296
static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
Definition: imgui.cpp:608
#define STB_TEXTEDIT_K_LEFT
Definition: imgui.cpp:7529
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
Definition: imgui.cpp:1276
StbUndoRecord undo_rec[STB_TEXTEDIT_UNDOSTATECOUNT]
Definition: stb_textedit.h:305
static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
Definition: imgui.cpp:549
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
Definition: imgui.cpp:1221


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:50:10