GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/textboxes.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 144 173 83.2%
Functions: 10 13 76.9%
Branches: 48 82 58.5%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/ui/textboxes.h"
30 #include "gate/results.h"
31
32 #if defined(GATE_UI_WINAPI)
33
34
35 #include "gate/ui/gateui_winapi.h"
36 #include "gate/platforms.h"
37
38 static gate_bool_t WINAPI gate_ui_textbox_events(ui_hwnd_t hwnd, gate_ui_ctrl_t* ctrl, gate_uint32_t msg, gate_uintptr_t wParam, gate_intptr_t lParam, gate_intptr_t* lresult)
39 {
40 if ((ctrl != NULL) && (hwnd != UI_HWND_NULL))
41 {
42 const HWND hwnd_ctrl = (HWND)GATE_UI_WINAPI_GET_HWND(ctrl);
43 if ((HWND)hwnd == hwnd_ctrl)
44 {
45 gate_ui_textbox_t* txtbx = (gate_ui_textbox_t*)ctrl;
46 switch (msg)
47 {
48 case WM_GETDLGCODE:
49 {
50 const gate_uint32_t styles = gate_ui_winapi_get_window_styles(hwnd);
51 if (GATE_FLAG_ENABLED(styles, ES_MULTILINE))
52 {
53 /* multi-line */
54 if (GATE_FLAG_ENABLED(styles, ES_READONLY))
55 {
56 *lresult = DLGC_WANTARROWS;
57 }
58 else
59 {
60 *lresult = DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL | DLGC_WANTALLKEYS;
61 }
62 }
63 else
64 {
65 /* single-line */
66 *lresult = DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL;
67 }
68 return true;
69 }
70 case WM_CHAR:
71 {
72 gate_char32_t chr, chr2;
73 chr2 = chr = (gate_char32_t)wParam;
74 if (txtbx->on_char != NULL)
75 {
76 txtbx->on_char(ctrl, &chr);
77 if (chr2 != chr)
78 {
79 if (chr == 0)
80 {
81 *lresult = 0;
82 return true;
83 }
84 else
85 {
86 WNDPROC wndproc = (WNDPROC)(gate_uintptr_t)GATE_UI_WINAPI_GET_HWND_PROC(ctrl);
87 if (wndproc != NULL)
88 {
89 *lresult = wndproc(hwnd_ctrl, msg, (WPARAM)chr, (LPARAM)lParam);
90 return true;
91 }
92 }
93 }
94 }
95 break;
96 }
97 case WM_KEYDOWN:
98 {
99 if (wParam == VK_TAB)
100 {
101 *lresult = 0;
102 return true;
103 }
104 if ((wParam == VK_RETURN) && ((gate_ui_winapi_get_window_styles(hwnd) & ES_MULTILINE) == 0))
105 {
106 *lresult = 0;
107 return true;
108 }
109 break;
110 }
111 case WM_KEYUP:
112 {
113 if (wParam == VK_TAB)
114 {
115 *lresult = 0;
116 return true;
117 }
118 if ((wParam == VK_RETURN) && ((gate_ui_winapi_get_window_styles(hwnd) & ES_MULTILINE) == 0))
119 {
120 *lresult = 0;
121 return true;
122 }
123 break;
124 }
125 }
126 }
127 }
128 return false;
129 }
130
131 gate_result_t gate_ui_textbox_create(
132 gate_ui_textbox_t* txtbox, gate_ui_ctrl_t* parent,
133 gate_ui_position_t const* position,
134 gate_string_t const* caption,
135 gate_uint32_t flags,
136 void* userparam
137 )
138 {
139 gate_result_t ret;
140
141 do
142 {
143 gate_uint32_t styles = WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | ES_LEFT;
144 gate_uint32_t exstyles = 0;
145 ui_hwnd_t hwndParent;
146 gate_ui_host_t* host = gate_ui_ctrl_get_host(parent);
147 if (host == NULL)
148 {
149 ret = GATE_RESULT_INVALIDSTATE;
150 break;
151 }
152 hwndParent = GATE_UI_WINAPI_GET_HWND(parent);
153 if (hwndParent == UI_HWND_NULL)
154 {
155 ret = GATE_RESULT_INVALIDSTATE;
156 break;
157 }
158
159 gate_mem_clear(txtbox, sizeof(gate_ui_textbox_t));
160
161 #if !defined(GATE_SYS_WIN16)
162 exstyles |= WS_EX_CLIENTEDGE;
163 #endif
164 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TEXTBOX_MULTILINE))
165 {
166 styles |= (ES_MULTILINE | ES_WANTRETURN);
167 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TEXTBOX_HSCROLL))
168 {
169 styles |= WS_HSCROLL;
170 }
171 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TEXTBOX_VSCROLL))
172 {
173 styles |= WS_VSCROLL;
174 }
175 }
176 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TEXTBOX_RETURNKEY))
177 {
178 styles |= ES_WANTRETURN;
179 }
180 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TEXTBOX_READONLY))
181 {
182 styles |= ES_READONLY;
183 }
184 else
185 {
186 styles |= (ES_AUTOHSCROLL | ES_AUTOVSCROLL);
187 }
188
189 if (!GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_ENABLED)) styles |= WS_DISABLED;
190 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_VISIBLE)) styles |= WS_VISIBLE;
191
192 ret = gate_ui_winapi_create(&txtbox->ctrl, host, hwndParent, _T("EDIT"), position, styles, exstyles, caption, userparam, true);
193 if (GATE_SUCCEEDED(ret))
194 {
195 ui_hwnd_t hwnd = GATE_UI_WINAPI_GET_HWND(&txtbox->ctrl);
196 gate_ui_winapi_register_event(host, hwnd, WM_CHAR, &gate_ui_textbox_events, &txtbox->ctrl);
197 gate_ui_winapi_register_event(host, hwnd, WM_GETDLGCODE, &gate_ui_textbox_events, &txtbox->ctrl);
198 gate_ui_winapi_register_event(host, hwnd, WM_KEYDOWN, &gate_ui_textbox_events, &txtbox->ctrl);
199 gate_ui_winapi_register_event(host, hwnd, WM_KEYUP, &gate_ui_textbox_events, &txtbox->ctrl);
200
201 }
202 } while (0);
203
204 return ret;
205 }
206
207 gate_result_t gate_ui_textbox_get_line(gate_ui_textbox_t* txtbox, gate_uint32_t* currentLine, gate_uint32_t* lineCount)
208 {
209 gate_result_t ret = GATE_RESULT_OK;
210 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&txtbox->ctrl);
211 LRESULT result;
212 if (lineCount != NULL)
213 {
214 result = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
215 if (result < 1)
216 {
217 *lineCount = (gate_uint32_t)result;
218 ret = GATE_RESULT_FAILED;
219 }
220 }
221 if (currentLine != NULL)
222 {
223 result = SendMessage(hwnd, EM_LINEFROMCHAR, -1, 0);
224 *currentLine = (gate_uint32_t)result;
225 }
226 return ret;
227 }
228 gate_result_t gate_ui_textbox_get_column(gate_ui_textbox_t* textbox, gate_uint32_t* currentColumn)
229 {
230 gate_result_t ret;
231 gate_uint32_t currentlinecharpos;
232 DWORD selstart, selend;
233 LRESULT result;
234 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&textbox->ctrl);
235 currentlinecharpos = (gate_uint32_t)SendMessage(hwnd, EM_LINEINDEX, -1, 0);
236 result = SendMessage(hwnd, EM_GETSEL, (WPARAM)(void*)&selstart, (LPARAM)(void*)&selend);
237 if (selstart >= currentlinecharpos)
238 {
239 if (currentColumn != NULL)
240 {
241 *currentColumn = selstart - currentlinecharpos;
242 }
243 ret = GATE_RESULT_OK;
244 }
245 else if (selend >= currentlinecharpos)
246 {
247 if (currentColumn != NULL)
248 {
249 *currentColumn = selend - currentlinecharpos;
250 }
251 ret = GATE_RESULT_OK;
252 }
253 else
254 {
255 ret = GATE_RESULT_FAILED;
256 }
257
258 return ret;
259 }
260 gate_result_t gate_ui_textbox_get_selection(gate_ui_textbox_t* textbox, gate_uint32_t* sel_start, gate_uint32_t* sel_end, gate_string_t* sel_text)
261 {
262 gate_result_t ret;
263 TCHAR buffer[GATE_DEFAULT_LINE_LENGTH * 6];
264 TCHAR* txtbuffer = &buffer[0];
265 static gate_size_t const buffersize = sizeof(buffer) / sizeof(buffer[0]);
266
267 do
268 {
269 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&textbox->ctrl);
270 DWORD selstart = (DWORD)-1;
271 DWORD selend = (DWORD)-1;
272 LRESULT result = SendMessage(hwnd, EM_GETSEL, (WPARAM)(void*)&selstart, (LPARAM)(void*)&selend);
273
274 if (sel_start != NULL)
275 {
276 *sel_start = (gate_uint32_t)selstart;
277 }
278 if (sel_end != NULL)
279 {
280 *sel_end = (gate_uint32_t)selend;
281 }
282 if (sel_text != NULL)
283 {
284 if (selstart == selend)
285 {
286 gate_string_create_empty(sel_text);
287 }
288 else
289 {
290 if (selend >= buffersize)
291 {
292 txtbuffer = (TCHAR*)gate_mem_alloc(((gate_size_t)selend + 4) * sizeof(TCHAR));
293 if (txtbuffer == NULL)
294 {
295 ret = GATE_RESULT_OUTOFMEMORY;
296 break;
297 }
298 }
299 result = SendMessage(hwnd, WM_GETTEXT, (WPARAM)selend + 1, (LPARAM)(gate_uintptr_t)txtbuffer);
300 gate_win32_winstr_2_utf8_string(&txtbuffer[selstart], selend - selstart, sel_text);
301 }
302 }
303 ret = GATE_RESULT_OK;
304 } while (0);
305 if (txtbuffer != &buffer[0])
306 {
307 gate_mem_dealloc(txtbuffer);
308 }
309 return ret;
310 }
311 gate_result_t gate_ui_textbox_set_selection(gate_ui_textbox_t* textbox, gate_uint32_t sel_start, gate_uint32_t sel_end, gate_bool_t scroll_to_sel)
312 {
313 gate_result_t ret = GATE_RESULT_OK;
314 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&textbox->ctrl);
315 SendMessage(hwnd, EM_SETSEL, (WPARAM)sel_start, (LPARAM)sel_end);
316 if (scroll_to_sel)
317 {
318 #if !defined(GATE_SYS_WIN16)
319 SendMessage(hwnd, EM_SCROLLCARET, 0, 0);
320 #endif
321 }
322 return ret;
323 }
324 gate_result_t gate_ui_textbox_replace_selection(gate_ui_textbox_t* textbox, gate_string_t const* text)
325 {
326 gate_result_t ret;
327 TCHAR buffer[GATE_DEFAULT_LINE_LENGTH * 6];
328 TCHAR* txtbuffer = &buffer[0];
329 do
330 {
331 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&textbox->ctrl);
332 const gate_size_t textlen = gate_string_length(text);
333
334 if (textlen >= sizeof(buffer) / sizeof(buffer[0]))
335 {
336 txtbuffer = gate_mem_alloc((textlen + 256) * sizeof(TCHAR));
337 if (txtbuffer == NULL)
338 {
339 ret = GATE_RESULT_OUTOFMEMORY;
340 break;
341 }
342 }
343 if (textlen == 0)
344 {
345 txtbuffer[0] = 0;
346 }
347 else
348 {
349 gate_win32_utf8_2_winstr(text->str, text->length, txtbuffer, textlen + 255);
350 }
351
352 SendMessage(hwnd, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)(gate_intptr_t)txtbuffer);
353 ret = GATE_RESULT_OK;
354 } while (0);
355
356 if ((txtbuffer != &buffer[0]) && (txtbuffer != NULL))
357 {
358 gate_mem_dealloc(txtbuffer);
359 }
360
361 return ret;
362 }
363 gate_result_t gate_ui_textbox_undo(gate_ui_textbox_t* textbox)
364 {
365 gate_result_t ret;
366 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&textbox->ctrl);
367 if (FALSE == SendMessage(hwnd, EM_UNDO, 0, 0))
368 {
369 ret = GATE_RESULT_FAILED;
370 }
371 else
372 {
373 ret = GATE_RESULT_OK;
374 }
375 return ret;
376 }
377
378 gate_result_t gate_ui_textbox_set_font(gate_ui_textbox_t* textbox, gate_ui_font_t const* font)
379 {
380 gate_result_t ret;
381 HFONT hfont = (HFONT)gate_ui_winapi_create_font(font);
382 if (hfont == NULL)
383 {
384 ret = GATE_RESULT_OUTOFRESOURCES;
385 }
386 else
387 {
388 ret = gate_ui_winapi_change_font(&textbox->ctrl, hfont);
389 }
390 return ret;
391 }
392
393 gate_result_t gate_ui_textbox_find_next(gate_ui_textbox_t* textbox, gate_string_t const* token, gate_uint32_t flags)
394 {
395 gate_result_t ret = GATE_RESULT_FAILED;
396 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&textbox->ctrl);
397 do
398 {
399
400 } while (0);
401 return ret;
402 }
403
404 #endif /*GATE_UI_WINAPI*/
405
406
407
408 #if defined(GATE_UI_GTK)
409
410 #include "gate/ui/gateui_gtk.h"
411
412 static gate_uint32_t gate_ui_gtk_textbox_get_text_length(gate_ui_ctrl_t* ctrl)
413 {
414 gint char_count = 0;
415 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(ctrl);
416 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
417
418 if (multiline)
419 {
420 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(widget);
421 if (scroll_window)
422 {
423 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
424 if (text_view)
425 {
426 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
427 if (buffer)
428 {
429 char_count = gtk_text_buffer_get_char_count(buffer);
430 }
431 }
432 }
433 }
434 else
435 {
436 GtkEntry* entry = GTK_ENTRY(widget);
437 if (entry)
438 {
439 char_count = gtk_entry_get_text_length(entry);
440 }
441 }
442
443 return (gate_uint32_t)char_count;
444 }
445 static gate_result_t gate_ui_gtk_textbox_get_text(gate_ui_ctrl_t* ctrl, gate_string_t* text)
446 {
447 gate_result_t ret = GATE_RESULT_FAILED;
448 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(ctrl);
449 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
450 char const* ptr_text_buffer = NULL;
451
452 if (multiline)
453 {
454 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(GATE_UI_GTK_GET_CTRL_WIDGET(ctrl));
455 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
456
457 if (text_view)
458 {
459 gchar* text_buffer = NULL;
460 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
461 if (buffer)
462 {
463 GtkTextIter text_start, text_end;
464 gtk_widget_set_sensitive((GtkWidget*)text_view, FALSE);
465 gtk_text_buffer_get_start_iter(buffer, &text_start);
466 gtk_text_buffer_get_end_iter(buffer, &text_end);
467 text_buffer = gtk_text_buffer_get_text(buffer, &text_start, &text_end, FALSE);
468 gtk_text_buffer_set_modified(buffer, FALSE);
469 gtk_widget_set_sensitive((GtkWidget*)text_view, TRUE);
470 }
471 if (text_buffer == NULL)
472 {
473 gate_string_create_empty(text);
474 ret = GATE_RESULT_OK;
475 }
476 else
477 {
478 if (NULL == gate_string_create(text, text_buffer, gate_str_length(text_buffer)))
479 {
480 ret = GATE_RESULT_OUTOFMEMORY;
481 }
482 else
483 {
484 ret = GATE_RESULT_OK;
485 }
486 g_free(text_buffer);
487 }
488 }
489 }
490 else
491 {
492 GtkEntry* entry = GTK_ENTRY(widget);
493 ptr_text_buffer = gtk_entry_get_text(entry);
494 if (ptr_text_buffer == NULL)
495 {
496 gate_string_create_empty(text);
497 ret = GATE_RESULT_OK;
498 }
499 else
500 {
501 if (NULL == gate_string_create(text, ptr_text_buffer, gate_str_length(ptr_text_buffer)))
502 {
503 ret = GATE_RESULT_OUTOFMEMORY;
504 }
505 else
506 {
507 ret = GATE_RESULT_OK;
508 }
509 }
510 }
511
512 return ret;
513 }
514 static gate_result_t gate_ui_gtk_textbox_set_text(gate_ui_ctrl_t* ctrl, gate_string_t const* text)
515 {
516 gate_result_t ret = GATE_RESULT_FAILED;
517 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(ctrl);
518 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
519
520 if (multiline)
521 {
522 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(widget);
523 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
524 if (text_view)
525 {
526 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
527 if (buffer)
528 {
529 gtk_widget_set_sensitive(GTK_WIDGET(text_view), FALSE);
530
531 if (gate_string_is_empty(text))
532 {
533 gtk_text_buffer_set_text(buffer, "", 0);
534 }
535 else
536 {
537 gtk_text_buffer_set_text(buffer, (gchar const*)text->str, (gint)text->length);
538 }
539 gtk_text_buffer_set_modified(buffer, TRUE);
540 gtk_widget_set_sensitive(GTK_WIDGET(text_view), TRUE);
541 ret = GATE_RESULT_OK;
542 }
543 }
544 }
545 else
546 {
547 char text_buffer[GATE_MAX_COPYBUFFER_LENGTH];
548 GtkEntry* entry = GTK_ENTRY(widget);
549 GATE_STRING_TO_BUFFER(text, text_buffer);
550 gtk_entry_set_text(entry, text_buffer);
551 ret = GATE_RESULT_OK;
552 }
553
554 return ret;
555 }
556 static gate_ui_gtk_dispatcher_t gate_ui_gtk_textbox_dispatcher =
557 {
558 gate_ui_gtk_textbox_get_text_length,
559 gate_ui_gtk_textbox_get_text,
560 gate_ui_gtk_textbox_set_text,
561 NULL,
562 NULL,
563 NULL
564 };
565
566
567 gate_result_t gate_ui_textbox_create(gate_ui_textbox_t* txtbox, gate_ui_ctrl_t* parent,
568 gate_ui_position_t const* position, gate_string_t const* caption, gate_uint32_t flags, void* userparam)
569 {
570 GtkWidget* widget;
571 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(parent);
572 gate_bool_t const multiline = GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TEXTBOX_MULTILINE);
573
574 gate_mem_clear(txtbox, sizeof(gate_ui_textbox_t));
575
576 if (multiline)
577 {
578 GtkWidget* scroll_widget;
579 GtkTextBuffer* textbuffer;
580
581 widget = gtk_text_view_new();
582 if (widget == NULL)
583 {
584 return GATE_RESULT_FAILED;
585 }
586 textbuffer = gtk_text_buffer_new(NULL);
587 if (textbuffer == NULL)
588 {
589 gtk_widget_destroy(widget);
590 return GATE_RESULT_OUTOFRESOURCES;
591 }
592
593 gtk_text_view_set_buffer(GTK_TEXT_VIEW(widget), textbuffer);
594
595 scroll_widget = gtk_scrolled_window_new(NULL, NULL);
596 if (scroll_widget == NULL)
597 {
598 gtk_widget_destroy(widget);
599 return GATE_RESULT_OUTOFRESOURCES;
600 }
601
602 gtk_container_add(GTK_CONTAINER(scroll_widget), widget);
603
604 gtk_widget_show(widget);
605
606
607 gate_ui_gtk_ctrl_init(&txtbox->ctrl, scroll_widget, host, userparam, parent,
608 &gate_ui_gtk_textbox_dispatcher, false, false, position, &flags);
609
610 if (gate_string_length(caption) > 0)
611 {
612 gate_ui_ctrl_set_text(&txtbox->ctrl, caption);
613 }
614
615 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TEXTBOX_READONLY))
616 {
617 gtk_text_view_set_editable(GTK_TEXT_VIEW(widget), FALSE);
618 }
619 }
620 else
621 {
622 GtkEntryBuffer* entrybuffer = gtk_entry_buffer_new(NULL, 0);
623 widget = gtk_entry_new_with_buffer(entrybuffer);
624
625 gate_ui_gtk_ctrl_init(&txtbox->ctrl, widget, host, userparam, parent,
626 &gate_ui_gtk_textbox_dispatcher, false, false, position, &flags);
627
628 if (gate_string_length(caption) > 0)
629 {
630 gate_ui_ctrl_set_text(&txtbox->ctrl, caption);
631 }
632 }
633
634 return GATE_RESULT_OK;
635 }
636
637 gate_result_t gate_ui_textbox_get_line(gate_ui_textbox_t* txtbox, gate_uint32_t* currentLine, gate_uint32_t* lineCount)
638 {
639 gate_result_t ret = GATE_RESULT_FAILED;
640 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl);
641 gate_bool_t multiline = GTK_IS_ENTRY(widget) ? false : true;
642
643 if (multiline)
644 {
645 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(widget);
646 if (scroll_window)
647 {
648 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
649 if (text_view)
650 {
651 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
652 if (buffer)
653 {
654 if (lineCount != NULL)
655 {
656 *lineCount = gtk_text_buffer_get_line_count(buffer);
657 }
658 if (currentLine != NULL)
659 {
660 GtkTextIter iter;
661 GtkTextMark* mark = gtk_text_buffer_get_insert(buffer);
662 gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
663 *currentLine = gtk_text_iter_get_line(&iter);
664 }
665 ret = GATE_RESULT_OK;
666 }
667 }
668 }
669 }
670 else
671 {
672 GtkEntry* entry = GTK_ENTRY(widget);
673 if (entry)
674 {
675 if (lineCount != NULL)
676 {
677 *lineCount = 1;
678 }
679 if (currentLine != NULL)
680 {
681 *currentLine = 0;
682 }
683 ret = GATE_RESULT_OK;
684 }
685 }
686
687
688 return ret;
689 }
690 gate_result_t gate_ui_textbox_get_column(gate_ui_textbox_t* txtbox, gate_uint32_t* currentColumn)
691 {
692 gate_result_t ret = GATE_RESULT_FAILED;
693 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl);
694 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
695
696 if (multiline)
697 {
698 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl));
699 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
700 if (text_view)
701 {
702 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
703 if (buffer)
704 {
705 if (currentColumn != NULL)
706 {
707 GtkTextIter iter;
708 GtkTextMark* mark = gtk_text_buffer_get_insert(buffer);
709 gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
710 *currentColumn = gtk_text_iter_get_line_offset(&iter);
711 }
712 ret = GATE_RESULT_OK;
713 }
714 }
715 }
716 else
717 {
718 GtkEntry* entry = GTK_ENTRY(widget);
719 if (entry)
720 {
721 if (currentColumn)
722 {
723 *currentColumn = 0;
724 }
725 ret = GATE_RESULT_OK;
726 }
727 }
728 return ret;
729 }
730 gate_result_t gate_ui_textbox_get_selection(gate_ui_textbox_t* txtbox, gate_uint32_t* sel_start,
731 gate_uint32_t* sel_end, gate_string_t* sel_text)
732 {
733 gate_result_t ret = GATE_RESULT_FAILED;
734 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl);
735 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
736
737 if (multiline)
738 {
739 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(widget);
740 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
741 if (text_view)
742 {
743 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
744 if (buffer)
745 {
746 GtkTextIter start_iter, end_iter;
747 gtk_text_buffer_get_selection_bounds(buffer, &start_iter, &end_iter);
748 if (sel_start != NULL)
749 {
750 *sel_start = gtk_text_iter_get_offset(&start_iter);
751 }
752 if (sel_end != NULL)
753 {
754 *sel_end = gtk_text_iter_get_offset(&start_iter);
755 }
756 ret = GATE_RESULT_OK;
757 if (sel_text != NULL)
758 {
759 gchar* data = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE);
760 if (NULL == gate_string_create(sel_text, data, gate_str_length(data)))
761 {
762 ret = GATE_RESULT_OUTOFMEMORY;
763 }
764 g_free(data);
765 }
766 }
767 }
768 }
769 else
770 {
771 GtkEntry* entry = GTK_ENTRY(widget);
772 if (entry)
773 {
774 /*TODO*/
775 if (sel_start)
776 {
777 *sel_start = 0;
778 }
779 if (sel_end)
780 {
781 *sel_end = 0;
782 }
783 if (sel_text)
784 {
785 gate_string_create_empty(sel_text);
786 }
787 ret = GATE_RESULT_OK;
788 }
789 }
790
791 return ret;
792 }
793
794 gate_result_t gate_ui_textbox_set_selection(gate_ui_textbox_t* txtbox, gate_uint32_t sel_start,
795 gate_uint32_t sel_end, gate_bool_t scroll_to_sel)
796 {
797 gate_result_t ret = GATE_RESULT_FAILED;
798 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl);
799 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
800
801 do
802 {
803 if (multiline)
804 {
805 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl));
806 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
807 if (text_view)
808 {
809 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
810 if (buffer)
811 {
812 /* TODO: set selection */
813 }
814 }
815 }
816 else
817 {
818 GtkEntry* entry = GTK_ENTRY(widget);
819 if (entry)
820 {
821 /* TODO: set selection */
822 }
823 }
824 } while (0);
825 return ret;
826 }
827 gate_result_t gate_ui_textbox_replace_selection(gate_ui_textbox_t* txtbox, gate_string_t const* text)
828 {
829 gate_result_t ret = GATE_RESULT_FAILED;
830 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl);
831 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
832
833 do
834 {
835 if (multiline)
836 {
837 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl));
838 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
839 if (text_view)
840 {
841 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
842 if (buffer)
843 {
844 /* TODO: replace selection */
845 }
846 }
847 }
848 else
849 {
850 GtkEntry* entry = GTK_ENTRY(widget);
851 if (entry)
852 {
853 /* TODO: replace selection */
854 }
855 }
856 } while (0);
857 return ret;
858 }
859
860 gate_result_t gate_ui_textbox_undo(gate_ui_textbox_t* txtbox)
861 {
862 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
863 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl);
864 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
865
866 do
867 {
868 if (multiline)
869 {
870 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl));
871 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
872 if (text_view)
873 {
874 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
875 if (buffer)
876 {
877 /*TODO: UNDO feature*/
878 }
879 }
880 }
881 else
882 {
883 GtkEntry* entry = GTK_ENTRY(widget);
884 if (entry)
885 {
886 /* TODO: UNDO feature */
887 }
888 }
889 } while (0);
890 return ret;
891 }
892 gate_result_t gate_ui_textbox_set_font(gate_ui_textbox_t* txtbox, gate_ui_font_t const* font)
893 {
894 gate_result_t ret = GATE_RESULT_FAILED;
895 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl);
896 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
897
898 do
899 {
900 if (multiline)
901 {
902 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl));
903 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
904 if (text_view)
905 {
906 ret = gate_ui_gtk_ctrl_set_font(GTK_WIDGET(text_view), font);
907 }
908 }
909 else
910 {
911 GtkEntry* entry = GTK_ENTRY(widget);
912 if (entry)
913 {
914 ret = gate_ui_gtk_ctrl_set_font(GTK_WIDGET(entry), font);
915 }
916 }
917 } while (0);
918 return ret;
919 }
920
921 gate_result_t gate_ui_textbox_find_next(gate_ui_textbox_t* txtbox, gate_string_t const* token, gate_uint32_t flags)
922 {
923 gate_result_t ret = GATE_RESULT_FAILED;
924 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl);
925 gate_bool_t const multiline = GTK_IS_ENTRY(widget) ? false : true;
926
927 do
928 {
929 if (multiline)
930 {
931 GtkScrolledWindow* scroll_window = GTK_SCROLLED_WINDOW(GATE_UI_GTK_GET_CTRL_WIDGET(&txtbox->ctrl));
932 GtkTextView* text_view = GTK_TEXT_VIEW(gtk_bin_get_child(GTK_BIN(scroll_window)));
933 if (text_view)
934 {
935 GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
936 if (buffer)
937 {
938 /* TODO: find implementation */
939 }
940 }
941 }
942 else
943 {
944 GtkEntry* entry = GTK_ENTRY(widget);
945 if (entry)
946 {
947 /* TODO: find implementation */
948 }
949 }
950 } while (0);
951 return ret;
952 }
953
954 #endif /* GATE_UI_GTK */
955
956
957
958 #if defined(GATE_UI_MOTIF)
959
960 #include "gate/ui/gateui_motif.h"
961 #include "gate/debugging.h"
962 #include <Xm/TextF.h>
963 #include <Xm/Text.h>
964 #include <Xm/RowColumn.h>
965 #include <Xm/ScrolledW.h>
966
967 7 static Widget textbox_get_widget(gate_ui_ctrl_t* ctrl)
968 {
969 7 Widget w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (w == NULL)
971 {
972 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
973 }
974 7 return w;
975 }
976
977 2 static gate_result_t textbox_get_text(gate_ui_ctrl_t* ctrl, gate_string_t* text)
978 {
979 Widget w, w_txt;
980 char* ptr_text;
981 2 gate_result_t ret = GATE_RESULT_OK;
982
983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(ctrl != NULL);
984 2 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!w)
986 {
987 return GATE_RESULT_INVALIDARG;
988 }
989
990 2 w_txt = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (w_txt)
992 {
993 w = w_txt;
994 }
995 2 ptr_text = XmTextGetString(w);
996
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (text)
997 {
998
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (NULL == gate_string_create(text, ptr_text, gate_str_length(ptr_text)))
999 {
1000 ret = GATE_RESULT_OUTOFMEMORY;
1001 }
1002 }
1003 2 XtFree(ptr_text);
1004 2 return ret;
1005 }
1006
1007 6 static gate_result_t textbox_set_text(gate_ui_ctrl_t* ctrl, gate_string_t const* text)
1008 {
1009 Widget w, w_txt;
1010 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
1011 6 char* ptr_buffer = &buffer[0];
1012 6 gate_size_t bufferlen = gate_string_length(text);
1013
1014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_DEBUG_ASSERT(ctrl != NULL);
1015 6 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
1016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!w)
1017 {
1018 return GATE_RESULT_INVALIDARG;
1019 }
1020 6 w_txt = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
1021
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (w_txt)
1022 {
1023 2 w = w_txt;
1024 }
1025
1026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (bufferlen >= sizeof(buffer))
1027 {
1028 bufferlen += 2;
1029 ptr_buffer = (char*)gate_mem_alloc(bufferlen);
1030 if (ptr_buffer == NULL)
1031 {
1032 return GATE_RESULT_OUTOFMEMORY;
1033 }
1034 }
1035 else
1036 {
1037 6 bufferlen = sizeof(buffer);
1038 }
1039
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (text)
1040 {
1041 6 gate_string_to_buffer(text, ptr_buffer, bufferlen);
1042 }
1043 else
1044 {
1045 ptr_buffer[0] = 0;
1046 }
1047 6 XmTextSetString(w, ptr_buffer);
1048
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (ptr_buffer && (ptr_buffer != &buffer[0]))
1049 {
1050 gate_mem_dealloc(ptr_buffer);
1051 }
1052 6 return GATE_RESULT_OK;
1053 }
1054
1055 4 static gate_result_t textbox_destroy(gate_ui_ctrl_t* ctrl)
1056 {
1057 Widget w;
1058 Widget w_txt;
1059
1060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(ctrl != NULL);
1061
1062 4 w_txt = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
1063
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (w_txt)
1064 {
1065
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (XtIsRealized(w_txt))
1066 {
1067 1 XtUnrealizeWidget(w_txt);
1068 }
1069 1 XtUnmanageChild(w_txt);
1070 1 XtDestroyWidget(w_txt);
1071 1 GATE_UI_MOTIF_SET_CTRL_CONTAINER(ctrl, NULL);
1072 }
1073
1074 4 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
1075
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (w)
1076 {
1077
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (XtIsRealized(w))
1078 {
1079 4 XtUnrealizeWidget(w);
1080 }
1081 4 XtUnmanageChild(w);
1082 4 XtDestroyWidget(w);
1083 4 GATE_UI_MOTIF_SET_CTRL_WIDGET(ctrl, NULL);
1084 }
1085
1086 4 return GATE_RESULT_OK;
1087 }
1088
1089
1090 static gate_ui_motif_dispatcher_t textbox_dispatcher =
1091 {
1092 &textbox_destroy,
1093 &textbox_get_text,
1094 &textbox_set_text,
1095 NULL,
1096 NULL,
1097 NULL,
1098 NULL
1099 };
1100
1101 4 gate_result_t gate_ui_textbox_create(gate_ui_textbox_t* txtbox, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
1102 gate_string_t const* caption, gate_uint32_t flags, void* userparam)
1103 {
1104 4 gate_result_t ret = GATE_RESULT_FAILED;
1105 do
1106 {
1107 4 Widget w = NULL;
1108 Arg args[12];
1109 4 Cardinal args_count = 0;
1110
1111
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (!txtbox || !parent)
1112 {
1113 ret = GATE_RESULT_INVALIDARG;
1114 break;
1115 }
1116
1117
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_TEXTBOX_MULTILINE))
1118 {
1119 1 Widget w_txt = NULL;
1120 1 Widget parent_widget = GATE_UI_MOTIF_GET_CTRL_CONTAINER(parent);
1121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!parent_widget)
1122 {
1123 parent_widget = GATE_UI_MOTIF_GET_CTRL_WIDGET(parent);
1124 }
1125 1 XtSetArg(args[args_count], XmNscrollingPolicy, XmAPPLICATION_DEFINED);++args_count;
1126 1 XtSetArg(args[args_count], XmNvisualPolicy, XmVARIABLE);++args_count;
1127 1 XtSetArg(args[args_count], XmNscrollBarDisplayPolicy, XmSTATIC);++args_count;
1128 //XtSetArg(args[args_count], XmNshadowThickness, 0);++args_count;
1129 1 XtSetArg(args[args_count], XmNshadowThickness, 0); ++args_count;
1130 1 XtSetArg(args[args_count], XmNhighlightThickness, 0); ++args_count;
1131
1132 1 w = XmCreateScrolledWindow(parent_widget, NULL, args, args_count);
1133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!w)
1134 {
1135 ret = GATE_RESULT_OUTOFRESOURCES;
1136 break;
1137 }
1138 1 XtManageChild(w);
1139
1140 1 args_count = 0;
1141 1 XtSetArg(args[args_count], XmNeditMode, XmMULTI_LINE_EDIT); ++args_count;
1142 1 XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
1143 1 XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
1144
1145 1 w_txt = XmCreateText(w, NULL, args, args_count);
1146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!w_txt)
1147 {
1148 XtUnmanageChild(w);
1149 XtDestroyWidget(w);
1150 ret = GATE_RESULT_OUTOFRESOURCES;
1151 break;
1152 }
1153
1154 1 ret = gate_ui_motif_ctrl_init(&txtbox->ctrl, w, userparam, NULL, parent,
1155 w_txt, position, &flags, &textbox_dispatcher);
1156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1157
1158 1 XtManageChild(w_txt);
1159 1 textbox_set_text(&txtbox->ctrl, caption);
1160 }
1161 else
1162 {
1163 3 WidgetClass cls = xmTextWidgetClass;
1164 3 XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
1165 3 XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
1166
1167 3 ret = gate_ui_motif_ctrl_create(&txtbox->ctrl, cls, userparam, NULL, parent,
1168 position, &flags, false, &textbox_dispatcher, args, args_count);
1169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1170
1171 3 textbox_set_text(&txtbox->ctrl, caption);
1172 }
1173
1174 } while (0);
1175
1176 4 return ret;
1177 }
1178
1179 2 gate_result_t gate_ui_textbox_get_line(gate_ui_textbox_t* txtbox, gate_uint32_t* currentLine, gate_uint32_t* lineCount)
1180 {
1181 2 Widget w = textbox_get_widget(&txtbox->ctrl);
1182
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!gate_ui_motif_widget_is_valid(w))
1183 {
1184 return GATE_RESULT_INVALIDARG;
1185 }
1186
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (currentLine)
1187 {
1188 1 XmTextPosition pos = XmTextGetCursorPosition(w);
1189 Position x, y;
1190
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (XmTextPosToXY(w, pos, &x, &y))
1191 {
1192 1 *currentLine = y;
1193 }
1194 }
1195
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (lineCount)
1196 {
1197 1 int cnt = 0;
1198 1 XtVaGetValues(w, XmNtotalLines, &cnt, NULL, NULL);
1199 1 *lineCount = cnt;
1200 }
1201 2 return GATE_RESULT_OK;
1202 }
1203
1204 1 gate_result_t gate_ui_textbox_get_column(gate_ui_textbox_t* txtbox, gate_uint32_t* currentColumn)
1205 {
1206 1 Widget w = textbox_get_widget(&txtbox->ctrl);
1207
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!gate_ui_motif_widget_is_valid(w))
1208 {
1209 return GATE_RESULT_INVALIDARG;
1210 }
1211
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (currentColumn)
1212 {
1213 1 XmTextPosition pos = XmTextGetCursorPosition(w);
1214 Position x, y;
1215
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (XmTextPosToXY(w, pos, &x, &y))
1216 {
1217 1 *currentColumn = x;
1218 }
1219 }
1220 1 return GATE_RESULT_OK;
1221 }
1222
1223 2 gate_result_t gate_ui_textbox_get_selection(gate_ui_textbox_t* textbox, gate_uint32_t* sel_start, gate_uint32_t* sel_end, gate_string_t* sel_text)
1224 {
1225 2 gate_result_t ret = GATE_RESULT_FAILED;
1226 2 Widget w = textbox_get_widget(&textbox->ctrl);
1227
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_ui_motif_widget_is_valid(w))
1228 {
1229 2 XmTextPosition left = 0;
1230 2 XmTextPosition right = 0;
1231 2 XmTextGetSelectionPosition(w, &left, &right);
1232
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(sel_start != NULL)
1233 {
1234 1 *sel_start = left;
1235 }
1236
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(sel_end != NULL)
1237 {
1238 1 *sel_end = right;
1239 }
1240
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (sel_text != NULL)
1241 {
1242 1 char const* txt = XmTextGetSelection(w);
1243 1 gate_string_create(sel_text, txt, gate_str_length(txt));
1244 }
1245 2 ret = GATE_RESULT_OK;
1246 }
1247 2 return ret;
1248 }
1249
1250 1 gate_result_t gate_ui_textbox_set_selection(gate_ui_textbox_t* textbox, gate_uint32_t sel_start, gate_uint32_t sel_end, gate_bool_t scroll_to_sel)
1251 {
1252 1 gate_result_t ret = GATE_RESULT_FAILED;
1253 1 Widget w = textbox_get_widget(&textbox->ctrl);
1254
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_ui_motif_widget_is_valid(w))
1255 {
1256 1 gate_ui_host_t* ptr_host = GATE_UI_MOTIF_GET_CTRL_HOST(&textbox->ctrl);
1257 1 Display* ptr_dpy = GATE_UI_MOTIF_GET_HOST_DISPLAY(ptr_host);
1258 1 XmTextPosition left = sel_start;
1259 1 XmTextPosition right = sel_end;
1260 1 Time tm = XtLastTimestampProcessed(ptr_dpy);
1261 1 XmTextSetSelection(w, left, right, tm);
1262 1 ret = GATE_RESULT_OK;
1263 }
1264 1 return ret;
1265 }
1266
1267 1 gate_result_t gate_ui_textbox_replace_selection(gate_ui_textbox_t* textbox, gate_string_t const* text)
1268 {
1269 1 gate_result_t ret = GATE_RESULT_FAILED;
1270 1 Widget w = textbox_get_widget(&textbox->ctrl);
1271
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_ui_motif_widget_is_valid(w))
1272 {
1273
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if(gate_string_is_empty(text))
1274 {
1275 XmTextRemove(w);
1276 }
1277 else
1278 {
1279 1 XmTextPosition left = 0;
1280 1 XmTextPosition right = 0;
1281 1 XmTextGetSelectionPosition(w, &left, &right);
1282 gate_cstrbuffer8_t buffer;
1283 1 gate_cstrbuffer_create_string(&buffer, text, false);
1284 1 XmTextReplace(w, left, right, (char*)gate_cstrbuffer_get(&buffer));
1285 1 gate_cstrbuffer_destroy(&buffer);
1286 }
1287 1 ret = GATE_RESULT_OK;
1288 }
1289 1 return ret;
1290 }
1291
1292 gate_result_t gate_ui_textbox_undo(gate_ui_textbox_t* textbox)
1293 {
1294 return GATE_RESULT_NOTIMPLEMENTED;
1295 }
1296
1297 gate_result_t gate_ui_textbox_set_font(gate_ui_textbox_t* textbox, gate_ui_font_t const* font)
1298 {
1299 return GATE_RESULT_OK;
1300 }
1301
1302 gate_result_t gate_ui_textbox_find_next(gate_ui_textbox_t* textbox, gate_string_t const* token, gate_uint32_t flags)
1303 {
1304 return GATE_RESULT_NOTIMPLEMENTED;
1305 }
1306
1307 #endif /* GATE_UI_MOTIF */
1308