GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/textboxes.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 138 0.0%
Functions: 0 13 0.0%
Branches: 0 62 0.0%

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