| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1 |
// [DEAR IMGUI] |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
2 |
// This is a slightly modified version of stb_textedit.h 1.14. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
3 |
// Those changes would need to be pushed into nothings/stb: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
4 |
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
5 |
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
6 |
// - Added name to struct or it may be forward declared in our code. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
7 |
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
8 |
// Grep for [DEAR IMGUI] to find the changes. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
9 |
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_* |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
10 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
11 |
// stb_textedit.h - v1.14 - public domain - Sean Barrett |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
12 |
// Development of this library was sponsored by RAD Game Tools |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
13 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
14 |
// This C header file implements the guts of a multi-line text-editing |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
15 |
// widget; you implement display, word-wrapping, and low-level string |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
16 |
// insertion/deletion, and stb_textedit will map user inputs into |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
17 |
// insertions & deletions, plus updates to the cursor position, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
18 |
// selection state, and undo state. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
19 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
20 |
// It is intended for use in games and other systems that need to build |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
21 |
// their own custom widgets and which do not have heavy text-editing |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
22 |
// requirements (this library is not recommended for use for editing large |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
23 |
// texts, as its performance does not scale and it has limited undo). |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
24 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
25 |
// Non-trivial behaviors are modelled after Windows text controls. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
26 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
27 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
28 |
// LICENSE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
29 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
30 |
// See end of file for license information. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
31 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
32 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
33 |
// DEPENDENCIES |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
34 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
35 |
// Uses the C runtime function 'memmove', which you can override |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
36 |
// by defining IMSTB_TEXTEDIT_memmove before the implementation. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
37 |
// Uses no other functions. Performs no runtime allocations. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
38 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
39 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
40 |
// VERSION HISTORY |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
41 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
42 |
// 1.14 (2021-07-11) page up/down, various fixes |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
43 |
// 1.13 (2019-02-07) fix bug in undo size management |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
44 |
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
45 |
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
46 |
// 1.10 (2016-10-25) suppress warnings about casting away const with -Wcast-qual |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
47 |
// 1.9 (2016-08-27) customizable move-by-word |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
48 |
// 1.8 (2016-04-02) better keyboard handling when mouse button is down |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
49 |
// 1.7 (2015-09-13) change y range handling in case baseline is non-0 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
50 |
// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
51 |
// 1.5 (2014-09-10) add support for secondary keys for OS X |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
52 |
// 1.4 (2014-08-17) fix signed/unsigned warnings |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
53 |
// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
54 |
// 1.2 (2014-05-27) fix some RAD types that had crept into the new code |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
55 |
// 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
56 |
// 1.0 (2012-07-26) improve documentation, initial public release |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
57 |
// 0.3 (2012-02-24) bugfixes, single-line mode; insert mode |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
58 |
// 0.2 (2011-11-28) fixes to undo/redo |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
59 |
// 0.1 (2010-07-08) initial version |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
60 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
61 |
// ADDITIONAL CONTRIBUTORS |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
62 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
63 |
// Ulf Winklemann: move-by-word in 1.1 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
64 |
// Fabian Giesen: secondary key inputs in 1.5 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
65 |
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
66 |
// Louis Schnellbach: page up/down in 1.14 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
67 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
68 |
// Bugfixes: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
69 |
// Scott Graham |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
70 |
// Daniel Keller |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
71 |
// Omar Cornut |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
72 |
// Dan Thompson |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
73 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
74 |
// USAGE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
75 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
76 |
// This file behaves differently depending on what symbols you define |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
77 |
// before including it. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
78 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
79 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
80 |
// Header-file mode: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
81 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
82 |
// If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
83 |
// it will operate in "header file" mode. In this mode, it declares a |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
84 |
// single public symbol, STB_TexteditState, which encapsulates the current |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
85 |
// state of a text widget (except for the string, which you will store |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
86 |
// separately). |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
87 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
88 |
// To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
89 |
// primitive type that defines a single character (e.g. char, wchar_t, etc). |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
90 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
91 |
// To save space or increase undo-ability, you can optionally define the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
92 |
// following things that are used by the undo system: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
93 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
94 |
// STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
95 |
// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
96 |
// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
97 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
98 |
// If you don't define these, they are set to permissive types and |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
99 |
// moderate sizes. The undo system does no memory allocations, so |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
100 |
// it grows STB_TexteditState by the worst-case storage which is (in bytes): |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
101 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
102 |
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
103 |
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
104 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
105 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
106 |
// Implementation mode: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
107 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
108 |
// If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
109 |
// will compile the implementation of the text edit widget, depending |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
110 |
// on a large number of symbols which must be defined before the include. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
111 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
112 |
// The implementation is defined only as static functions. You will then |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
113 |
// need to provide your own APIs in the same file which will access the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
114 |
// static functions. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
115 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
116 |
// The basic concept is that you provide a "string" object which |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
117 |
// behaves like an array of characters. stb_textedit uses indices to |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
118 |
// refer to positions in the string, implicitly representing positions |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
119 |
// in the displayed textedit. This is true for both plain text and |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
120 |
// rich text; even with rich text stb_truetype interacts with your |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
121 |
// code as if there was an array of all the displayed characters. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
122 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
123 |
// Symbols that must be the same in header-file and implementation mode: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
124 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
125 |
// STB_TEXTEDIT_CHARTYPE the character type |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
126 |
// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
127 |
// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
128 |
// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
129 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
130 |
// Symbols you must define for implementation mode: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
131 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
132 |
// STB_TEXTEDIT_STRING the type of object representing a string being edited, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
133 |
// typically this is a wrapper object with other data you need |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
134 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
135 |
// STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
136 |
// STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
137 |
// starting from character #n (see discussion below) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
138 |
// STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
139 |
// to the xpos of the i+1'th char for a line of characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
140 |
// starting at character #n (i.e. accounts for kerning |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
141 |
// with previous char) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
142 |
// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
143 |
// (return type is int, -1 means not valid to insert) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
144 |
// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
145 |
// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
146 |
// as manually wordwrapping for end-of-line positioning |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
147 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
148 |
// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
149 |
// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
150 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
151 |
// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
152 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
153 |
// STB_TEXTEDIT_K_LEFT keyboard input to move cursor left |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
154 |
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
155 |
// STB_TEXTEDIT_K_UP keyboard input to move cursor up |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
156 |
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
157 |
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
158 |
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
159 |
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
160 |
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
161 |
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
162 |
// STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
163 |
// STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
164 |
// STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
165 |
// STB_TEXTEDIT_K_UNDO keyboard input to perform undo |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
166 |
// STB_TEXTEDIT_K_REDO keyboard input to perform redo |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
167 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
168 |
// Optional: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
169 |
// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
170 |
// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'), |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
171 |
// required for default WORDLEFT/WORDRIGHT handlers |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
172 |
// STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
173 |
// STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
174 |
// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
175 |
// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
176 |
// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
177 |
// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
178 |
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
179 |
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
180 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
181 |
// Keyboard input must be encoded as a single integer value; e.g. a character code |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
182 |
// and some bitflags that represent shift states. to simplify the interface, SHIFT must |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
183 |
// be a bitflag, so we can test the shifted state of cursor movements to allow selection, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
184 |
// i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
185 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
186 |
// You can encode other things, such as CONTROL or ALT, in additional bits, and |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
187 |
// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
188 |
// my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
189 |
// bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
190 |
// and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
191 |
// API below. The control keys will only match WM_KEYDOWN events because of the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
192 |
// keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
193 |
// bit so it only decodes WM_CHAR events. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
194 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
195 |
// STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
196 |
// row of characters assuming they start on the i'th character--the width and |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
197 |
// the height and the number of characters consumed. This allows this library |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
198 |
// to traverse the entire layout incrementally. You need to compute word-wrapping |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
199 |
// here. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
200 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
201 |
// Each textfield keeps its own insert mode state, which is not how normal |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
202 |
// applications work. To keep an app-wide insert mode, update/copy the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
203 |
// "insert_mode" field of STB_TexteditState before/after calling API functions. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
204 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
205 |
// API |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
206 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
207 |
// void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
208 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
209 |
// void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
210 |
// void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
211 |
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
212 |
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
213 |
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
214 |
// void stb_textedit_text(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int text_len) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
215 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
216 |
// Each of these functions potentially updates the string and updates the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
217 |
// state. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
218 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
219 |
// initialize_state: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
220 |
// set the textedit state to a known good default state when initially |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
221 |
// constructing the textedit. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
222 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
223 |
// click: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
224 |
// call this with the mouse x,y on a mouse down; it will update the cursor |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
225 |
// and reset the selection start/end to the cursor point. the x,y must |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
226 |
// be relative to the text widget, with (0,0) being the top left. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
227 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
228 |
// drag: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
229 |
// call this with the mouse x,y on a mouse drag/up; it will update the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
230 |
// cursor and the selection end point |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
231 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
232 |
// cut: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
233 |
// call this to delete the current selection; returns true if there was |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
234 |
// one. you should FIRST copy the current selection to the system paste buffer. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
235 |
// (To copy, just copy the current selection out of the string yourself.) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
236 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
237 |
// paste: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
238 |
// call this to paste text at the current cursor point or over the current |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
239 |
// selection if there is one. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
240 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
241 |
// key: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
242 |
// call this for keyboard inputs sent to the textfield. you can use it |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
243 |
// for "key down" events or for "translated" key events. if you need to |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
244 |
// do both (as in Win32), or distinguish Unicode characters from control |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
245 |
// inputs, set a high bit to distinguish the two; then you can define the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
246 |
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
247 |
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
248 |
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
249 |
// anything other type you want before including. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
250 |
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
251 |
// transformed into text and stb_textedit_text() is automatically called. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
252 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
253 |
// text: [DEAR IMGUI] added 2024-09 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
254 |
// call this to text inputs sent to the textfield. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
255 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
256 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
257 |
// When rendering, you can read the cursor position and selection state from |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
258 |
// the STB_TexteditState. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
259 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
260 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
261 |
// Notes: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
262 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
263 |
// This is designed to be usable in IMGUI, so it allows for the possibility of |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
264 |
// running in an IMGUI that has NOT cached the multi-line layout. For this |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
265 |
// reason, it provides an interface that is compatible with computing the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
266 |
// layout incrementally--we try to make sure we make as few passes through |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
267 |
// as possible. (For example, to locate the mouse pointer in the text, we |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
268 |
// could define functions that return the X and Y positions of characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
269 |
// and binary search Y and then X, but if we're doing dynamic layout this |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
270 |
// will run the layout algorithm many times, so instead we manually search |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
271 |
// forward in one pass. Similar logic applies to e.g. up-arrow and |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
272 |
// down-arrow movement.) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
273 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
274 |
// If it's run in a widget that *has* cached the layout, then this is less |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
275 |
// efficient, but it's not horrible on modern computers. But you wouldn't |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
276 |
// want to edit million-line files with it. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
277 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
278 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
279 |
//////////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
280 |
//////////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
281 |
//// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
282 |
//// Header-file mode |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
283 |
//// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
284 |
//// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
285 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
286 |
#ifndef INCLUDE_IMSTB_TEXTEDIT_H |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
287 |
#define INCLUDE_IMSTB_TEXTEDIT_H |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
288 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
289 |
//////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
290 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
291 |
// STB_TexteditState |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
292 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
293 |
// Definition of STB_TexteditState which you should store |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
294 |
// per-textfield; it includes cursor position, selection state, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
295 |
// and undo state. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
296 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
297 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
298 |
#ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
299 |
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
300 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
301 |
#ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
302 |
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
303 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
304 |
#ifndef IMSTB_TEXTEDIT_CHARTYPE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
305 |
#define IMSTB_TEXTEDIT_CHARTYPE int |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
306 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
307 |
#ifndef IMSTB_TEXTEDIT_POSITIONTYPE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
308 |
#define IMSTB_TEXTEDIT_POSITIONTYPE int |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
309 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
310 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
311 |
typedef struct |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
312 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
313 |
// private data |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
314 |
IMSTB_TEXTEDIT_POSITIONTYPE where; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
315 |
IMSTB_TEXTEDIT_POSITIONTYPE insert_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
316 |
IMSTB_TEXTEDIT_POSITIONTYPE delete_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
317 |
int char_storage; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
318 |
} StbUndoRecord; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
319 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
320 |
typedef struct |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
321 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
322 |
// private data |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
323 |
StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
324 |
IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
325 |
short undo_point, redo_point; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
326 |
int undo_char_point, redo_char_point; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
327 |
} StbUndoState; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
328 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
329 |
typedef struct STB_TexteditState |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
330 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
331 |
///////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
332 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
333 |
// public data |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
334 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
335 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
336 |
int cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
337 |
// position of the text cursor within the string |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
338 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
339 |
int select_start; // selection start point |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
340 |
int select_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
341 |
// selection start and end point in characters; if equal, no selection. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
342 |
// note that start may be less than or greater than end (e.g. when |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
343 |
// dragging the mouse, start is where the initial click was, and you |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
344 |
// can drag in either direction) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
345 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
346 |
unsigned char insert_mode; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
347 |
// each textfield keeps its own insert mode state. to keep an app-wide |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
348 |
// insert mode, copy this value in/out of the app state |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
349 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
350 |
int row_count_per_page; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
351 |
// page size in number of row. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
352 |
// this value MUST be set to >0 for pageup or pagedown in multilines documents. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
353 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
354 |
///////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
355 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
356 |
// private data |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
357 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
358 |
unsigned char cursor_at_end_of_line; // not implemented yet |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
359 |
unsigned char initialized; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
360 |
unsigned char has_preferred_x; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
361 |
unsigned char single_line; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
362 |
unsigned char padding1, padding2, padding3; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
363 |
float preferred_x; // this determines where the cursor up/down tries to seek to along x |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
364 |
StbUndoState undostate; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
365 |
} STB_TexteditState; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
366 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
367 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
368 |
//////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
369 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
370 |
// StbTexteditRow |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
371 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
372 |
// Result of layout query, used by stb_textedit to determine where |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
373 |
// the text in each row is. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
374 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
375 |
// result of layout query |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
376 |
typedef struct |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
377 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
378 |
float x0,x1; // starting x location, end x location (allows for align=right, etc) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
379 |
float baseline_y_delta; // position of baseline relative to previous row's baseline |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
380 |
float ymin,ymax; // height of row above and below baseline |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
381 |
int num_chars; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
382 |
} StbTexteditRow; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
383 |
#endif //INCLUDE_IMSTB_TEXTEDIT_H |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
384 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
385 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
386 |
//////////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
387 |
//////////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
388 |
//// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
389 |
//// Implementation mode |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
390 |
//// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
391 |
//// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
392 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
393 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
394 |
// implementation isn't include-guarded, since it might have indirectly |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
395 |
// included just the "header" portion |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
396 |
#ifdef IMSTB_TEXTEDIT_IMPLEMENTATION |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
397 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
398 |
#ifndef IMSTB_TEXTEDIT_memmove |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
399 |
#include <string.h> |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
400 |
#define IMSTB_TEXTEDIT_memmove memmove |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
401 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
402 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
403 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
404 |
///////////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
405 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
406 |
// Mouse input handling |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
407 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
408 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
409 |
// traverse the layout to locate the nearest character to a display position |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
410 |
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
411 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
412 |
StbTexteditRow r; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
413 |
int n = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
414 |
float base_y = 0, prev_x; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
415 |
int i=0, k; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
416 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
417 |
r.x0 = r.x1 = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
418 |
r.ymin = r.ymax = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
419 |
r.num_chars = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
420 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
421 |
// search rows to find one that straddles 'y' |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
422 |
while (i < n) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
423 |
STB_TEXTEDIT_LAYOUTROW(&r, str, i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
424 |
if (r.num_chars <= 0) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
425 |
return n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
426 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
427 |
if (i==0 && y < base_y + r.ymin) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
428 |
return 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
429 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
430 |
if (y < base_y + r.ymax) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
431 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
432 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
433 |
i += r.num_chars; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
434 |
base_y += r.baseline_y_delta; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
435 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
436 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
437 |
// below all text, return 'after' last character |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
438 |
if (i >= n) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
439 |
return n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
440 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
441 |
// check if it's before the beginning of the line |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
442 |
if (x < r.x0) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
443 |
return i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
444 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
445 |
// check if it's before the end of the line |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
446 |
if (x < r.x1) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
447 |
// search characters in row for one that straddles 'x' |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
448 |
prev_x = r.x0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
449 |
for (k=0; k < r.num_chars; k = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k) - i) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
450 |
float w = STB_TEXTEDIT_GETWIDTH(str, i, k); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
451 |
if (x < prev_x+w) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
452 |
if (x < prev_x+w/2) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
453 |
return k+i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
454 |
else |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
455 |
return IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
456 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
457 |
prev_x += w; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
458 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
459 |
// shouldn't happen, but if it does, fall through to end-of-line case |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
460 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
461 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
462 |
// if the last character is a newline, return that. otherwise return 'after' the last character |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
463 |
if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
464 |
return i+r.num_chars-1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
465 |
else |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
466 |
return i+r.num_chars; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
467 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
468 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
469 |
// API click: on mouse down, move the cursor to the clicked location, and reset the selection |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
470 |
static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
471 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
472 |
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
473 |
// goes off the top or bottom of the text |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
474 |
if( state->single_line ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
475 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
476 |
StbTexteditRow r; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
477 |
STB_TEXTEDIT_LAYOUTROW(&r, str, 0); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
478 |
y = r.ymin; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
479 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
480 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
481 |
state->cursor = stb_text_locate_coord(str, x, y); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
482 |
state->select_start = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
483 |
state->select_end = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
484 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
485 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
486 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
487 |
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
488 |
static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
489 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
490 |
int p = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
491 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
492 |
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
493 |
// goes off the top or bottom of the text |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
494 |
if( state->single_line ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
495 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
496 |
StbTexteditRow r; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
497 |
STB_TEXTEDIT_LAYOUTROW(&r, str, 0); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
498 |
y = r.ymin; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
499 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
500 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
501 |
if (state->select_start == state->select_end) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
502 |
state->select_start = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
503 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
504 |
p = stb_text_locate_coord(str, x, y); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
505 |
state->cursor = state->select_end = p; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
506 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
507 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
508 |
///////////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
509 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
510 |
// Keyboard input handling |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
511 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
512 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
513 |
// forward declarations |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
514 |
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
515 |
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
516 |
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
517 |
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
518 |
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
519 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
520 |
typedef struct |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
521 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
522 |
float x,y; // position of n'th character |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
523 |
float height; // height of line |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
524 |
int first_char, length; // first char of row, and length |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
525 |
int prev_first; // first char of previous row |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
526 |
} StbFindState; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
527 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
528 |
// find the x/y location of a character, and remember info about the previous row in |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
529 |
// case we get a move-up event (for page up, we'll have to rescan) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
530 |
static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
531 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
532 |
StbTexteditRow r; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
533 |
int prev_start = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
534 |
int z = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
535 |
int i=0, first; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
536 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
537 |
if (n == z && single_line) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
538 |
// special case if it's at the end (may not be needed?) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
539 |
STB_TEXTEDIT_LAYOUTROW(&r, str, 0); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
540 |
find->y = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
541 |
find->first_char = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
542 |
find->length = z; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
543 |
find->height = r.ymax - r.ymin; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
544 |
find->x = r.x1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
545 |
return; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
546 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
547 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
548 |
// search rows to find the one that straddles character n |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
549 |
find->y = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
550 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
551 |
for(;;) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
552 |
STB_TEXTEDIT_LAYOUTROW(&r, str, i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
553 |
if (n < i + r.num_chars) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
554 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
555 |
if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] special handling for last line |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
556 |
break; // [DEAR IMGUI] |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
557 |
prev_start = i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
558 |
i += r.num_chars; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
559 |
find->y += r.baseline_y_delta; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
560 |
if (i == z) // [DEAR IMGUI] |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
561 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
562 |
r.num_chars = 0; // [DEAR IMGUI] |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
563 |
break; // [DEAR IMGUI] |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
564 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
565 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
566 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
567 |
find->first_char = first = i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
568 |
find->length = r.num_chars; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
569 |
find->height = r.ymax - r.ymin; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
570 |
find->prev_first = prev_start; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
571 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
572 |
// now scan to find xpos |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
573 |
find->x = r.x0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
574 |
for (i=0; first+i < n; i = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, first + i) - first) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
575 |
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
576 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
577 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
578 |
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
579 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
580 |
// make the selection/cursor state valid if client altered the string |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
581 |
static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
582 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
583 |
int n = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
584 |
if (STB_TEXT_HAS_SELECTION(state)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
585 |
if (state->select_start > n) state->select_start = n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
586 |
if (state->select_end > n) state->select_end = n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
587 |
// if clamping forced them to be equal, move the cursor to match |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
588 |
if (state->select_start == state->select_end) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
589 |
state->cursor = state->select_start; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
590 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
591 |
if (state->cursor > n) state->cursor = n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
592 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
593 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
594 |
// delete characters while updating undo |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
595 |
static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
596 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
597 |
stb_text_makeundo_delete(str, state, where, len); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
598 |
STB_TEXTEDIT_DELETECHARS(str, where, len); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
599 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
600 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
601 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
602 |
// delete the section |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
603 |
static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
604 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
605 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
606 |
if (STB_TEXT_HAS_SELECTION(state)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
607 |
if (state->select_start < state->select_end) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
608 |
stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
609 |
state->select_end = state->cursor = state->select_start; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
610 |
} else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
611 |
stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
612 |
state->select_start = state->cursor = state->select_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
613 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
614 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
615 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
616 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
617 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
618 |
// canoncialize the selection so start <= end |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
619 |
static void stb_textedit_sortselection(STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
620 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
621 |
if (state->select_end < state->select_start) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
622 |
int temp = state->select_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
623 |
state->select_end = state->select_start; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
624 |
state->select_start = temp; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
625 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
626 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
627 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
628 |
// move cursor to first character of selection |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
629 |
static void stb_textedit_move_to_first(STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
630 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
631 |
if (STB_TEXT_HAS_SELECTION(state)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
632 |
stb_textedit_sortselection(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
633 |
state->cursor = state->select_start; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
634 |
state->select_end = state->select_start; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
635 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
636 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
637 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
638 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
639 |
// move cursor to last character of selection |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
640 |
static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
641 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
642 |
if (STB_TEXT_HAS_SELECTION(state)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
643 |
stb_textedit_sortselection(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
644 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
645 |
state->cursor = state->select_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
646 |
state->select_start = state->select_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
647 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
648 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
649 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
650 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
651 |
// [DEAR IMGUI] |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
652 |
// Functions must be implemented for UTF8 support |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
653 |
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
654 |
// There is not necessarily a '[DEAR IMGUI]' at the usage sites. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
655 |
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
656 |
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx) (idx - 1) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
657 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
658 |
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
659 |
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
660 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
661 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
662 |
#ifdef STB_TEXTEDIT_IS_SPACE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
663 |
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
664 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
665 |
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
666 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
667 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
668 |
#ifndef STB_TEXTEDIT_MOVEWORDLEFT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
669 |
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
670 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
671 |
--c; // always move at least one character |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
672 |
while( c >= 0 && !is_word_boundary( str, c ) ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
673 |
--c; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
674 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
675 |
if( c < 0 ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
676 |
c = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
677 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
678 |
return c; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
679 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
680 |
#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
681 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
682 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
683 |
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
684 |
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
685 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
686 |
const int len = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
687 |
++c; // always move at least one character |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
688 |
while( c < len && !is_word_boundary( str, c ) ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
689 |
++c; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
690 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
691 |
if( c > len ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
692 |
c = len; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
693 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
694 |
return c; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
695 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
696 |
#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
697 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
698 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
699 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
700 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
701 |
// update selection and cursor to match each other |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
702 |
static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
703 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
704 |
if (!STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
705 |
state->select_start = state->select_end = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
706 |
else |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
707 |
state->cursor = state->select_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
708 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
709 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
710 |
// API cut: delete selection |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
711 |
static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
712 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
713 |
if (STB_TEXT_HAS_SELECTION(state)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
714 |
stb_textedit_delete_selection(str,state); // implicitly clamps |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
715 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
716 |
return 1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
717 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
718 |
return 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
719 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
720 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
721 |
// API paste: replace existing selection with passed-in text |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
722 |
static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
723 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
724 |
// if there's a selection, the paste should delete it |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
725 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
726 |
stb_textedit_delete_selection(str,state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
727 |
// try to insert the characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
728 |
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
729 |
stb_text_makeundo_insert(state, state->cursor, len); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
730 |
state->cursor += len; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
731 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
732 |
return 1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
733 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
734 |
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
735 |
return 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
736 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
737 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
738 |
#ifndef STB_TEXTEDIT_KEYTYPE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
739 |
#define STB_TEXTEDIT_KEYTYPE int |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
740 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
741 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
742 |
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
743 |
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
744 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
745 |
// can't add newline in single-line mode |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
746 |
if (text[0] == '\n' && state->single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
747 |
return; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
748 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
749 |
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
750 |
stb_text_makeundo_replace(str, state, state->cursor, 1, 1); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
751 |
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
752 |
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
753 |
state->cursor += text_len; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
754 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
755 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
756 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
757 |
else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
758 |
stb_textedit_delete_selection(str, state); // implicitly clamps |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
759 |
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
760 |
stb_text_makeundo_insert(state, state->cursor, text_len); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
761 |
state->cursor += text_len; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
762 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
763 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
764 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
765 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
766 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
767 |
// API key: process a keyboard input |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
768 |
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
769 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
770 |
retry: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
771 |
switch (key) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
772 |
default: { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
773 |
#ifdef STB_TEXTEDIT_KEYTOTEXT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
774 |
int c = STB_TEXTEDIT_KEYTOTEXT(key); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
775 |
if (c > 0) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
776 |
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
777 |
stb_textedit_text(str, state, &ch, 1); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
778 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
779 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
780 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
781 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
782 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
783 |
#ifdef STB_TEXTEDIT_K_INSERT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
784 |
case STB_TEXTEDIT_K_INSERT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
785 |
state->insert_mode = !state->insert_mode; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
786 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
787 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
788 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
789 |
case STB_TEXTEDIT_K_UNDO: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
790 |
stb_text_undo(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
791 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
792 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
793 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
794 |
case STB_TEXTEDIT_K_REDO: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
795 |
stb_text_redo(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
796 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
797 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
798 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
799 |
case STB_TEXTEDIT_K_LEFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
800 |
// if currently there's a selection, move cursor to start of selection |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
801 |
if (STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
802 |
stb_textedit_move_to_first(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
803 |
else |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
804 |
if (state->cursor > 0) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
805 |
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
806 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
807 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
808 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
809 |
case STB_TEXTEDIT_K_RIGHT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
810 |
// if currently there's a selection, move cursor to end of selection |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
811 |
if (STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
812 |
stb_textedit_move_to_last(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
813 |
else |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
814 |
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
815 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
816 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
817 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
818 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
819 |
case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
820 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
821 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
822 |
// move selection left |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
823 |
if (state->select_end > 0) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
824 |
state->select_end = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->select_end); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
825 |
state->cursor = state->select_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
826 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
827 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
828 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
829 |
#ifdef STB_TEXTEDIT_MOVEWORDLEFT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
830 |
case STB_TEXTEDIT_K_WORDLEFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
831 |
if (STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
832 |
stb_textedit_move_to_first(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
833 |
else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
834 |
state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
835 |
stb_textedit_clamp( str, state ); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
836 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
837 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
838 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
839 |
case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
840 |
if( !STB_TEXT_HAS_SELECTION( state ) ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
841 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
842 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
843 |
state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
844 |
state->select_end = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
845 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
846 |
stb_textedit_clamp( str, state ); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
847 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
848 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
849 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
850 |
#ifdef STB_TEXTEDIT_MOVEWORDRIGHT |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
851 |
case STB_TEXTEDIT_K_WORDRIGHT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
852 |
if (STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
853 |
stb_textedit_move_to_last(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
854 |
else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
855 |
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
856 |
stb_textedit_clamp( str, state ); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
857 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
858 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
859 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
860 |
case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
861 |
if( !STB_TEXT_HAS_SELECTION( state ) ) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
862 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
863 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
864 |
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
865 |
state->select_end = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
866 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
867 |
stb_textedit_clamp( str, state ); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
868 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
869 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
870 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
871 |
case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
872 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
873 |
// move selection right |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
874 |
state->select_end = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->select_end); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
875 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
876 |
state->cursor = state->select_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
877 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
878 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
879 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
880 |
case STB_TEXTEDIT_K_DOWN: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
881 |
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
882 |
case STB_TEXTEDIT_K_PGDOWN: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
883 |
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
884 |
StbFindState find; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
885 |
StbTexteditRow row; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
886 |
int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
887 |
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
888 |
int row_count = is_page ? state->row_count_per_page : 1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
889 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
890 |
if (!is_page && state->single_line) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
891 |
// on windows, up&down in single-line behave like left&right |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
892 |
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
893 |
goto retry; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
894 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
895 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
896 |
if (sel) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
897 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
898 |
else if (STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
899 |
stb_textedit_move_to_last(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
900 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
901 |
// compute current position of cursor point |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
902 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
903 |
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
904 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
905 |
for (j = 0; j < row_count; ++j) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
906 |
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
907 |
int start = find.first_char + find.length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
908 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
909 |
if (find.length == 0) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
910 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
911 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
912 |
// [DEAR IMGUI] |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
913 |
// going down while being on the last line shouldn't bring us to that line end |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
914 |
if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
915 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
916 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
917 |
// now find character position down a row |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
918 |
state->cursor = start; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
919 |
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
920 |
x = row.x0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
921 |
for (i=0; i < row.num_chars; ++i) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
922 |
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
923 |
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
924 |
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
925 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
926 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
927 |
x += dx; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
928 |
if (x > goal_x) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
929 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
930 |
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
931 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
932 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
933 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
934 |
state->has_preferred_x = 1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
935 |
state->preferred_x = goal_x; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
936 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
937 |
if (sel) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
938 |
state->select_end = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
939 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
940 |
// go to next line |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
941 |
find.first_char = find.first_char + find.length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
942 |
find.length = row.num_chars; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
943 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
944 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
945 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
946 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
947 |
case STB_TEXTEDIT_K_UP: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
948 |
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
949 |
case STB_TEXTEDIT_K_PGUP: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
950 |
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
951 |
StbFindState find; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
952 |
StbTexteditRow row; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
953 |
int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
954 |
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
955 |
int row_count = is_page ? state->row_count_per_page : 1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
956 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
957 |
if (!is_page && state->single_line) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
958 |
// on windows, up&down become left&right |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
959 |
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
960 |
goto retry; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
961 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
962 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
963 |
if (sel) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
964 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
965 |
else if (STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
966 |
stb_textedit_move_to_first(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
967 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
968 |
// compute current position of cursor point |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
969 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
970 |
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
971 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
972 |
for (j = 0; j < row_count; ++j) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
973 |
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
974 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
975 |
// can only go up if there's a previous row |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
976 |
if (find.prev_first == find.first_char) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
977 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
978 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
979 |
// now find character position up a row |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
980 |
state->cursor = find.prev_first; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
981 |
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
982 |
x = row.x0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
983 |
for (i=0; i < row.num_chars; ++i) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
984 |
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
985 |
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
986 |
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
987 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
988 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
989 |
x += dx; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
990 |
if (x > goal_x) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
991 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
992 |
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
993 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
994 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
995 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
996 |
state->has_preferred_x = 1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
997 |
state->preferred_x = goal_x; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
998 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
999 |
if (sel) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1000 |
state->select_end = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1001 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1002 |
// go to previous line |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1003 |
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1004 |
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1005 |
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1006 |
--prev_scan; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1007 |
find.first_char = find.prev_first; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1008 |
find.prev_first = prev_scan; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1009 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1010 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1011 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1012 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1013 |
case STB_TEXTEDIT_K_DELETE: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1014 |
case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1015 |
if (STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1016 |
stb_textedit_delete_selection(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1017 |
else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1018 |
int n = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1019 |
if (state->cursor < n) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1020 |
stb_textedit_delete(str, state, state->cursor, IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor) - state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1021 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1022 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1023 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1024 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1025 |
case STB_TEXTEDIT_K_BACKSPACE: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1026 |
case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1027 |
if (STB_TEXT_HAS_SELECTION(state)) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1028 |
stb_textedit_delete_selection(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1029 |
else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1030 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1031 |
if (state->cursor > 0) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1032 |
int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1033 |
stb_textedit_delete(str, state, prev, state->cursor - prev); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1034 |
state->cursor = prev; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1035 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1036 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1037 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1038 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1039 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1040 |
#ifdef STB_TEXTEDIT_K_TEXTSTART2 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1041 |
case STB_TEXTEDIT_K_TEXTSTART2: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1042 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1043 |
case STB_TEXTEDIT_K_TEXTSTART: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1044 |
state->cursor = state->select_start = state->select_end = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1045 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1046 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1047 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1048 |
#ifdef STB_TEXTEDIT_K_TEXTEND2 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1049 |
case STB_TEXTEDIT_K_TEXTEND2: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1050 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1051 |
case STB_TEXTEDIT_K_TEXTEND: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1052 |
state->cursor = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1053 |
state->select_start = state->select_end = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1054 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1055 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1056 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1057 |
#ifdef STB_TEXTEDIT_K_TEXTSTART2 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1058 |
case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1059 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1060 |
case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1061 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1062 |
state->cursor = state->select_end = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1063 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1064 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1065 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1066 |
#ifdef STB_TEXTEDIT_K_TEXTEND2 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1067 |
case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1068 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1069 |
case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1070 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1071 |
state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1072 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1073 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1074 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1075 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1076 |
#ifdef STB_TEXTEDIT_K_LINESTART2 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1077 |
case STB_TEXTEDIT_K_LINESTART2: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1078 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1079 |
case STB_TEXTEDIT_K_LINESTART: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1080 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1081 |
stb_textedit_move_to_first(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1082 |
if (state->single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1083 |
state->cursor = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1084 |
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1085 |
--state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1086 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1087 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1088 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1089 |
#ifdef STB_TEXTEDIT_K_LINEEND2 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1090 |
case STB_TEXTEDIT_K_LINEEND2: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1091 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1092 |
case STB_TEXTEDIT_K_LINEEND: { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1093 |
int n = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1094 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1095 |
stb_textedit_move_to_first(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1096 |
if (state->single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1097 |
state->cursor = n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1098 |
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1099 |
++state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1100 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1101 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1102 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1103 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1104 |
#ifdef STB_TEXTEDIT_K_LINESTART2 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1105 |
case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1106 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1107 |
case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1108 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1109 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1110 |
if (state->single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1111 |
state->cursor = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1112 |
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1113 |
--state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1114 |
state->select_end = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1115 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1116 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1117 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1118 |
#ifdef STB_TEXTEDIT_K_LINEEND2 |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1119 |
case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1120 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1121 |
case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1122 |
int n = STB_TEXTEDIT_STRINGLEN(str); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1123 |
stb_textedit_clamp(str, state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1124 |
stb_textedit_prep_selection_at_cursor(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1125 |
if (state->single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1126 |
state->cursor = n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1127 |
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1128 |
++state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1129 |
state->select_end = state->cursor; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1130 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1131 |
break; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1132 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1133 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1134 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1135 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1136 |
///////////////////////////////////////////////////////////////////////////// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1137 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1138 |
// Undo processing |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1139 |
// |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1140 |
// @OPTIMIZE: the undo/redo buffer should be circular |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1141 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1142 |
static void stb_textedit_flush_redo(StbUndoState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1143 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1144 |
state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1145 |
state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1146 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1147 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1148 |
// discard the oldest entry in the undo list |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1149 |
static void stb_textedit_discard_undo(StbUndoState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1150 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1151 |
if (state->undo_point > 0) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1152 |
// if the 0th undo state has characters, clean those up |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1153 |
if (state->undo_rec[0].char_storage >= 0) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1154 |
int n = state->undo_rec[0].insert_length, i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1155 |
// delete n characters from all other records |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1156 |
state->undo_char_point -= n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1157 |
IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE))); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1158 |
for (i=0; i < state->undo_point; ++i) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1159 |
if (state->undo_rec[i].char_storage >= 0) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1160 |
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1161 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1162 |
--state->undo_point; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1163 |
IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1164 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1165 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1166 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1167 |
// discard the oldest entry in the redo list--it's bad if this |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1168 |
// ever happens, but because undo & redo have to store the actual |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1169 |
// characters in different cases, the redo character buffer can |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1170 |
// fill up even though the undo buffer didn't |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1171 |
static void stb_textedit_discard_redo(StbUndoState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1172 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1173 |
int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1174 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1175 |
if (state->redo_point <= k) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1176 |
// if the k'th undo state has characters, clean those up |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1177 |
if (state->undo_rec[k].char_storage >= 0) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1178 |
int n = state->undo_rec[k].insert_length, i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1179 |
// move the remaining redo character data to the end of the buffer |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1180 |
state->redo_char_point += n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1181 |
IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE))); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1182 |
// adjust the position of all the other records to account for above memmove |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1183 |
for (i=state->redo_point; i < k; ++i) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1184 |
if (state->undo_rec[i].char_storage >= 0) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1185 |
state->undo_rec[i].char_storage += n; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1186 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1187 |
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point' |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1188 |
// [DEAR IMGUI] |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1189 |
size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0])); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1190 |
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1191 |
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1192 |
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1193 |
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1194 |
IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1195 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1196 |
// now move redo_point to point to the new one |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1197 |
++state->redo_point; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1198 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1199 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1200 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1201 |
static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1202 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1203 |
// any time we create a new undo record, we discard redo |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1204 |
stb_textedit_flush_redo(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1205 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1206 |
// if we have no free records, we have to make room, by sliding the |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1207 |
// existing records down |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1208 |
if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1209 |
stb_textedit_discard_undo(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1210 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1211 |
// if the characters to store won't possibly fit in the buffer, we can't undo |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1212 |
if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1213 |
state->undo_point = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1214 |
state->undo_char_point = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1215 |
return NULL; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1216 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1217 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1218 |
// if we don't have enough free characters in the buffer, we have to make room |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1219 |
while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1220 |
stb_textedit_discard_undo(state); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1221 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1222 |
return &state->undo_rec[state->undo_point++]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1223 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1224 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1225 |
static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1226 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1227 |
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1228 |
if (r == NULL) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1229 |
return NULL; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1230 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1231 |
r->where = pos; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1232 |
r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1233 |
r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1234 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1235 |
if (insert_len == 0) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1236 |
r->char_storage = -1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1237 |
return NULL; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1238 |
} else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1239 |
r->char_storage = state->undo_char_point; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1240 |
state->undo_char_point += insert_len; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1241 |
return &state->undo_char[r->char_storage]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1242 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1243 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1244 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1245 |
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1246 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1247 |
StbUndoState *s = &state->undostate; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1248 |
StbUndoRecord u, *r; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1249 |
if (s->undo_point == 0) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1250 |
return; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1251 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1252 |
// we need to do two things: apply the undo record, and create a redo record |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1253 |
u = s->undo_rec[s->undo_point-1]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1254 |
r = &s->undo_rec[s->redo_point-1]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1255 |
r->char_storage = -1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1256 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1257 |
r->insert_length = u.delete_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1258 |
r->delete_length = u.insert_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1259 |
r->where = u.where; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1260 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1261 |
if (u.delete_length) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1262 |
// if the undo record says to delete characters, then the redo record will |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1263 |
// need to re-insert the characters that get deleted, so we need to store |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1264 |
// them. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1265 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1266 |
// there are three cases: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1267 |
// there's enough room to store the characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1268 |
// characters stored for *redoing* don't leave room for redo |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1269 |
// characters stored for *undoing* don't leave room for redo |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1270 |
// if the last is true, we have to bail |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1271 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1272 |
if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1273 |
// the undo records take up too much character space; there's no space to store the redo characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1274 |
r->insert_length = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1275 |
} else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1276 |
int i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1277 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1278 |
// there's definitely room to store the characters eventually |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1279 |
while (s->undo_char_point + u.delete_length > s->redo_char_point) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1280 |
// should never happen: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1281 |
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1282 |
return; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1283 |
// there's currently not enough room, so discard a redo record |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1284 |
stb_textedit_discard_redo(s); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1285 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1286 |
r = &s->undo_rec[s->redo_point-1]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1287 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1288 |
r->char_storage = s->redo_char_point - u.delete_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1289 |
s->redo_char_point = s->redo_char_point - u.delete_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1290 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1291 |
// now save the characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1292 |
for (i=0; i < u.delete_length; ++i) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1293 |
s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1294 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1295 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1296 |
// now we can carry out the deletion |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1297 |
STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1298 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1299 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1300 |
// check type of recorded action: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1301 |
if (u.insert_length) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1302 |
// easy case: was a deletion, so we need to insert n characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1303 |
STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1304 |
s->undo_char_point -= u.insert_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1305 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1306 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1307 |
state->cursor = u.where + u.insert_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1308 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1309 |
s->undo_point--; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1310 |
s->redo_point--; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1311 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1312 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1313 |
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1314 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1315 |
StbUndoState *s = &state->undostate; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1316 |
StbUndoRecord *u, r; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1317 |
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1318 |
return; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1319 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1320 |
// we need to do two things: apply the redo record, and create an undo record |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1321 |
u = &s->undo_rec[s->undo_point]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1322 |
r = s->undo_rec[s->redo_point]; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1323 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1324 |
// we KNOW there must be room for the undo record, because the redo record |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1325 |
// was derived from an undo record |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1326 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1327 |
u->delete_length = r.insert_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1328 |
u->insert_length = r.delete_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1329 |
u->where = r.where; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1330 |
u->char_storage = -1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1331 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1332 |
if (r.delete_length) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1333 |
// the redo record requires us to delete characters, so the undo record |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1334 |
// needs to store the characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1335 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1336 |
if (s->undo_char_point + u->insert_length > s->redo_char_point) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1337 |
u->insert_length = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1338 |
u->delete_length = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1339 |
} else { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1340 |
int i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1341 |
u->char_storage = s->undo_char_point; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1342 |
s->undo_char_point = s->undo_char_point + u->insert_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1343 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1344 |
// now save the characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1345 |
for (i=0; i < u->insert_length; ++i) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1346 |
s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1347 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1348 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1349 |
STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1350 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1351 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1352 |
if (r.insert_length) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1353 |
// easy case: need to insert n characters |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1354 |
STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1355 |
s->redo_char_point += r.insert_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1356 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1357 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1358 |
state->cursor = r.where + r.insert_length; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1359 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1360 |
s->undo_point++; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1361 |
s->redo_point++; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1362 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1363 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1364 |
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1365 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1366 |
stb_text_createundo(&state->undostate, where, 0, length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1367 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1368 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1369 |
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1370 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1371 |
int i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1372 |
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1373 |
if (p) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1374 |
for (i=0; i < length; ++i) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1375 |
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1376 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1377 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1378 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1379 |
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1380 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1381 |
int i; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1382 |
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1383 |
if (p) { |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1384 |
for (i=0; i < old_length; ++i) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1385 |
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1386 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1387 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1388 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1389 |
// reset the state to default |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1390 |
static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1391 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1392 |
state->undostate.undo_point = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1393 |
state->undostate.undo_char_point = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1394 |
state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1395 |
state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1396 |
state->select_end = state->select_start = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1397 |
state->cursor = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1398 |
state->has_preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1399 |
state->preferred_x = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1400 |
state->cursor_at_end_of_line = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1401 |
state->initialized = 1; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1402 |
state->single_line = (unsigned char) is_single_line; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1403 |
state->insert_mode = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1404 |
state->row_count_per_page = 0; |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1405 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1406 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1407 |
// API initialize |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1408 |
static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1409 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1410 |
stb_textedit_clear_state(state, is_single_line); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1411 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1412 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1413 |
#if defined(__GNUC__) || defined(__clang__) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1414 |
#pragma GCC diagnostic push |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1415 |
#pragma GCC diagnostic ignored "-Wcast-qual" |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1416 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1417 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1418 |
static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1419 |
{ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1420 |
return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len); |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1421 |
} |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1422 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1423 |
#if defined(__GNUC__) || defined(__clang__) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1424 |
#pragma GCC diagnostic pop |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1425 |
#endif |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1426 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1427 |
#endif//IMSTB_TEXTEDIT_IMPLEMENTATION |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1428 |
|
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1429 |
/* |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1430 |
------------------------------------------------------------------------------ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1431 |
This software is available under 2 licenses -- choose whichever you prefer. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1432 |
------------------------------------------------------------------------------ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1433 |
ALTERNATIVE A - MIT License |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1434 |
Copyright (c) 2017 Sean Barrett |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1435 |
Permission is hereby granted, free of charge, to any person obtaining a copy of |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1436 |
this software and associated documentation files (the "Software"), to deal in |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1437 |
the Software without restriction, including without limitation the rights to |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1438 |
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1439 |
of the Software, and to permit persons to whom the Software is furnished to do |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1440 |
so, subject to the following conditions: |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1441 |
The above copyright notice and this permission notice shall be included in all |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1442 |
copies or substantial portions of the Software. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1443 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1444 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1445 |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1446 |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1447 |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1448 |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1449 |
SOFTWARE. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1450 |
------------------------------------------------------------------------------ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1451 |
ALTERNATIVE B - Public Domain (www.unlicense.org) |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1452 |
This is free and unencumbered software released into the public domain. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1453 |
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1454 |
software, either in source code form or as a compiled binary, for any purpose, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1455 |
commercial or non-commercial, and by any means. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1456 |
In jurisdictions that recognize copyright laws, the author or authors of this |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1457 |
software dedicate any and all copyright interest in the software to the public |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1458 |
domain. We make this dedication for the benefit of the public at large and to |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1459 |
the detriment of our heirs and successors. We intend this dedication to be an |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1460 |
overt act of relinquishment in perpetuity of all present and future rights to |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1461 |
this software under copyright law. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1462 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1463 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1464 |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1465 |
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1466 |
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1467 |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1468 |
------------------------------------------------------------------------------ |
| 1193b4be |
Poul Sander |
2025-02-03 21:28 |
1469 |
*/ |
|
|
1970-01-01 00:00 |
1470 |
|