1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Multi Line Text Input Managment (Multi Line Text Input) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_multi_line_text_view.h"
29 #include "gx_multi_line_text_input.h"
30 #include "gx_scrollbar.h"
31 #include "gx_window.h"
32 #include "gx_widget.h"
33 #include "gx_utility.h"
34
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _gx_multi_line_text_input_new_line_character_get PORTABLE C */
40 /* 6.1 */
41 /* AUTHOR */
42 /* */
43 /* Kenneth Maxwell, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* Internal helper function to retrieve the new line character of the */
48 /* input text. */
49 /* */
50 /* INPUT */
51 /* */
52 /* text_view Multi-line text input widget */
53 /* control block */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* status Completion status */
58 /* */
59 /* CALLS */
60 /* */
61 /* memcpy Copy block of memory */
62 /* _gx_utility_utf8_string_character_get Parse utf8 string to */
63 /* multi-byte glyph */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _gx_multi_line_text_input_text_set */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
74 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
75 /* resulting in version 6.1 */
76 /* */
77 /**************************************************************************/
_gx_multi_line_text_input_new_line_character_get(GX_MULTI_LINE_TEXT_INPUT * text_input)78 static VOID _gx_multi_line_text_input_new_line_character_get(GX_MULTI_LINE_TEXT_INPUT *text_input)
79 {
80 GX_STRING string;
81 GX_CONST GX_CHAR *ch;
82
83 #ifdef GX_UTF8_SUPPORT
84 UINT glyph_len;
85 #endif
86
87 string = text_input -> gx_multi_line_text_view_text;
88
89 while (string.gx_string_length > 0)
90 {
91 ch = string.gx_string_ptr;
92
93 #ifdef GX_UTF8_SUPPORT
94 _gx_utility_utf8_string_character_get(&string, GX_NULL, &glyph_len);
95 #else
96 string.gx_string_ptr++;
97 string.gx_string_length--;
98 #endif /* GX_UTF8_SUPPORT */
99
100 if (ch[0] == GX_KEY_CARRIAGE_RETURN)
101 {
102 if (ch[1] == GX_KEY_LINE_FEED)
103 {
104 memcpy(text_input -> gx_multi_line_text_input_new_line_character, "\r\n", 3); /* Use case of memcpy is verified. */
105 text_input -> gx_multi_line_text_input_new_line_character_size = 2;
106 }
107 else
108 {
109 memcpy(text_input -> gx_multi_line_text_input_new_line_character, "\r", 2); /* Use case of memcpy is verified. */
110 text_input -> gx_multi_line_text_input_new_line_character_size = 1;
111 }
112
113 break;
114 }
115 else if (ch[0] == GX_KEY_LINE_FEED)
116 {
117 memcpy(text_input -> gx_multi_line_text_input_new_line_character, "\n", 2); /* Use case of memcpy is verified. */
118 text_input -> gx_multi_line_text_input_new_line_character_size = 1;
119 break;
120 }
121 }
122 }
123
124 /**************************************************************************/
125 /* */
126 /* FUNCTION RELEASE */
127 /* */
128 /* _gx_multi_line_text_input_text_set PORTABLE C */
129 /* 6.1 */
130 /* AUTHOR */
131 /* */
132 /* Kenneth Maxwell, Microsoft Corporation */
133 /* */
134 /* DESCRIPTION (Deprecated) */
135 /* */
136 /* This function assigns a text string to a multi line text input */
137 /* widget. */
138 /* */
139 /* INPUT */
140 /* */
141 /* text_view Multi-line text input widget */
142 /* control block */
143 /* text Null-terminated text string */
144 /* */
145 /* OUTPUT */
146 /* */
147 /* status Completion status */
148 /* */
149 /* CALLS */
150 /* */
151 /* _gx_utility_string_length_check Calculate string length */
152 /* _gx_multi_line_text_input_text_set_ext */
153 /* New text set function */
154 /* */
155 /* CALLED BY */
156 /* */
157 /* Application Code */
158 /* */
159 /* RELEASE HISTORY */
160 /* */
161 /* DATE NAME DESCRIPTION */
162 /* */
163 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
164 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
165 /* resulting in version 6.1 */
166 /* */
167 /**************************************************************************/
168 #if defined(GX_ENABLE_DEPRECATED_STRING_API)
_gx_multi_line_text_input_text_set(GX_MULTI_LINE_TEXT_INPUT * text_input,GX_CONST GX_CHAR * text)169 UINT _gx_multi_line_text_input_text_set(GX_MULTI_LINE_TEXT_INPUT *text_input, GX_CONST GX_CHAR *text)
170 {
171 UINT status;
172 UINT str_len;
173 GX_STRING new_string;
174
175 new_string.gx_string_ptr = text;
176 status = _gx_utility_string_length_check(text, &str_len, GX_MAX_STRING_LENGTH);
177 if (status == GX_SUCCESS)
178 {
179 new_string.gx_string_length = str_len;
180 status = _gx_multi_line_text_input_text_set_ext(text_input, &new_string);
181 }
182
183 return(status);
184 }
185 #endif
186
187 /**************************************************************************/
188 /* */
189 /* FUNCTION RELEASE */
190 /* */
191 /* _gx_multi_line_text_input_text_set_ext PORTABLE C */
192 /* 6.1 */
193 /* AUTHOR */
194 /* */
195 /* Kenneth Maxwell, Microsoft Corporation */
196 /* */
197 /* DESCRIPTION */
198 /* */
199 /* This function assigns a text string to a multi line text input */
200 /* widget. */
201 /* */
202 /* INPUT */
203 /* */
204 /* text_view Multi-line text input widget */
205 /* control block */
206 /* text Null-terminated text string */
207 /* */
208 /* OUTPUT */
209 /* */
210 /* status Completion status */
211 /* */
212 /* CALLS */
213 /* */
214 /* _gx_multi_line_text_input_new_line_character_get */
215 /* Get the new line character */
216 /* _gx_multi_line_text_view_string_total_rows_compute */
217 /* Compute the total rows of */
218 /* the input text */
219 /* _gx_multi_line_text_view_line_cache_update */
220 /* Update line cache */
221 /* _gx_window_scrollbar_find Find scrollbar for a window */
222 /* _gx_scrollbar_reset Reset scrollbar information */
223 /* _gx_system_dirty_mark Mark the widget dirty */
224 /* */
225 /* CALLED BY */
226 /* */
227 /* Application Code */
228 /* */
229 /* RELEASE HISTORY */
230 /* */
231 /* DATE NAME DESCRIPTION */
232 /* */
233 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
234 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
235 /* resulting in version 6.1 */
236 /* */
237 /**************************************************************************/
_gx_multi_line_text_input_text_set_ext(GX_MULTI_LINE_TEXT_INPUT * text_input,GX_CONST GX_STRING * text)238 UINT _gx_multi_line_text_input_text_set_ext(GX_MULTI_LINE_TEXT_INPUT *text_input, GX_CONST GX_STRING *text)
239 {
240 GX_SCROLLBAR *scroll;
241 UINT copy_size;
242
243 #if defined GX_UTF8_SUPPORT
244 GX_STRING string;
245 UINT index;
246 UINT glyph_len = 0;
247 #endif
248
249 if (text && text -> gx_string_ptr)
250 {
251 copy_size = text_input -> gx_multi_line_text_input_buffer_size - 1;
252
253 if (text -> gx_string_length > copy_size - 1)
254 {
255 #if defined GX_UTF8_SUPPORT
256 string.gx_string_ptr = text -> gx_string_ptr;
257 string.gx_string_length = copy_size;
258
259 index = 0;
260
261 /* Calculate maximum bytes that can be copied. */
262 while (_gx_utility_utf8_string_character_get(&string, GX_NULL, &glyph_len) == GX_SUCCESS)
263 {
264 index += glyph_len;
265 }
266 copy_size = index;
267 #endif
268 }
269 else
270 {
271 copy_size = text -> gx_string_length;
272 }
273
274 memcpy((GX_CHAR *)text_input -> gx_multi_line_text_view_text.gx_string_ptr, text -> gx_string_ptr, copy_size); /* Use case of memcpy is verified. */
275 text_input -> gx_multi_line_text_view_text.gx_string_length = copy_size;
276 }
277 else
278 {
279 copy_size = 0;
280 }
281
282 ((GX_CHAR *)text_input -> gx_multi_line_text_view_text.gx_string_ptr)[copy_size] = '\0';
283
284 text_input -> gx_multi_line_text_view_text.gx_string_length = copy_size;
285
286 /* Get new line character. */
287 _gx_multi_line_text_input_new_line_character_get(text_input);
288
289 if (text_input -> gx_widget_status & GX_STATUS_VISIBLE)
290 {
291 /* Compute the total rows of input string. */
292 _gx_multi_line_text_view_string_total_rows_compute((GX_MULTI_LINE_TEXT_VIEW *)text_input);
293
294 text_input -> gx_multi_line_text_input_text_insert_position = copy_size;
295
296 _gx_window_scrollbar_find((GX_WINDOW *)text_input, GX_TYPE_VERTICAL_SCROLL, &scroll);
297 if (scroll)
298 {
299 /* Reset scrollbar. */
300 _gx_scrollbar_reset(scroll, GX_NULL);
301 }
302 else
303 {
304
305 if (text_input -> gx_multi_line_text_view_text_total_rows >
306 text_input -> gx_multi_line_text_view_cache_size)
307 {
308 /* Update line cache. */
309 _gx_multi_line_text_view_line_cache_update((GX_MULTI_LINE_TEXT_VIEW *)text_input);
310 }
311 }
312
313 /* Update cursor position. */
314 _gx_multi_line_text_input_cursor_pos_update(text_input, GX_TRUE);
315
316 _gx_system_dirty_mark((GX_WIDGET *)text_input);
317 }
318 else
319 {
320 text_input -> gx_multi_line_text_view_line_index_old = GX_TRUE;
321 text_input -> gx_multi_line_text_input_text_insert_position = 0;
322 }
323 return(GX_SUCCESS);
324 }
325
326