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