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