GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/comboboxes.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 155 0.0%
Functions: 0 11 0.0%
Branches: 0 58 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/comboboxes.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_combobox_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 hwndCtrl;
41 gate_ui_combobox_t* combobox;
42 LRESULT sel_index;
43 gate_ui_host_t* host;
44
45 if ((ctrl != NULL) && (hwnd != NULL))
46 {
47 hwndCtrl = GATE_UI_WINAPI_GET_HWND(ctrl);
48 host = GATE_UI_WINAPI_GET_HOST(ctrl);
49 if (hwndCtrl)
50 {
51 switch (msg)
52 {
53 case WM_COMMAND:
54 {
55 if (hwndCtrl == (HWND)lParam)
56 {
57 combobox = (gate_ui_combobox_t*)ctrl;
58 switch (HIWORD(wParam))
59 {
60 case CBN_SELCHANGE:
61 {
62 sel_index = SendMessage(hwndCtrl, CB_GETCURSEL, 0, 0);
63 if ((sel_index != CB_ERR) && (combobox->on_select != NULL))
64 {
65 combobox->on_select(&combobox->ctrl, sel_index);
66 }
67 *lresult = 0;
68 return true;
69 }
70 default:
71 {
72 break;
73 }
74 }
75 }
76 break;
77 }
78 default:
79 {
80 break;
81 }
82 }
83 }
84 }
85 return false;
86 }
87
88 static gate_result_t gate_ui_combobox_set_position(gate_ui_ctrl_t* ctrl, gate_ui_point_t const* position, gate_ui_size_t const* size)
89 {
90 gate_ui_host_t* host = GATE_UI_WINAPI_GET_HOST(ctrl);
91 gate_ui_size_t new_size;
92 gate_uint32_t line_height;
93 if (size)
94 {
95 line_height = gate_ui_host_default_line_height(host);
96 new_size = *size;
97 if (new_size.height < (int)(line_height * 10))
98 {
99 new_size.height = (int)(line_height * 10);
100 }
101 }
102 return gate_ui_winapi_set_position(ctrl, position, size ? &new_size : NULL);
103 }
104
105 static gate_ui_winapi_dispatchers_t global_win32_combobox_dispatchers =
106 {
107 &gate_ui_winapi_destroy_with_font,
108 &gate_ui_winapi_is_enabled,
109 &gate_ui_winapi_is_visible,
110 &gate_ui_winapi_is_focused,
111 &gate_ui_winapi_get_position,
112 &gate_ui_winapi_get_size,
113 &gate_ui_winapi_get_children,
114 &gate_ui_winapi_get_text_length,
115 &gate_ui_winapi_get_text,
116 &gate_ui_winapi_get_state,
117 &gate_ui_winapi_set_enabled,
118 &gate_ui_winapi_set_visible,
119 &gate_ui_winapi_set_focus,
120 &gate_ui_combobox_set_position,
121 &gate_ui_winapi_set_text,
122 &gate_ui_winapi_set_state,
123 &gate_ui_winapi_refresh
124 };
125
126 gate_result_t gate_ui_combobox_create(
127 gate_ui_combobox_t* combobox, gate_ui_ctrl_t* parent,
128 gate_ui_position_t const* position,
129 gate_uint32_t flags,
130 void* userparam
131 )
132 {
133 gate_result_t ret;
134 gate_uint32_t styles, exstyles;
135 gate_ui_host_t* host;
136 gate_ui_position_t adapted_position;
137 HWND hwndParent, hwndCtrl;
138
139 do
140 {
141 host = gate_ui_ctrl_get_host(parent);
142 if (host == NULL)
143 {
144 ret = GATE_RESULT_INVALIDSTATE;
145 break;
146 }
147 hwndParent = GATE_UI_WINAPI_GET_HWND(parent);
148 if (!hwndParent)
149 {
150 ret = GATE_RESULT_INVALIDSTATE;
151 break;
152 }
153
154 gate_mem_clear(combobox, sizeof(gate_ui_combobox_t));
155
156 exstyles = 0;
157 styles = WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_NOINTEGRALHEIGHT;
158 /*styles |= BS_FLAT;*/
159 if (!GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_ENABLED)) styles |= WS_DISABLED;
160 if (GATE_FLAG_ENABLED(flags, GATE_UI_FLAG_VISIBLE)) styles |= WS_VISIBLE;
161
162 ret = gate_ui_winapi_create(&combobox->ctrl, host, (void*)hwndParent, _T("COMBOBOX"),
163 position ? &adapted_position : NULL, styles, exstyles, NULL, userparam, true);
164 if (GATE_SUCCEEDED(ret))
165 {
166 GATE_UI_WINAPI_SET_DISPATCHER(&combobox->ctrl, &global_win32_combobox_dispatchers);
167 hwndCtrl = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
168 gate_ui_winapi_register_event(host, (void*)hwndParent, WM_COMMAND, &gate_ui_combobox_events, &combobox->ctrl);
169 }
170 } while (0);
171
172 return ret;
173 }
174
175 gate_size_t gate_ui_combobox_get_item_count(gate_ui_combobox_t* combobox)
176 {
177 gate_size_t ret = 0;
178 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
179 LRESULT result;
180 if (hwnd)
181 {
182 result = SendMessage(hwnd, CB_GETCOUNT, 0, 0);
183 if (result != CB_ERR)
184 {
185 ret = (gate_size_t)result;
186 }
187 }
188 return ret;
189 }
190
191 gate_result_t gate_ui_combobox_insert_item(gate_ui_combobox_t* combobox, gate_size_t const* at_index,
192 gate_string_t const* text, void* itemparam)
193 {
194 gate_result_t ret = GATE_RESULT_FAILED;
195 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
196 TCHAR text_buffer[4096];
197 LRESULT new_index;
198 if (hwnd)
199 {
200 if (text)
201 {
202 gate_win32_utf8_2_winstr(text->str, text->length, text_buffer, sizeof(text_buffer) / sizeof(text_buffer[0]));
203 }
204 else
205 {
206 text_buffer[0] = 0;
207 }
208 new_index = SendMessage(hwnd, CB_INSERTSTRING, (at_index ? (WPARAM)*at_index : (WPARAM)-1), (LPARAM)text_buffer);
209 if (CB_ERR == new_index)
210 {
211 ret = GATE_RESULT_FAILED;
212 }
213 else
214 {
215 SendMessage(hwnd, CB_SETITEMDATA, (WPARAM)new_index, (LPARAM)(gate_intptr_t)itemparam);
216 ret = GATE_RESULT_OK;
217 }
218 }
219 return ret;
220 }
221
222 gate_result_t gate_ui_combobox_remove_item(gate_ui_combobox_t* combobox, gate_size_t index)
223 {
224 gate_result_t ret = GATE_RESULT_FAILED;
225 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
226 if (hwnd)
227 {
228 SendMessage(hwnd, CB_DELETESTRING, (WPARAM)index, 0);
229 ret = GATE_RESULT_OK;
230 }
231 return ret;
232 }
233
234 gate_result_t gate_ui_combobox_get_selected_item(gate_ui_combobox_t* combobox, gate_size_t* index)
235 {
236 gate_result_t ret = GATE_RESULT_FAILED;
237 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
238 LRESULT sel_index;
239 if (hwnd)
240 {
241 sel_index = SendMessage(hwnd, CB_GETCURSEL, 0, 0);
242 if (sel_index == CB_ERR)
243 {
244 ret = GATE_RESULT_NOTAVAILABLE;
245 }
246 else
247 {
248 if (index)
249 {
250 *index = sel_index;
251 }
252 ret = GATE_RESULT_OK;
253 }
254 }
255 return ret;
256 }
257
258 gate_result_t gate_ui_combobox_set_selected_item(gate_ui_combobox_t* combobox, gate_size_t index)
259 {
260 gate_result_t ret = GATE_RESULT_FAILED;
261 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
262 if (hwnd)
263 {
264 SendMessage(hwnd, CB_SETCURSEL, (WPARAM)index, 0);
265 ret = GATE_RESULT_OK;
266 }
267 return ret;
268 }
269
270 gate_result_t gate_ui_combobox_get_item_text(gate_ui_combobox_t* combobox, gate_size_t index, gate_string_t* text)
271 {
272 gate_result_t ret = GATE_RESULT_FAILED;
273 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
274 TCHAR buffer[4096];
275 TCHAR* ptr_buffer = &buffer[0];
276 LRESULT buf_len;
277
278 do
279 {
280 if (!hwnd)
281 {
282 ret = GATE_RESULT_FAILED;
283 break;
284 }
285
286 buf_len = SendMessage(hwnd, CB_GETLBTEXTLEN, (WPARAM)index, 0);
287 if (CB_ERR == buf_len)
288 {
289 ret = GATE_RESULT_FAILED;
290 break;
291 }
292
293 if (buf_len >= sizeof(buffer) / sizeof(buffer[0]))
294 {
295 ptr_buffer = (TCHAR*)gate_mem_alloc((buf_len + 2) * sizeof(TCHAR));
296 if (ptr_buffer == NULL)
297 {
298 ret = GATE_RESULT_OUTOFMEMORY;
299 break;
300 }
301 }
302 buf_len = SendMessage(hwnd, CB_GETLBTEXT, (WPARAM)index, (LPARAM)(gate_intptr_t)ptr_buffer);
303 if (buf_len > 0)
304 {
305 if (NULL == gate_win32_winstr_2_utf8_string(ptr_buffer, buf_len, text))
306 {
307 ret = GATE_RESULT_OUTOFMEMORY;
308 break;
309 }
310 }
311 else
312 {
313 gate_string_create_empty(text);
314 }
315 ret = GATE_RESULT_OK;
316
317 } while (0);
318
319 if ((ptr_buffer != &buffer[0]) && (ptr_buffer != NULL))
320 {
321 gate_mem_dealloc(ptr_buffer);
322 }
323
324 return ret;
325 }
326
327 void* gate_ui_combobox_get_item_param(gate_ui_combobox_t* combobox, gate_size_t index)
328 {
329 void* ret = NULL;
330 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
331 LRESULT data;
332 if (hwnd)
333 {
334 data = SendMessage(hwnd, CB_GETITEMDATA, (WPARAM)index, 0);
335 ret = (void*)(gate_intptr_t)data;
336 }
337 return ret;
338 }
339
340 gate_result_t gate_ui_combobox_find_item_param(gate_ui_combobox_t* combobox, void* input_match_param,
341 gate_size_t* output_match_index, gate_size_t start_at)
342 {
343 gate_result_t ret = GATE_RESULT_FAILED;
344 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
345 LRESULT lresult, ndx;
346 LRESULT data;
347 if (hwnd)
348 {
349 lresult = SendMessage(hwnd, CB_GETCOUNT, 0, 0);
350 if (lresult != CB_ERR)
351 {
352 ret = GATE_RESULT_NOMATCH;
353 for (ndx = (LRESULT)start_at; ndx < lresult; ++ndx)
354 {
355 data = SendMessage(hwnd, CB_GETITEMDATA, (WPARAM)ndx, 0);
356 if ((LRESULT)input_match_param == data)
357 {
358 if (output_match_index)
359 {
360 *output_match_index = (gate_size_t)ndx;
361 ret = GATE_RESULT_OK;
362 break;
363 }
364 }
365 }
366 }
367 }
368 return ret;
369 }
370
371
372 gate_result_t gate_ui_combobox_set_item_text(gate_ui_combobox_t* combobox, gate_size_t index, gate_string_t const* text)
373 {
374 gate_result_t ret = GATE_RESULT_FAILED;
375 void* item_data = gate_ui_combobox_get_item_param(combobox, index);
376 ret = gate_ui_combobox_insert_item(combobox, &index, text, item_data);
377 if (GATE_SUCCEEDED(ret))
378 {
379 gate_ui_combobox_remove_item(combobox, index + 1);
380 }
381 return ret;
382 }
383
384 gate_result_t gate_ui_combobox_clear(gate_ui_combobox_t* combobox)
385 {
386 gate_result_t ret = GATE_RESULT_FAILED;
387 HWND hwnd = GATE_UI_WINAPI_GET_HWND(&combobox->ctrl);
388 if (hwnd)
389 {
390 SendMessage(hwnd, CB_RESETCONTENT, 0, 0);
391 ret = GATE_RESULT_OK;
392 }
393 return ret;
394 }
395
396
397 #endif /*GATE_UI_WINAPI*/
398
399
400 #if defined(GATE_UI_GTK)
401
402 #include "gate/ui/gateui_gtk.h"
403
404 gate_result_t gate_ui_combobox_create(gate_ui_combobox_t* combobox, gate_ui_ctrl_t* parent,
405 gate_ui_position_t const* position,
406 gate_uint32_t flags, void* userparam)
407 {
408 gate_result_t ret = GATE_RESULT_OK;
409 GtkWidget* widget;
410 GtkListStore* liststore;
411 GtkCellRenderer* cellrenderer;
412 gate_ui_host_t* host = GATE_UI_GTK_GET_CTRL_HOST(parent);
413
414 gate_mem_clear(combobox, sizeof(gate_ui_combobox_t));
415
416 liststore = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING);
417
418 widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(liststore));
419
420 cellrenderer = gtk_cell_renderer_text_new();
421 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), cellrenderer, TRUE);
422 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(widget), cellrenderer, "text", 1, NULL);
423
424 if (widget == NULL)
425 {
426 return GATE_RESULT_FAILED;
427 }
428
429 ret = gate_ui_gtk_ctrl_init(&combobox->ctrl, widget, host, userparam, parent,
430 NULL, false, false, position, &flags);
431
432 return ret;
433 }
434
435 static gate_bool_t gate_ui_combobox_resolve_index(GtkTreeModel* model, gate_size_t index, GtkTreeIter* found_iter)
436 {
437 gate_bool_t ret = false;
438 GtkTreeIter iter;
439
440 if (!gtk_tree_model_get_iter_first(model, &iter))
441 {
442 return false;
443 }
444
445 do
446 {
447 if (index == 0)
448 {
449 *found_iter = iter;
450 ret = true;
451 break;
452 }
453 --index;
454 } while (gtk_tree_model_iter_next(model, &iter));
455 return ret;
456 }
457
458 gate_size_t gate_ui_combobox_get_item_count(gate_ui_combobox_t* combobox)
459 {
460 gate_size_t ret = 0;
461 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
462 GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
463 GtkListStore* store = GTK_LIST_STORE(model);
464 GtkTreeIter iter;
465
466 if (gtk_tree_model_get_iter_first(model, &iter))
467 {
468 do
469 {
470 ++ret;
471 } while (gtk_tree_model_iter_next(model, &iter));
472 }
473
474 return ret;
475 }
476
477 gate_result_t gate_ui_combobox_insert_item(gate_ui_combobox_t* combobox, gate_size_t const* atIndex,
478 gate_string_t const* text, void* itemparam)
479 {
480 gate_result_t ret = GATE_RESULT_FAILED;
481
482 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
483 GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
484 GtkListStore* store = GTK_LIST_STORE(model);
485 GtkTreeIter at_iter;
486 GtkTreeIter new_iter;
487 char text_buffer[GATE_MAX_COPYBUFFER_LENGTH];
488
489
490 if (atIndex != NULL)
491 {
492 if (gate_ui_combobox_resolve_index(model, *atIndex, &at_iter))
493 {
494 gtk_list_store_insert_before(store, &new_iter, &at_iter);
495 }
496 else
497 {
498 gtk_list_store_append(store, &new_iter);
499 }
500 }
501 else
502 {
503 gtk_list_store_append(store, &new_iter);
504 }
505
506 if (text != NULL)
507 {
508 GATE_STRING_TO_BUFFER(text, text_buffer);
509 gtk_list_store_set(store, &new_iter,
510 0, itemparam,
511 1, text_buffer,
512 -1);
513 }
514 else
515 {
516 gtk_list_store_set(store, &new_iter,
517 0, itemparam,
518 -1);
519 }
520 ret = GATE_RESULT_OK;
521
522 return ret;
523 }
524
525 gate_result_t gate_ui_combobox_remove_item(gate_ui_combobox_t* combobox, gate_size_t index)
526 {
527 gate_result_t ret = GATE_RESULT_FAILED;
528
529 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
530 GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
531 GtkListStore* store = GTK_LIST_STORE(model);
532 GtkTreeIter iter;
533
534 if (gate_ui_combobox_resolve_index(model, index, &iter))
535 {
536 if (gtk_list_store_remove(store, &iter))
537 {
538 ret = GATE_RESULT_OK;
539 }
540 }
541 else
542 {
543 ret = GATE_RESULT_NOTAVAILABLE;
544 }
545 return ret;
546 }
547
548 gate_result_t gate_ui_combobox_get_selected_item(gate_ui_combobox_t* combobox, gate_size_t* index)
549 {
550 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
551 gint ndx = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
552 if (ndx < 0)
553 {
554 return GATE_RESULT_NOTAVAILABLE;
555 }
556 else
557 {
558 *index = (gate_size_t)ndx;
559 return GATE_RESULT_OK;
560 }
561 }
562
563 gate_result_t gate_ui_combobox_set_selected_item(gate_ui_combobox_t* combobox, gate_size_t index)
564 {
565 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
566 gtk_combo_box_set_active(GTK_COMBO_BOX(widget), (gint)index);
567 return GATE_RESULT_OK;
568 }
569
570 gate_result_t gate_ui_combobox_get_item_text(gate_ui_combobox_t* combobox, gate_size_t index, gate_string_t* text)
571 {
572 gate_result_t ret = GATE_RESULT_FAILED;
573 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
574 GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
575 GtkListStore* store = GTK_LIST_STORE(model);
576 GtkTreeIter iter;
577 GValue value = GATE_INIT_EMPTY;
578 gchar const* ptr_text;
579
580 if (gate_ui_combobox_resolve_index(model, index, &iter))
581 {
582 gtk_tree_model_get_value(model, &iter, 1, &value);
583 ptr_text = g_value_get_string(&value);
584 if (NULL == gate_string_create(text, ptr_text, gate_str_length(ptr_text)))
585 {
586 ret = GATE_RESULT_OUTOFMEMORY;
587 }
588 else
589 {
590 ret = GATE_RESULT_OK;
591 }
592 g_value_unset(&value);
593 }
594 else
595 {
596 ret = GATE_RESULT_NOTAVAILABLE;
597 }
598 return ret;
599 }
600
601 void* gate_ui_combobox_get_item_param(gate_ui_combobox_t* combobox, gate_size_t index)
602 {
603 void* ret = NULL;
604 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
605 GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
606 GtkListStore* store = GTK_LIST_STORE(model);
607 GtkTreeIter iter;
608 GValue value = GATE_INIT_EMPTY;
609
610 if (gate_ui_combobox_resolve_index(model, index, &iter))
611 {
612 gtk_tree_model_get_value(model, &iter, 0, &value);
613 ret = g_value_get_pointer(&value);
614 g_value_unset(&value);
615 }
616 return ret;
617 }
618 gate_result_t gate_ui_combobox_find_item_param(gate_ui_combobox_t* combobox, void* input_match_param,
619 gate_size_t* output_match_index, gate_size_t start_at)
620 {
621 gate_result_t ret = GATE_RESULT_FAILED;
622 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
623 GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
624 GtkListStore* store = GTK_LIST_STORE(model);
625 GtkTreeIter iter;
626 gate_size_t index;
627 GValue value = GATE_INIT_EMPTY;
628 gpointer data_ptr;
629 gate_bool_t param_found;
630
631 if (gtk_tree_model_get_iter_first(model, &iter))
632 {
633 ret = GATE_RESULT_NOMATCH;
634 index = 0;
635 do
636 {
637 if (index >= start_at)
638 {
639 gtk_tree_model_get_value(model, &iter, 0, &value);
640 data_ptr = g_value_get_pointer(&value);
641 param_found = (data_ptr == input_match_param);
642 g_value_unset(&value);
643 if (param_found)
644 {
645 if (output_match_index)
646 {
647 *output_match_index = index;
648 }
649 ret = GATE_RESULT_OK;
650 break;
651 }
652 }
653 ++index;
654 } while (gtk_tree_model_iter_next(model, &iter));
655 }
656 return ret;
657 }
658
659 gate_result_t gate_ui_combobox_set_item_text(gate_ui_combobox_t* combobox, gate_size_t index, gate_string_t const* text)
660 {
661 gate_result_t ret = GATE_RESULT_FAILED;
662 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
663 GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
664 GtkListStore* store = GTK_LIST_STORE(model);
665 GtkTreeIter iter;
666 GValue value = GATE_INIT_EMPTY;
667 gchar text_buffer[GATE_MAX_COPYBUFFER_LENGTH];
668
669 if (gate_ui_combobox_resolve_index(model, index, &iter))
670 {
671 GATE_STRING_TO_BUFFER(text, text_buffer);
672 g_value_set_string(&value, text_buffer);
673 gtk_list_store_set_value(store, &iter, 1, &value);
674 g_value_unset(&value);
675 }
676 else
677 {
678 ret = GATE_RESULT_NOTAVAILABLE;
679 }
680 return ret;
681 }
682
683 gate_result_t gate_ui_combobox_clear(gate_ui_combobox_t* combobox)
684 {
685 gate_result_t ret = GATE_RESULT_FAILED;
686 GtkWidget* widget = GATE_UI_GTK_GET_CTRL_WIDGET(&combobox->ctrl);
687 GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
688 GtkListStore* store = GTK_LIST_STORE(model);
689 gtk_list_store_clear(store);
690 ret = GATE_RESULT_OK;
691 return ret;
692 }
693
694 #endif /* GATE_UI_GTK */
695
696
697
698 #if defined(GATE_UI_MOTIF)
699
700 #include "gate/ui/gateui_motif.h"
701 #include <Xm/ComboBox.h>
702
703 gate_result_t gate_ui_combobox_create(gate_ui_combobox_t* combobox, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
704 gate_uint32_t flags, void* userparam)
705 {
706 Widget w;
707 Widget w_parent = NULL;
708 gate_result_t ret = GATE_RESULT_FAILED;
709 gate_ui_host_t* host = NULL;
710 Arg args[8];
711 unsigned args_count = 0;
712 gate_arraylist_t item_params = NULL;
713
714 do
715 {
716 w_parent = (Widget)GATE_UI_MOTIF_GET_CTRL_CONTAINER(parent);
717 if (NULL == w_parent)
718 {
719 w_parent = (Widget)GATE_UI_MOTIF_GET_CTRL_WIDGET(parent);
720 }
721 if (NULL == w_parent)
722 {
723 ret = GATE_RESULT_INVALIDSTATE;
724 break;
725 }
726 host = GATE_UI_MOTIF_GET_CTRL_HOST(parent);
727 if (NULL == host)
728 {
729 ret = GATE_RESULT_INVALIDSTATE;
730 break;
731 }
732
733 XtSetArg(args[args_count], XmNcomboBoxType, XmDROP_DOWN_LIST); ++args_count;
734 XtSetArg(args[args_count], XmNvisibleItemCount, 12); ++args_count;
735 XtSetArg(args[args_count], XmNpositionMode, XmONE_BASED); ++args_count;
736 XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
737 XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
738
739 w = XmCreateComboBox(w_parent, NULL, args, args_count);
740 if (w == NULL)
741 {
742 ret = GATE_RESULT_FAILED;
743 break;
744 }
745 XtManageChild(w);
746 ret = gate_ui_motif_ctrl_init(&combobox->ctrl, w, userparam, host, parent, NULL, position, &flags, NULL);
747 GATE_BREAK_IF_FAILED(ret);
748
749 item_params = gate_arraylist_create(sizeof(void*), NULL, 16, NULL, NULL);
750 if (item_params == NULL)
751 {
752 gate_ui_motif_ctrl_destroy(&combobox->ctrl);
753 ret = GATE_RESULT_OUTOFMEMORY;
754 break;
755 }
756 GATE_UI_MOTIF_SET_CTRL_PRIVATE_ARG(&combobox->ctrl, item_params);
757 } while (0);
758 return ret;
759 }
760
761 gate_size_t gate_ui_combobox_get_item_count(gate_ui_combobox_t* combobox)
762 {
763 const Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&combobox->ctrl);
764 int cnt = 0;
765 if (w != NULL)
766 {
767 XtVaGetValues(w, XmNitemCount, &cnt, NULL);
768 }
769
770 return (gate_size_t)cnt;
771 }
772
773 gate_result_t gate_ui_combobox_insert_item(gate_ui_combobox_t* combobox, gate_size_t const* at_index, gate_string_t const* text, void* itemparam)
774 {
775 const Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&combobox->ctrl);
776 gate_result_t ret = GATE_RESULT_FAILED;
777 XmString xstr = NULL;
778 int pos = 0; /* default pos => add at end */
779 gate_arraylist_t item_params = NULL;
780 gate_size_t cnt = 0;
781 void* new_item = NULL;
782
783 item_params = (gate_arraylist_t)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(&combobox->ctrl);
784
785 cnt = gate_ui_combobox_get_item_count(combobox);
786
787 if (at_index)
788 {
789 if (*at_index >= cnt)
790 {
791 pos = 0;
792 }
793 else
794 {
795 pos = (int)(*at_index + 1);
796 }
797 }
798 else
799 {
800 pos = 0;
801 }
802
803 do
804 {
805 xstr = gate_ui_motif_create_string(text);
806 if (xstr == NULL)
807 {
808 ret = GATE_RESULT_OUTOFMEMORY;
809 break;
810 }
811
812 if (pos == 0)
813 {
814 new_item = gate_arraylist_add(item_params, &itemparam);
815 }
816 else
817 {
818 new_item = gate_arraylist_insert(item_params, (gate_size_t)(pos - 1), &itemparam, 1);
819 }
820 if (new_item == NULL)
821 {
822 ret = GATE_RESULT_OUTOFMEMORY;
823 break;
824 }
825
826 XmComboBoxAddItem(w, xstr, pos, False);
827 ret = GATE_RESULT_OK;
828 } while (0);
829
830 if (xstr != NULL)
831 {
832 XmStringFree(xstr);
833 }
834 return ret;
835 }
836
837 gate_result_t gate_ui_combobox_remove_item(gate_ui_combobox_t* combobox, gate_size_t index)
838 {
839 const Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&combobox->ctrl);
840 const gate_arraylist_t item_params = (gate_arraylist_t)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(&combobox->ctrl);
841 const gate_size_t cnt = gate_ui_combobox_get_item_count(combobox);
842 int pos = (int)(index + 1);
843 if (index < cnt)
844 {
845 XmComboBoxDeletePos(w, pos);
846 gate_arraylist_remove(item_params, index, 1);
847 return GATE_RESULT_OK;
848 }
849 else
850 {
851 return GATE_RESULT_OUTOFBOUNDS;
852 }
853 }
854
855 gate_result_t gate_ui_combobox_get_selected_item(gate_ui_combobox_t* combobox, gate_size_t* index)
856 {
857 const Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&combobox->ctrl);
858 int pos = 0;
859 XtVaGetValues(w, XmNselectedPosition, &pos, NULL);
860 if (pos > 0)
861 {
862 if (index != NULL)
863 {
864 *index = (gate_size_t)(pos - 1);
865 }
866 return GATE_RESULT_OK;
867 }
868 else
869 {
870 if (index != NULL)
871 {
872 *index = GATE_UI_COMBOBOX_INVALID_INDEX;
873 }
874 return GATE_RESULT_OK;
875 }
876 return GATE_RESULT_FAILED;
877 }
878
879 gate_result_t gate_ui_combobox_set_selected_item(gate_ui_combobox_t* combobox, gate_size_t index)
880 {
881 const Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&combobox->ctrl);
882 const int pos = (int)index + 1;
883 if (index >= gate_ui_combobox_get_item_count(combobox))
884 {
885 return GATE_RESULT_OUTOFBOUNDS;
886 }
887 XtVaSetValues(w, XmNselectedPosition, pos, NULL);
888 return GATE_RESULT_OK;
889 }
890
891 gate_result_t gate_ui_combobox_get_item_text(gate_ui_combobox_t* combobox, gate_size_t index, gate_string_t* text)
892 {
893 const Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&combobox->ctrl);
894 XmStringTable strings = NULL;
895 if (index >= gate_ui_combobox_get_item_count(combobox))
896 {
897 return GATE_RESULT_OUTOFBOUNDS;
898 }
899 XtVaGetValues(w, XmNitems, &strings, NULL);
900 if (strings)
901 {
902 return gate_ui_motif_convert_string(strings[index], text);
903 }
904 return GATE_RESULT_FAILED;
905 }
906
907 void* gate_ui_combobox_get_item_param(gate_ui_combobox_t* combobox, gate_size_t index)
908 {
909 const gate_arraylist_t item_params = (gate_arraylist_t)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(&combobox->ctrl);
910 void** ptr_param = (void**)gate_arraylist_get(item_params, index);
911 if (ptr_param)
912 {
913 return *ptr_param;
914 }
915 return NULL;
916 }
917
918 gate_result_t gate_ui_combobox_find_item_param(gate_ui_combobox_t* combobox, void* match_param, gate_size_t* match_index, gate_size_t start_at)
919 {
920 const gate_arraylist_t item_params = (gate_arraylist_t)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(&combobox->ctrl);
921 const gate_size_t cnt = gate_arraylist_length(item_params);
922 gate_size_t ndx = start_at;
923 void** ptr_param = NULL;
924
925 while (ndx < cnt)
926 {
927 ptr_param = (void**)gate_arraylist_get(item_params, ndx);
928 if (!ptr_param) break;
929 if (match_param == *ptr_param)
930 {
931 if (match_index)
932 {
933 *match_index = ndx;
934 }
935 return GATE_RESULT_OK;
936 }
937 ++ndx;
938 }
939 return GATE_RESULT_NOMATCH;
940 }
941
942 gate_result_t gate_ui_combobox_set_item_text(gate_ui_combobox_t* combobox, gate_size_t index, gate_string_t const* text)
943 {
944 gate_result_t ret = GATE_RESULT_FAILED;
945 Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&combobox->ctrl);
946 gate_size_t cnt = gate_ui_combobox_get_item_count(combobox);
947 XmString xstr = NULL;
948
949 do
950 {
951 if (index >= cnt)
952 {
953 ret = GATE_RESULT_OUTOFBOUNDS;
954 break;
955 }
956 xstr = gate_ui_motif_create_string(text);
957 if (!xstr)
958 {
959 ret = GATE_RESULT_OUTOFMEMORY;
960 break;
961 }
962 XmComboBoxAddItem(w, xstr, (int)index + 1, False);
963 XmComboBoxDeletePos(w, (int)index + 2);
964 ret = GATE_RESULT_OK;
965 } while (0);
966
967 if (xstr != NULL)
968 {
969 XmStringFree(xstr);
970 }
971 return ret;
972 }
973
974 gate_result_t gate_ui_combobox_clear(gate_ui_combobox_t* combobox)
975 {
976 Widget w = GATE_UI_MOTIF_GET_CTRL_WIDGET(&combobox->ctrl);
977 gate_arraylist_t item_params = (gate_arraylist_t)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(&combobox->ctrl);
978 gate_size_t cnt = gate_ui_combobox_get_item_count(combobox);
979 while (cnt > 0)
980 {
981 XmComboBoxDeletePos(w, (int)cnt);
982 --cnt;
983 }
984 gate_arraylist_clear(item_params);
985 return GATE_RESULT_OK;
986 }
987
988 #endif /* GATE_UI_MOTIF */
989