1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** GUIX Component */
17 /** */
18 /** Multi Line Text Input Management (Multi Line Text Input) */
19 /** */
20 /**************************************************************************/
21
22 #define GX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "gx_api.h"
28 #include "gx_system.h"
29 #include "gx_window.h"
30 #include "gx_widget.h"
31 #include "gx_multi_line_text_input.h"
32 #include "gx_multi_line_text_view.h"
33 #include "gx_text_input_cursor.h"
34
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _gx_multi_line_text_input_pen_down_process PORTABLE C */
40 /* 6.1 */
41 /* AUTHOR */
42 /* */
43 /* Kenneth Maxwell, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* This function handles pen down event for multi line text input */
48 /* widget. */
49 /* */
50 /* INPUT */
51 /* */
52 /* text_input Multi-line text input widget */
53 /* control block */
54 /* event_ptr Pointer to GX_EVENT structure */
55 /* */
56 /* OUTPUT */
57 /* */
58 /* status Completion status */
59 /* */
60 /* CALLS */
61 /* */
62 /* _gx_system_input_capture Direct all input events to */
63 /* specified widget */
64 /* _gx_multi_line_text_input_highlight_rectangle_get */
65 /* Retrieve rectangle of */
66 /* highlight text */
67 /* _gx_text_input_cursor_dirty_rectangle_get */
68 /* Retrieve cursor rectangle */
69 /* _gx_multi_line_text_input_cursor_pos_calculate */
70 /* Update text insert position */
71 /* _gx_system_dirty_partial_add Mark the partial area of a */
72 /* widget as dirty */
73 /* _gx_system_dirty_mark Mark specified widget dirty */
74 /* _gx_window_event_process Default window event process */
75 /* */
76 /* CALLED BY */
77 /* */
78 /* _gx_multi_line_text_input_event_process */
79 /* */
80 /* RELEASE HISTORY */
81 /* */
82 /* DATE NAME DESCRIPTION */
83 /* */
84 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
85 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
86 /* resulting in version 6.1 */
87 /* */
88 /**************************************************************************/
_gx_multi_line_text_input_pen_down_process(GX_MULTI_LINE_TEXT_INPUT * text_input,GX_EVENT * event_ptr)89 static UINT _gx_multi_line_text_input_pen_down_process(GX_MULTI_LINE_TEXT_INPUT *text_input, GX_EVENT *event_ptr)
90 {
91 GX_TEXT_INPUT_CURSOR *cursor_ptr = &text_input -> gx_multi_line_text_input_cursor_instance;
92 INT scroll_shift;
93 GX_RECTANGLE cursor_rect;
94 UINT start_mark = text_input -> gx_multi_line_text_input_start_mark;
95 UINT end_mark = text_input -> gx_multi_line_text_input_end_mark;
96
97 _gx_system_input_capture((GX_WIDGET *)text_input);
98
99 scroll_shift = text_input -> gx_multi_line_text_view_text_scroll_shift;
100
101 if (start_mark != end_mark)
102 {
103 _gx_multi_line_text_input_highlight_rectangle_get(text_input, &cursor_rect);
104 }
105 else
106 {
107 /* Record cursor rectangle and scroll shift value before recaculate cursor position. */
108 _gx_text_input_cursor_dirty_rectangle_get(cursor_ptr, &cursor_rect);
109 }
110
111 /* Calculate cursor position according to click position. */
112 _gx_multi_line_text_input_cursor_pos_calculate(text_input, (*event_ptr).gx_event_payload.gx_event_pointdata);
113
114 /* Set highlight start/end mark to insert position. */
115 text_input -> gx_multi_line_text_input_start_mark = text_input -> gx_multi_line_text_input_text_insert_position;
116 text_input -> gx_multi_line_text_input_end_mark = text_input -> gx_multi_line_text_input_text_insert_position;
117
118 if (scroll_shift != text_input -> gx_multi_line_text_view_text_scroll_shift)
119 {
120 _gx_system_dirty_mark((GX_WIDGET *)text_input);
121 }
122 else
123 {
124 if (start_mark != end_mark)
125 {
126 /* Mark highlight area as dirty. */
127 _gx_system_dirty_partial_add((GX_WIDGET *)text_input, &cursor_rect);
128 }
129 else
130 {
131 _gx_system_dirty_partial_add((GX_WIDGET *)text_input, &cursor_rect);
132
133 /* Get current cursor rectangle. */
134 _gx_text_input_cursor_dirty_rectangle_get(cursor_ptr, &cursor_rect);
135
136 _gx_system_dirty_partial_add((GX_WIDGET *)text_input, &cursor_rect);
137 }
138 }
139
140 return _gx_window_event_process((GX_WINDOW *)text_input, event_ptr);
141 }
142
143
144 /**************************************************************************/
145 /* */
146 /* FUNCTION RELEASE */
147 /* */
148 /* _gx_multi_line_text_input_pen_drag_process PORTABLE C */
149 /* 6.1 */
150 /* AUTHOR */
151 /* */
152 /* Kenneth Maxwell, Microsoft Corporation */
153 /* */
154 /* DESCRIPTION */
155 /* */
156 /* This function handles pen drag event for multi line text input */
157 /* widget. */
158 /* */
159 /* INPUT */
160 /* */
161 /* text_input Multi-line text input widget */
162 /* control block */
163 /* event_ptr Pointer to GX_EVENT structure */
164 /* */
165 /* OUTPUT */
166 /* */
167 /* status Completion status */
168 /* */
169 /* CALLS */
170 /* */
171 /* _gx_text_input_cursor_dirty_rectangle_get */
172 /* Retrieve cursor rectangle */
173 /* _gx_multi_line_text_input_text_rectangle_get */
174 /* Retrieve text rectangle */
175 /* between specified position */
176 /* _gx_multi_line_text_input_cursor_pos_calculate */
177 /* Update text insert position */
178 /* _gx_system_dirty_partial_add Mark the partial area of a */
179 /* widget as dirty */
180 /* _gx_system_timer_start Start a timer */
181 /* _gx_system_timer_stop Stop a timer */
182 /* _gx_windwo_event_process Default window event process */
183 /* */
184 /* CALLED BY */
185 /* */
186 /* _gx_multi_line_text_input_event_process */
187 /* */
188 /* RELEASE HISTORY */
189 /* */
190 /* DATE NAME DESCRIPTION */
191 /* */
192 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
193 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
194 /* resulting in version 6.1 */
195 /* */
196 /**************************************************************************/
_gx_multi_line_text_input_pen_drag_process(GX_MULTI_LINE_TEXT_INPUT * text_input,GX_EVENT * event_ptr)197 static UINT _gx_multi_line_text_input_pen_drag_process(GX_MULTI_LINE_TEXT_INPUT *text_input, GX_EVENT *event_ptr)
198 {
199 GX_TEXT_INPUT_CURSOR *cursor_ptr = &text_input -> gx_multi_line_text_input_cursor_instance;
200 INT scroll_shift;
201 GX_RECTANGLE cursor_rect;
202 GX_POINT start_pos;
203 UINT old_end_mark;
204 GX_RECTANGLE client;
205 GX_POINT click_pos;
206 GX_VALUE click_y;
207
208 if (text_input -> gx_widget_status & GX_STATUS_OWNS_INPUT)
209 {
210 client = text_input -> gx_window_client;
211
212 click_pos = event_ptr -> gx_event_payload.gx_event_pointdata;
213 click_y = click_pos.gx_point_y;
214
215 if (text_input -> gx_multi_line_text_input_start_mark == text_input -> gx_multi_line_text_input_end_mark)
216 {
217 _gx_text_input_cursor_dirty_rectangle_get(cursor_ptr, &cursor_rect);
218
219 /* Mark cursor area as dirty. */
220 _gx_system_dirty_partial_add((GX_WIDGET *)text_input, &cursor_rect);
221 }
222
223 start_pos = cursor_ptr -> gx_text_input_cursor_pos;
224
225 scroll_shift = text_input -> gx_multi_line_text_view_text_scroll_shift;
226 old_end_mark = text_input -> gx_multi_line_text_input_end_mark;
227
228 if (click_pos.gx_point_y < client.gx_rectangle_top)
229 {
230 click_pos.gx_point_y = client.gx_rectangle_top;
231 }
232 else if (click_pos.gx_point_y > client.gx_rectangle_bottom)
233 {
234 click_pos.gx_point_y = client.gx_rectangle_bottom;
235 }
236 _gx_multi_line_text_input_cursor_pos_calculate(text_input, click_pos);
237
238 text_input -> gx_multi_line_text_input_end_mark = text_input -> gx_multi_line_text_input_text_insert_position;
239
240 if ((click_y < client.gx_rectangle_top) &&
241 (text_input -> gx_multi_line_text_input_text_cursor_line > 1))
242 {
243 if (!(text_input -> gx_widget_status & (GX_STATUS_MARK_NEXT | GX_STATUS_MARK_PREVIOUS)))
244 {
245 /* Start a timer to move text right. */
246 _gx_system_timer_start((GX_WIDGET *)text_input, GX_MARK_TIMER,
247 GX_MARK_INTERVAL, GX_MARK_INTERVAL);
248 }
249
250 text_input -> gx_widget_status &= ~GX_STATUS_MARK_NEXT;
251 text_input -> gx_widget_status |= GX_STATUS_MARK_PREVIOUS;
252 }
253 else if ((click_y > client.gx_rectangle_bottom) &&
254 (text_input -> gx_multi_line_text_input_text_cursor_line < text_input -> gx_multi_line_text_view_text_total_rows))
255 {
256 if (!(text_input -> gx_widget_status & (GX_STATUS_MARK_NEXT | GX_STATUS_MARK_PREVIOUS)))
257 {
258 /* Start a timer to move text left. */
259 _gx_system_timer_start((GX_WIDGET *)text_input, GX_MARK_TIMER,
260 GX_MARK_INTERVAL, GX_MARK_INTERVAL);
261 }
262
263 text_input -> gx_widget_status &= ~GX_STATUS_MARK_PREVIOUS;
264 text_input -> gx_widget_status |= GX_STATUS_MARK_NEXT;
265 }
266 else
267 {
268 if (text_input -> gx_widget_status & (GX_STATUS_MARK_NEXT | GX_STATUS_MARK_PREVIOUS))
269 {
270 _gx_system_timer_stop((GX_WIDGET *)text_input, GX_MARK_TIMER);
271 text_input -> gx_widget_status &= ~(GX_STATUS_MARK_NEXT | GX_STATUS_MARK_PREVIOUS);
272 }
273 }
274
275 if (scroll_shift != text_input -> gx_multi_line_text_view_text_scroll_shift)
276 {
277 _gx_system_dirty_mark((GX_WIDGET *)text_input);
278 }
279 else
280 {
281 if ((text_input -> gx_multi_line_text_input_start_mark != text_input -> gx_multi_line_text_input_end_mark) ||
282 (text_input -> gx_multi_line_text_input_start_mark != old_end_mark))
283 {
284 _gx_multi_line_text_input_text_rectangle_get(text_input,
285 start_pos,
286 cursor_ptr -> gx_text_input_cursor_pos, &cursor_rect);
287
288 /* Mark highlight area as dirty. */
289 _gx_system_dirty_partial_add((GX_WIDGET *)text_input, &cursor_rect);
290 }
291 }
292 }
293 else
294 {
295 _gx_window_event_process((GX_WINDOW *)text_input, event_ptr);
296 }
297
298 return GX_SUCCESS;
299 }
300
301 /**************************************************************************/
302 /* */
303 /* FUNCTION RELEASE */
304 /* */
305 /* _gx_multi_line_text_input_event_process PORTABLE C */
306 /* 6.1.3 */
307 /* AUTHOR */
308 /* */
309 /* Kenneth Maxwell, Microsoft Corporation */
310 /* */
311 /* DESCRIPTION */
312 /* */
313 /* This function processes events for the specified text input widget. */
314 /* */
315 /* INPUT */
316 /* */
317 /* text_input Multi line text input */
318 /* control block */
319 /* event_ptr Incoming event to process */
320 /* */
321 /* OUTPUT */
322 /* */
323 /* status Completion status */
324 /* */
325 /* CALLS */
326 /* */
327 /* _gx_widget_event_process Default widget event process */
328 /* _gx_system_timer_start Allocate a free timer and */
329 /* activates it */
330 /* _gx_system_timer_stop Stop an active GUIX timer */
331 /* _gx_multi_line_text_input_keydown_process */
332 /* Process the keydown event */
333 /* _gx_widget_event_generate Generate an event */
334 /* _gx_text_input_cursor_dirty_rectangle_get */
335 /* Get cursor rectangle */
336 /* _gx_multi_line_text_input_cursor_pos_calculate */
337 /* Calculate cursor position */
338 /* according to click positin */
339 /* _gx_multi_line_text_input_cursor_pos_update */
340 /* Update cursor position */
341 /* according to insert position*/
342 /* _gx_system_dirty_partial_add Add a dirty area to the */
343 /* specified widget */
344 /* _gx_multi_line_text_view_event_process */
345 /* Invoke the text view event */
346 /* process routine */
347 /* */
348 /* CALLED BY */
349 /* */
350 /* Application Code */
351 /* GUIX Internal Code */
352 /* */
353 /* RELEASE HISTORY */
354 /* */
355 /* DATE NAME DESCRIPTION */
356 /* */
357 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
358 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
359 /* resulting in version 6.1 */
360 /* 12-31-2020 Kenneth Maxwell Modified comment(s), */
361 /* added logic to release */
362 /* dynamic input buffer, */
363 /* resulting in version 6.1.3 */
364 /* */
365 /**************************************************************************/
_gx_multi_line_text_input_event_process(GX_MULTI_LINE_TEXT_INPUT * text_input,GX_EVENT * event_ptr)366 UINT _gx_multi_line_text_input_event_process(GX_MULTI_LINE_TEXT_INPUT *text_input, GX_EVENT *event_ptr)
367 {
368 GX_TEXT_INPUT_CURSOR *cursor_ptr = &text_input -> gx_multi_line_text_input_cursor_instance;
369 GX_MULTI_LINE_TEXT_VIEW *view = (GX_MULTI_LINE_TEXT_VIEW *)text_input;
370 GX_WIDGET *widget = (GX_WIDGET *)text_input;
371 GX_VALUE blink_interval = text_input -> gx_multi_line_text_input_cursor_instance.gx_text_input_cursor_blink_interval;
372 UINT status;
373 GX_RECTANGLE cursor_rect;
374 INT scroll_shift;
375 ULONG old_style;
376
377 /* Default status to success. */
378 status = GX_SUCCESS;
379
380 /* Process relative to the type of event. */
381 switch (event_ptr -> gx_event_type)
382 {
383 case GX_EVENT_SHOW:
384 _gx_window_event_process((GX_WINDOW *)text_input, event_ptr);
385
386 /* Update cursor position. */
387 _gx_multi_line_text_input_cursor_pos_update(text_input, GX_TRUE);
388
389 if ((text_input -> gx_widget_style & GX_STYLE_CURSOR_ALWAYS) &&
390 (text_input -> gx_widget_style & GX_STYLE_CURSOR_BLINK))
391 {
392 /* Start the timer. */
393 _gx_system_timer_start(widget, ID_TEXT_INPUT_TIMER, GX_CURSOR_BLINK_INTERVAL, GX_CURSOR_BLINK_INTERVAL);
394 }
395
396 /* Get visible rows. */
397 _gx_multi_line_text_view_visible_rows_compute((GX_MULTI_LINE_TEXT_VIEW *)text_input);
398 break;
399
400 case GX_EVENT_STYLE_CHANGED:
401 if (widget -> gx_widget_status & GX_STATUS_VISIBLE)
402 {
403 _gx_multi_line_text_view_event_process((GX_MULTI_LINE_TEXT_VIEW *)text_input, event_ptr);
404
405 old_style = event_ptr -> gx_event_payload.gx_event_ulongdata;
406 if ((old_style & (GX_STYLE_BORDER_MASK | GX_STYLE_TEXT_ALIGNMENT_MASK)) !=
407 (widget -> gx_widget_style & (GX_STYLE_BORDER_MASK | GX_STYLE_TEXT_ALIGNMENT_MASK)))
408 {
409 text_input -> gx_multi_line_text_view_line_index_old = GX_TRUE;
410 }
411 }
412 break;
413
414 case GX_EVENT_FOCUS_GAINED:
415 /* Call the widget default processing. */
416 _gx_widget_event_process(widget, event_ptr);
417
418 /* Do not do anything if the CURSOR_ALWAYS flag is set. */
419 if (!(text_input -> gx_widget_style & GX_STYLE_CURSOR_ALWAYS))
420 {
421 text_input -> gx_widget_status |= (GX_STATUS_CURSOR_SHOW | GX_STATUS_CURSOR_DRAW);
422
423 if (text_input -> gx_widget_style & GX_STYLE_CURSOR_BLINK)
424 {
425 /* Start the timer. */
426 _gx_system_timer_start(widget, ID_TEXT_INPUT_TIMER, (UINT)blink_interval, (UINT)blink_interval);
427 }
428 }
429
430 _gx_multi_line_text_input_text_select(text_input, 0, text_input -> gx_multi_line_text_view_text.gx_string_length - 1);
431 break;
432
433 case GX_EVENT_KEY_DOWN:
434 _gx_multi_line_text_input_keydown_process(text_input, event_ptr);
435 if (widget -> gx_widget_style & GX_STYLE_TEXT_INPUT_NOTIFY_ALL)
436 {
437 _gx_widget_event_generate(widget, GX_EVENT_TEXT_EDITED, 0);
438 }
439 break;
440
441 case GX_EVENT_PEN_DOWN:
442 _gx_multi_line_text_input_pen_down_process(text_input, event_ptr);
443 break;
444
445 case GX_EVENT_PEN_DRAG:
446 _gx_multi_line_text_input_pen_drag_process(text_input, event_ptr);
447 break;
448
449 case GX_EVENT_PEN_UP:
450 if (text_input -> gx_widget_status & GX_STATUS_OWNS_INPUT)
451 {
452 _gx_system_input_release((GX_WIDGET *)text_input);
453
454 if (text_input -> gx_widget_status & (GX_STATUS_MARK_NEXT | GX_STATUS_MARK_PREVIOUS))
455 {
456 _gx_system_timer_stop((GX_WIDGET *)text_input, GX_MARK_TIMER);
457 text_input -> gx_widget_status &= ~(GX_STATUS_MARK_NEXT | GX_STATUS_MARK_PREVIOUS);
458 }
459 }
460 else
461 {
462 _gx_window_event_process((GX_WINDOW *)text_input, event_ptr);
463 }
464 break;
465
466 case GX_EVENT_TIMER:
467 if (event_ptr -> gx_event_payload.gx_event_timer_id == GX_MARK_TIMER)
468 {
469 if (text_input -> gx_widget_status & GX_STATUS_MARK_PREVIOUS)
470 {
471 _gx_multi_line_text_input_mark_up(text_input);
472 }
473 else
474 {
475 _gx_multi_line_text_input_mark_down(text_input);
476 }
477 }
478 else if ((event_ptr -> gx_event_payload.gx_event_timer_id == ID_TEXT_INPUT_TIMER) &&
479 (text_input -> gx_widget_status & GX_STATUS_CURSOR_SHOW) &&
480 (text_input -> gx_multi_line_text_input_start_mark == text_input -> gx_multi_line_text_input_end_mark))
481 {
482 if (text_input -> gx_widget_status & GX_STATUS_CURSOR_DRAW)
483 {
484 text_input -> gx_widget_status &= (ULONG)(~GX_STATUS_CURSOR_DRAW);
485 }
486 else
487 {
488 text_input -> gx_widget_status |= GX_STATUS_CURSOR_DRAW;
489 }
490 /* Define a cursor rectangle for the cursor. */
491 _gx_text_input_cursor_dirty_rectangle_get(&text_input -> gx_multi_line_text_input_cursor_instance, &cursor_rect);
492 _gx_system_dirty_partial_add(widget, &cursor_rect);
493 }
494 break;
495
496 case GX_EVENT_FOCUS_LOST:
497 _gx_widget_event_process(widget, event_ptr);
498
499 /* Do not do anything if the CURSOR_ALWAYS flag is set. */
500 if (!(text_input -> gx_widget_style & GX_STYLE_CURSOR_ALWAYS))
501 {
502 text_input -> gx_widget_status &= (ULONG)(~GX_STATUS_CURSOR_SHOW);
503
504 /* Stop the timer if the cursor style is BLINK. */
505 if (text_input -> gx_widget_style & GX_STYLE_CURSOR_BLINK)
506 {
507 /* Stop the timer. */
508 _gx_system_timer_stop(widget, 0);
509 }
510
511 /* Define a cursor rectangle for the cursor. */
512 _gx_text_input_cursor_dirty_rectangle_get(&text_input -> gx_multi_line_text_input_cursor_instance, &cursor_rect);
513 _gx_system_dirty_partial_add(widget, &cursor_rect);
514 }
515
516 if (text_input -> gx_multi_line_text_input_start_mark != text_input -> gx_multi_line_text_input_end_mark)
517 {
518 _gx_multi_line_text_input_highlight_rectangle_get(text_input, &cursor_rect);
519
520 text_input -> gx_multi_line_text_input_start_mark = 0;
521 text_input -> gx_multi_line_text_input_end_mark = 0;
522
523 _gx_system_dirty_partial_add(widget, &cursor_rect);
524 }
525
526 if (text_input -> gx_multi_line_text_input_text_was_modified)
527 {
528 _gx_widget_event_generate(widget, GX_EVENT_TEXT_EDITED, 0);
529 text_input -> gx_multi_line_text_input_text_was_modified = GX_FALSE;
530 }
531 break;
532
533 case GX_EVENT_VERTICAL_SCROLL:
534 /* Pick up scroll shift value. */
535 scroll_shift = event_ptr -> gx_event_payload.gx_event_intdata[1] - event_ptr -> gx_event_payload.gx_event_intdata[0];
536
537 /* Move cursor position according to shift value. */
538 cursor_ptr -> gx_text_input_cursor_pos.gx_point_y = (GX_VALUE)(cursor_ptr -> gx_text_input_cursor_pos.gx_point_y + scroll_shift);
539
540 /* Call the multi-line text view event processing. */
541 _gx_multi_line_text_view_event_process(view, event_ptr);
542 break;
543
544 case GX_EVENT_LANGUAGE_CHANGE:
545 break;
546
547 case GX_EVENT_COPY:
548 _gx_multi_line_text_input_copy(text_input);
549 break;
550
551 case GX_EVENT_CUT:
552 _gx_multi_line_text_input_cut(text_input);
553 break;
554
555 case GX_EVENT_PASTE:
556 _gx_multi_line_text_input_paste(text_input);
557 break;
558
559 case GX_EVENT_MARK_NEXT:
560 _gx_multi_line_text_input_mark_next(text_input);
561 break;
562
563 case GX_EVENT_MARK_PREVIOUS:
564 _gx_multi_line_text_input_mark_previous(text_input);
565 break;
566
567 case GX_EVENT_MARK_UP:
568 _gx_multi_line_text_input_mark_up(text_input);
569 break;
570
571 case GX_EVENT_MARK_DOWN:
572 _gx_multi_line_text_input_mark_down(text_input);
573 break;
574
575 case GX_EVENT_MARK_END:
576 _gx_multi_line_text_input_mark_end(text_input);
577 break;
578
579 case GX_EVENT_MARK_HOME:
580 _gx_multi_line_text_input_mark_home(text_input);
581 break;
582
583 case GX_EVENT_DELETE:
584 if (text_input -> gx_widget_status & GX_STATUS_DYNAMIC_BUFFER)
585 {
586 if (!_gx_system_memory_free)
587 {
588 return GX_SYSTEM_MEMORY_ERROR;
589 }
590
591 _gx_system_memory_free((void *)text_input -> gx_multi_line_text_view_text.gx_string_ptr);
592 text_input -> gx_multi_line_text_view_text.gx_string_ptr = GX_NULL;
593 }
594 break;
595
596 default:
597 /* Call the multi-line text view event processing. */
598 status = _gx_multi_line_text_view_event_process(view, event_ptr);
599 }
600
601 /* Return completion status. */
602 return(status);
603 }
604
605