GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/listviews_motif.c
Date: 2025-09-22 22:57:09
Exec Total Coverage
Lines: 0 830 0.0%
Functions: 0 61 0.0%
Branches: 0 400 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/listviews.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32
33
34 #if defined(GATE_UI_MOTIF)
35
36 #include "gate/ui/gateui_motif.h"
37 #include <Xm/List.h>
38 #include <Xm/Container.h>
39 #include <Xm/Label.h>
40 #include <Xm/ScrolledW.h>
41 #include <Xm/IconG.h>
42 #include <Xm/ScrollBar.h>
43
44 ✗ static gate_size_t gate_ui_listbox_widget_get_item_count(Widget w)
45 {
46 ✗ int list_count = 0;
47 ✗ XtVaGetValues(w, XmNitemCount, &list_count, NULL);
48 ✗ return (gate_size_t)list_count;
49 }
50
51 ✗ gate_result_t gate_ui_listbox_create(gate_ui_listbox_t* lstbox, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
52 gate_uint32_t flags, void* userparam)
53 {
54 ✗ gate_result_t ret = GATE_RESULT_FAILED;
55 ✗ Widget parent_widget = NULL;
56 Widget w;
57 Widget w_list;
58 Arg args[8];
59 Cardinal args_count;
60
61 do
62 {
63 ✗ if (!lstbox || !parent)
64 {
65 ✗ ret = GATE_RESULT_INVALIDARG;
66 ✗ break;
67 }
68
69 ✗ parent_widget = GATE_UI_MOTIF_GET_CTRL_CONTAINER(parent);
70 ✗ if (!parent_widget)
71 {
72 ✗ parent_widget = GATE_UI_MOTIF_GET_CTRL_WIDGET(parent);
73 }
74 ✗ args_count = 0;
75 ✗ XtSetArg(args[args_count], XmNscrollingPolicy, XmAPPLICATION_DEFINED); ++args_count;
76 ✗ XtSetArg(args[args_count], XmNvisualPolicy, XmVARIABLE); ++args_count;
77 ✗ XtSetArg(args[args_count], XmNscrollBarDisplayPolicy, XmSTATIC); ++args_count;
78 ✗ XtSetArg(args[args_count], XmNshadowThickness, 0); ++args_count;
79 ✗ XtSetArg(args[args_count], XmNhighlightThickness, 0); ++args_count;
80
81 ✗ w = XmCreateScrolledWindow(parent_widget, NULL, args, args_count);
82 ✗ if (!w)
83 {
84 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
85 ✗ break;
86 }
87
88 ✗ args_count = 0;
89 ✗ XtSetArg(args[args_count], XmNautomaticSelection, XmBROWSE_SELECT); ++args_count;
90 //XtSetArg(args[args_count], XmNscrollBarDisplayPolicy, XmAS_NEEDED); ++args_count;
91 ✗ XtSetArg(args[args_count], XmNselectionPolicy, XmSINGLE_SELECT); ++args_count;
92 ✗ XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
93 ✗ XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
94
95 ✗ w_list = XmCreateList(w, NULL, args, args_count);
96 ✗ if (!w_list)
97 {
98 ✗ XtDestroyWidget(w);
99 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
100 ✗ break;
101 }
102
103 ✗ ret = gate_ui_motif_ctrl_init(&lstbox->ctrl, w, userparam, NULL, parent, w_list, position, &flags, NULL);
104 ✗ GATE_BREAK_IF_FAILED(ret);
105
106 ✗ XtManageChild(w);
107 ✗ XtManageChild(w_list);
108
109 } while (0);
110
111 ✗ return ret;
112 }
113
114 ✗ gate_result_t gate_ui_listbox_insert_item(gate_ui_listbox_t* lstbox, gate_size_t const* at_index, gate_string_t const* text, void* itemparam)
115 {
116 ✗ gate_result_t ret = GATE_RESULT_FAILED;
117 ✗ Widget w = NULL;
118 ✗ XmString str = NULL;
119 gate_size_t item_count;
120 int insert_pos;
121
122 do
123 {
124 ✗ GATE_UI_MOTIF_EXTRACT_CONTAINER_OR_RETURN_ERROR(lstbox, w);
125
126 ✗ str = gate_ui_motif_create_string(text);
127 ✗ if (!str)
128 {
129 ✗ ret = GATE_RESULT_OUTOFMEMORY;
130 ✗ break;
131 }
132
133 /* insert at end */
134 ✗ insert_pos = 0;
135
136 ✗ if (at_index)
137 {
138 ✗ item_count = gate_ui_listbox_widget_get_item_count(w);
139 ✗ if (*at_index < item_count)
140 {
141 /* insert at position, counting starts at "1" */
142 ✗ insert_pos = (*at_index) + 1;
143 }
144 }
145 ✗ XmListAddItem(w, str, insert_pos);
146 ✗ ret = GATE_RESULT_OK;
147
148 } while (0);
149
150 ✗ if (str)
151 {
152 ✗ XmStringFree(str);
153 }
154
155 ✗ return ret;
156 }
157
158 ✗ gate_result_t gate_ui_listbox_remove_item(gate_ui_listbox_t* lstbox, gate_size_t index)
159 {
160 ✗ Widget w = NULL;
161 ✗ GATE_UI_MOTIF_EXTRACT_CONTAINER_OR_RETURN_ERROR(lstbox, w);
162 ✗ XmListDeletePos(w, (int)(index + 1));
163 ✗ return GATE_RESULT_OK;
164 }
165
166 ✗ gate_result_t gate_ui_listbox_remove_all_items(gate_ui_listbox_t* lstbox)
167 {
168 ✗ Widget w = NULL;
169 ✗ GATE_UI_MOTIF_EXTRACT_CONTAINER_OR_RETURN_ERROR(lstbox, w);
170 ✗ XmListDeleteAllItems(w);
171 ✗ return GATE_RESULT_OK;
172 }
173
174 ✗ gate_size_t gate_ui_listbox_get_item_count(gate_ui_listbox_t* lstbox)
175 {
176 ✗ gate_size_t ret = 0;
177 Widget w_list;
178 ✗ int list_count = 0;
179
180 do
181 {
182 ✗ if (!lstbox) break;
183 ✗ w_list = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstbox->ctrl);
184 ✗ if (!w_list) break;
185
186 ✗ ret = gate_ui_listbox_widget_get_item_count(w_list);
187 } while (0);
188
189 ✗ return 0;
190 }
191
192 ✗ void* gate_ui_listbox_get_item_param(gate_ui_listbox_t* lstbox, gate_size_t index)
193 {
194 ✗ return NULL;
195 }
196
197 ✗ gate_result_t gate_ui_listbox_find_param(gate_ui_listbox_t* lstbox, void* param, gate_size_t startIndex, gate_size_t* foundIndex)
198 {
199 ✗ return GATE_RESULT_NOTIMPLEMENTED;
200 }
201
202 ✗ gate_result_t gate_ui_listbox_get_text(gate_ui_listbox_t* lstbox, gate_size_t index, gate_string_t* text)
203 {
204 ✗ int count = 0;
205 ✗ XmStringTable tbl = NULL;
206 ✗ Widget w = NULL;
207 char const* ptr_data;
208
209 ✗ GATE_UI_MOTIF_EXTRACT_CONTAINER_OR_RETURN_ERROR(lstbox, w);
210 ✗ XtVaGetValues(w, XmNitemCount, &count, XmNitems, &tbl, NULL);
211 ✗ if (index >= (int)count)
212 {
213 ✗ return GATE_RESULT_OUTOFBOUNDS;
214 }
215
216 ✗ return gate_ui_motif_convert_string(tbl[index], text);
217 }
218
219 ✗ gate_result_t gate_ui_listbox_set_text(gate_ui_listbox_t* lstbox, gate_size_t index, gate_string_t const* text)
220 {
221 ✗ Widget w = NULL;
222 int positions[1];
223 XmString strs[1];
224 ✗ GATE_UI_MOTIF_EXTRACT_CONTAINER_OR_RETURN_ERROR(lstbox, w);
225 ✗ strs[0] = gate_ui_motif_create_string(text);
226 ✗ if (!strs[0]) return GATE_RESULT_OUTOFMEMORY;
227 ✗ positions[0] = (int)(index + 1);
228 ✗ XmListReplacePositions(w, positions, strs, 1);
229 ✗ XmStringFree(strs[0]);
230 ✗ return GATE_RESULT_OK;
231 }
232
233 ✗ gate_size_t gate_ui_listbox_get_selected_item(gate_ui_listbox_t* lstbox)
234 {
235 ✗ gate_size_t ret = GATE_UI_LISTBOX_INVALID_INDEX;
236 ✗ Widget w = NULL;
237 ✗ int count = 0;
238 ✗ int* ptr_positions = NULL;
239 do
240 {
241 ✗ if (!lstbox)
242 {
243 ✗ ret = GATE_RESULT_INVALIDARG;
244 ✗ break;
245 }
246 ✗ w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstbox->ctrl);
247 ✗ if (!w)
248 {
249 ✗ ret = GATE_RESULT_INVALIDSTATE;
250 ✗ break;
251 }
252 ✗ XtVaGetValues(w, XmNselectedPositionCount, &count, XmNselectedPositions, &ptr_positions, NULL);
253 } while (0);
254 ✗ return ret;
255 }
256
257 ✗ gate_result_t gate_ui_listbox_set_selected_item(gate_ui_listbox_t* lstbox, gate_size_t index)
258 {
259 ✗ gate_result_t ret = GATE_RESULT_FAILED;
260 Widget w;
261 ✗ GATE_UI_MOTIF_EXTRACT_CONTAINER_OR_RETURN_ERROR(lstbox, w);
262 ✗ if (index == GATE_UI_LISTBOX_INVALID_INDEX)
263 {
264 ✗ XmListDeselectAllItems(w);
265 }
266 else
267 {
268 ✗ XmListSelectPos(w, (int)(index + 1), 1);
269 }
270 ✗ return GATE_RESULT_OK;
271 }
272
273
274
275
276
277 ✗ static void motif_free_pixmap_array(gate_ui_ctrl_t* ctrl)
278 {
279 gate_ui_host_t* host;
280 ✗ Display* dpy = NULL;
281 gate_arraylist_t pixmap_array;
282 gate_size_t arrlen;
283 gate_size_t ndx;
284 Pixmap* ptr_pixmap;
285
286 ✗ GATE_DEBUG_ASSERT(ctrl != NULL);
287
288 ✗ host = GATE_UI_MOTIF_GET_CTRL_HOST(ctrl);
289 ✗ pixmap_array = (gate_arraylist_t)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(ctrl);
290 ✗ if (pixmap_array)
291 {
292 ✗ if (host)
293 {
294 ✗ dpy = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
295 }
296 ✗ arrlen = gate_arraylist_length(pixmap_array);
297 ✗ for (ndx = 0; ndx < arrlen; ++ndx)
298 {
299 ✗ ptr_pixmap = (Pixmap*)gate_arraylist_get(pixmap_array, ndx);
300 ✗ if (dpy && ptr_pixmap && (*ptr_pixmap != 0))
301 {
302 ✗ XFreePixmap(dpy, *ptr_pixmap);
303 }
304 }
305 ✗ gate_arraylist_release(pixmap_array);
306 ✗ GATE_UI_MOTIF_SET_CTRL_PRIVATE_ARG(ctrl, NULL);
307 }
308 ✗ }
309
310 ✗ static gate_result_t motif_listview_destroy(gate_ui_ctrl_t* ctrl)
311 {
312 ✗ gate_ui_listview_t* lv = (gate_ui_listview_t*)ctrl;
313 Widget w_scroll;
314 Widget w_list;
315 ✗ Cardinal col_count = 0;
316 unsigned ndx;
317 ✗ XmStringTable col_tbl = NULL;
318
319 ✗ GATE_DEBUG_ASSERT(lv != NULL);
320
321 ✗ gate_ui_listview_remove_all_items(lv);
322
323 ✗ w_scroll = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
324 ✗ w_list = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
325
326 ✗ if (w_list)
327 {
328 ✗ XtUnmanageChild(w_list);
329 ✗ XtVaGetValues(w_list, XmNdetailColumnHeadingCount, &col_count, XmNdetailColumnHeading, &col_tbl, NULL, NULL);
330 ✗ XtVaSetValues(w_list, XmNdetailColumnHeadingCount, 0, XmNdetailColumnHeading, NULL, NULL, NULL);
331 ✗ if ((col_count > 0) && (col_tbl != NULL))
332 {
333 ✗ for (ndx = 0; ndx != col_count; ++ndx)
334 {
335 ✗ if (col_tbl[ndx])
336 {
337 ✗ XmStringFree(col_tbl[ndx]);
338 ✗ col_tbl[ndx] = NULL;
339 }
340 }
341 //XtFree((char*)col_tbl);
342 }
343 ✗ XtDestroyWidget(w_list);
344 }
345 ✗ if (w_scroll)
346 {
347 ✗ XtUnmanageChild(w_scroll);
348 ✗ XtDestroyWidget(w_scroll);
349 }
350
351 ✗ motif_free_pixmap_array(ctrl);
352
353 ✗ gate_mem_clear(ctrl, sizeof(gate_ui_ctrl_t));
354 ✗ return GATE_RESULT_OK;
355 }
356
357 ✗ static gate_result_t motif_listview_get_children(gate_ui_ctrl_t* ctrl, void** ptr_to_widgetlist, gate_size_t* ptr_to_children_count)
358 {
359 ✗ Widget w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
360 ✗ WidgetList children = NULL;
361 ✗ Cardinal num_children = 0;
362
363 ✗ GATE_DEBUG_ASSERT(w != NULL);
364 ✗ XtVaGetValues(w, XmNchildren, &children, XmNnumChildren, &num_children, NULL, NULL);
365 ✗ if (ptr_to_widgetlist)
366 {
367 ✗ *ptr_to_widgetlist = children;
368 }
369 ✗ if (ptr_to_children_count)
370 {
371 ✗ *ptr_to_children_count = (gate_size_t)num_children;
372 }
373 ✗ return GATE_RESULT_OK;
374 }
375
376 static gate_ui_motif_dispatcher_t listview_dispatcher =
377 {
378 &motif_listview_destroy,
379 NULL,
380 NULL,
381 NULL,
382 NULL,
383 NULL,
384 &motif_listview_get_children
385 };
386
387 ✗ static gate_size_t motif_listview_resolve_item_widget_index(gate_ui_listview_t* lstvw, Widget item)
388 {
389 ✗ WidgetList wl = NULL;
390 ✗ gate_size_t widget_count = 0;
391 ✗ gate_result_t ret = motif_listview_get_children(&lstvw->ctrl, (void**)&wl, &widget_count);
392 ✗ gate_size_t item_index = 0;
393 gate_size_t ndx;
394 Widget w;
395
396 ✗ for (ndx = 0; ndx != widget_count; ++ndx)
397 {
398 ✗ w = wl[ndx];
399 ✗ if (!XmIsIconGadget(w))
400 {
401 ✗ continue;
402 }
403 ✗ if (w == item)
404 {
405 ✗ return item_index;
406 }
407 ✗ ++item_index;
408 }
409 ✗ return GATE_STR_NPOS;
410 }
411
412 ✗ static Widget motif_listview_get_item_widget(gate_ui_listview_t* lstvw, gate_size_t index)
413 {
414 ✗ WidgetList wl = NULL;
415 ✗ gate_size_t widget_count = 0;
416 ✗ gate_size_t item_count = 0;
417 gate_size_t ndx;
418 Widget w;
419 WidgetClass wc;
420 ✗ gate_result_t ret = motif_listview_get_children(&lstvw->ctrl, (void**)&wl, &widget_count);
421 ✗ if (GATE_SUCCEEDED(ret))
422 {
423 ✗ for (ndx = 0; ndx != widget_count; ++ndx)
424 {
425 ✗ w = wl[ndx];
426 ✗ if (!XmIsIconGadget(w))
427 {
428 ✗ continue;
429 }
430 ✗ if (index == item_count)
431 {
432 ✗ return w;
433 }
434 ✗ ++item_count;
435 }
436 }
437 ✗ return NULL;
438 }
439
440
441 ✗ static void motif_listview_selection_callback(Widget widget, XtPointer client_data, XtPointer call_data)
442 {
443 ✗ gate_ui_listview_t* lv = (gate_ui_listview_t*)client_data;
444 ✗ XmContainerSelectCallbackStruct* evt_data = (XmContainerSelectCallbackStruct*)call_data;
445 gate_size_t item_index;
446 Widget item_widget;
447 ✗ void* item_data = NULL;
448
449 ✗ if (lv && lv->on_select && evt_data && evt_data->selected_item_count > 0)
450 {
451 ✗ item_widget = evt_data->selected_items[0];
452 ✗ item_index = motif_listview_resolve_item_widget_index(lv, item_widget);
453 ✗ if (item_index != GATE_STR_NPOS)
454 {
455 ✗ XtVaGetValues(item_widget, XmNuserData, &item_data, NULL, NULL);
456 ✗ lv->on_select(&lv->ctrl, item_index, item_data);
457 }
458 }
459 ✗ }
460
461 ✗ gate_result_t gate_ui_listview_create(gate_ui_listview_t* lstvw, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
462 gate_uint32_t flags, void* userparam)
463 {
464 ✗ gate_result_t ret = GATE_RESULT_FAILED;
465 ✗ Widget parent_widget = NULL;
466 Widget w;
467 Widget w_list;
468 ✗ Widget w_scroll1 = NULL;
469 ✗ Widget w_scroll2 = NULL;
470 Arg args[12];
471 Cardinal args_count;
472
473 do
474 {
475 ✗ if (!lstvw || !parent)
476 {
477 ✗ ret = GATE_RESULT_INVALIDARG;
478 ✗ break;
479 }
480
481 ✗ parent_widget = GATE_UI_MOTIF_GET_CTRL_CONTAINER(parent);
482 ✗ if (!parent_widget)
483 {
484 ✗ parent_widget = GATE_UI_MOTIF_GET_CTRL_WIDGET(parent);
485 }
486 ✗ args_count = 0;
487 ✗ XtSetArg(args[args_count], XmNscrollingPolicy, XmAUTOMATIC); ++args_count;
488 ✗ XtSetArg(args[args_count], XmNvisualPolicy, XmVARIABLE); ++args_count;
489 //XtSetArg(args[args_count], XmNscrollBarDisplayPolicy, XmSTATIC); ++args_count;
490 ✗ XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
491 ✗ XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
492
493 ✗ w = XmCreateScrolledWindow(parent_widget, NULL, args, args_count);
494 ✗ if (!w)
495 {
496 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
497 ✗ break;
498 }
499
500 ✗ XtVaGetValues(w, XmNhorizontalScrollBar, &w_scroll1, XmNverticalScrollBar, &w_scroll2, NULL);
501 ✗ if (w_scroll1)
502 {
503 ✗ XtVaSetValues(w_scroll1, XmNshadowThickness, 1, NULL);
504 }
505 ✗ if (w_scroll2)
506 {
507 ✗ XtVaSetValues(w_scroll2, XmNshadowThickness, 1, NULL);
508 }
509
510 ✗ args_count = 0;
511 ✗ XtSetArg(args[args_count], XmNlayoutType, XmDETAIL); ++args_count;
512 ✗ XtSetArg(args[args_count], XmNautomaticSelection, XmAUTO_SELECT); ++args_count;
513 ✗ XtSetArg(args[args_count], XmNselectionPolicy, XmSINGLE_SELECT); ++args_count;
514 ✗ XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
515
516 ✗ w_list = XmCreateContainer(w, NULL, args, args_count);
517 ✗ if (!w_list)
518 {
519 ✗ XtDestroyWidget(w);
520 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
521 ✗ break;
522 }
523
524 ✗ ret = gate_ui_motif_ctrl_init(&lstvw->ctrl, w, userparam, NULL, parent, w_list, position, &flags, &listview_dispatcher);
525 ✗ GATE_BREAK_IF_FAILED(ret);
526
527 ✗ XtManageChild(w);
528 ✗ XtManageChild(w_list);
529
530 ✗ XtAddCallback(w_list, XmNselectionCallback, &motif_listview_selection_callback, lstvw);
531 } while (0);
532
533 ✗ return ret;
534 }
535
536 ✗ gate_result_t gate_ui_listview_set_columns(gate_ui_listview_t* lstvw, gate_ui_listview_column_t const* columns, gate_size_t column_count)
537 {
538 Widget w;
539 gate_size_t ndx;
540 ✗ Cardinal col_count = (Cardinal)column_count;
541 ✗ XmStringTable col_headers = (XmStringTable)XtMalloc(column_count * sizeof(XmString));
542
543 ✗ if (!col_headers)
544 {
545 ✗ return GATE_RESULT_OUTOFMEMORY;
546 }
547
548 ✗ for (ndx = 0; ndx != column_count; ++ndx)
549 {
550 ✗ col_headers[ndx] = gate_ui_motif_create_string(&columns[ndx].title);
551 }
552
553 ✗ w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
554 ✗ XtVaSetValues(w,
555 XmNdetailColumnHeadingCount, col_count,
556 XmNdetailColumnHeading, col_headers,
557 NULL, NULL);
558 ✗ return GATE_RESULT_OK;
559 }
560
561 ✗ gate_size_t gate_ui_listview_get_column_count(gate_ui_listview_t* lstvw)
562 {
563 Widget w;
564 ✗ Cardinal col_count = 0;
565
566 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
567
568 ✗ w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
569 ✗ XtVaGetValues(w, XmNdetailColumnHeadingCount, &col_count, NULL, NULL);
570 ✗ return col_count;
571 }
572
573 ✗ gate_result_t gate_ui_listview_get_column(gate_ui_listview_t* lstvw, gate_size_t index, gate_string_t* text, gate_uint32_t* width)
574 {
575 ✗ XmStringTable tbl = NULL;
576 ✗ Widget w = NULL;
577 ✗ Cardinal col_count = 0;
578 unsigned ndx;
579
580 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
581
582 ✗ w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
583 ✗ if (!w)
584 {
585 ✗ return GATE_RESULT_INVALIDSTATE;
586 }
587 ✗ XtVaGetValues(w, XmNdetailColumnHeadingCount, &col_count, XmNdetailColumnHeading, &tbl, NULL, NULL);
588 ✗ if ((index < col_count) && (tbl != NULL))
589 {
590 ✗ if (text)
591 {
592 ✗ gate_ui_motif_convert_string(tbl[index], text);
593 }
594 ✗ if (width)
595 {
596 ✗ *width = 0;
597 }
598 ✗ return GATE_RESULT_OK;
599 }
600 ✗ return GATE_RESULT_OUTOFBOUNDS;
601 }
602
603 ✗ gate_result_t gate_ui_listview_add_icon(gate_ui_listview_t* lstvw, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
604 {
605 ✗ return GATE_RESULT_NOTIMPLEMENTED;
606 }
607
608 ✗ static Pixmap create_mask_pixmap(gate_ui_host_t* host, gate_rasterimage_t const* image)
609 {
610 ✗ Display* dpy = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
611 ✗ Window win = XDefaultRootWindow(dpy);
612 Pixmap pm;
613 GC gc;
614 gate_color_t col;
615 unsigned int x, y, width, height;
616
617 ✗ width = gate_rasterimage_width(image);
618 ✗ height = gate_rasterimage_height(image);
619
620 ✗ pm = XCreatePixmap(dpy, win, image->width, image->height, 1);
621 ✗ gc = XCreateGC(dpy, pm, 0, NULL);
622 ✗ XSetForeground(dpy, gc, 0);
623 ✗ XFillRectangle(dpy, pm, gc, 0, 0, width, height);
624 ✗ XSetForeground(dpy, gc, 1);
625 ✗ for (y = 0; y != height; ++y)
626 {
627 ✗ for (x = 0; x != width; ++x)
628 {
629 ✗ gate_rasterimage_get_pixel(image, x, y, &col);
630 ✗ if (col.a > 127)
631 {
632 ✗ XDrawPoint(dpy, pm, gc, x, y);
633 }
634 }
635 }
636 ✗ XFreeGC(dpy, gc);
637 ✗ return pm;
638 }
639
640 ✗ static gate_result_t motif_ctrl_add_pixmap_image(gate_ui_ctrl_t* ctrl, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
641 {
642 ✗ gate_arraylist_t pixmap_array = NULL;
643 gate_result_t ret;
644 gate_ui_graphics_t graph;
645 ✗ gate_ui_host_t* host = NULL;
646 Pixmap pm;
647 gate_size_t len;
648
649 ✗ GATE_DEBUG_ASSERT(ctrl != NULL);
650
651 do
652 {
653 ✗ host = GATE_UI_MOTIF_GET_CTRL_HOST(ctrl);
654 ✗ pixmap_array = (gate_arraylist_t)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(ctrl);
655 ✗ if (pixmap_array == NULL)
656 {
657 ✗ pixmap_array = gate_arraylist_create(sizeof(Pixmap), NULL, 16, NULL, NULL);
658 ✗ if (NULL == pixmap_array)
659 {
660 ✗ GATE_DEBUG_TRACE("Failed to allocate pixmap array");
661 ✗ ret = GATE_RESULT_OUTOFMEMORY;
662 ✗ break;
663 }
664 ✗ GATE_UI_MOTIF_SET_CTRL_PRIVATE_ARG(ctrl, pixmap_array);
665 }
666
667 ✗ pm = create_mask_pixmap(host, image);
668 ✗ gate_arraylist_add(pixmap_array, &pm);
669
670 ✗ ret = gate_ui_graphics_create_image_from(&graph, host, image);
671 ✗ GATE_BREAK_IF_FAILED(ret);
672
673 ✗ pm = (Pixmap)graph.resources[1];
674 ✗ graph.resources[1] = 0;
675 ✗ gate_ui_graphics_destroy(&graph);
676
677 ✗ gate_arraylist_add(pixmap_array, &pm);
678 ✗ len = gate_arraylist_length(pixmap_array);
679 ✗ if (icon_key)
680 {
681 ✗ *icon_key = (gate_intptr_t)len;
682 }
683 ✗ ret = GATE_RESULT_OK;
684 } while (0);
685
686 ✗ return ret;
687 }
688
689 ✗ static gate_result_t motif_ctrl_get_pixmap_image(gate_ui_ctrl_t* ctrl, gate_intptr_t icon_key, Pixmap* ptr_pm_image, Pixmap* ptr_pm_mask)
690 {
691 ✗ Pixmap ret = 0;
692 ✗ gate_arraylist_t pixmap_array = NULL;
693 ✗ Pixmap* ptr_pixmap = NULL;
694
695 ✗ if (icon_key == GATE_UI_LISTVIEW_INVALID_ICON)
696 {
697 ✗ return GATE_RESULT_NOTAVAILABLE;
698 }
699
700 ✗ pixmap_array = (gate_arraylist_t)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(ctrl);
701 ✗ if (!pixmap_array)
702 {
703 ✗ return GATE_RESULT_NOTAVAILABLE;
704 }
705
706 /* retrieve image pixmap */
707 ✗ if (ptr_pm_image)
708 {
709 ✗ ptr_pixmap = (Pixmap*)gate_arraylist_get(pixmap_array, icon_key - 1);
710 ✗ if (!ptr_pixmap)
711 {
712 ✗ return GATE_RESULT_NOTAVAILABLE;
713 }
714 ✗ *ptr_pm_image = *ptr_pixmap;
715 }
716
717 /* retrieve mask image */
718 ✗ if (ptr_pm_mask)
719 {
720 ✗ ptr_pixmap = (Pixmap*)gate_arraylist_get(pixmap_array, icon_key - 2);
721 ✗ *ptr_pm_mask = ptr_pixmap ? *ptr_pixmap : 0;
722 }
723
724 ✗ return GATE_RESULT_OK;
725 }
726
727
728 ✗ gate_result_t gate_ui_listview_add_icon_image(gate_ui_listview_t* lstvw, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
729 {
730 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
731 ✗ return motif_ctrl_add_pixmap_image(&lstvw->ctrl, image, icon_key);
732 }
733
734 ✗ gate_result_t gate_ui_listview_insert_item(gate_ui_listview_t* lstvw, gate_size_t const* atIndex, gate_string_t const* text,
735 gate_intptr_t icon_key, void* itemparam)
736 {
737 Widget w_lstvw;
738 Widget new_widget;
739 ✗ Arg args[12] = GATE_INIT_EMPTY;
740 ✗ Cardinal arg_count = 0;
741 ✗ XmString main_text = NULL;
742 XmStringTable text_items;
743 gate_size_t ndx;
744 Cardinal col_count;
745 Pixmap pm_image;
746 Pixmap pm_mask;
747 gate_result_t result;
748
749 ✗ if (!lstvw)
750 {
751 ✗ return GATE_RESULT_INVALIDSTATE;
752 }
753 ✗ w_lstvw = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
754 ✗ if (!w_lstvw)
755 {
756 ✗ return GATE_RESULT_INVALIDSTATE;
757 }
758
759 ✗ col_count = (Cardinal)gate_ui_listview_get_column_count(lstvw);
760 ✗ if (col_count > 0)
761 {
762 ✗ main_text = gate_ui_motif_create_string(text);
763 ✗ --col_count;
764 }
765 ✗ if (col_count > 0)
766 {
767 ✗ text_items = (XmStringTable)XtMalloc(col_count * sizeof(XmString));
768 ✗ if (!text_items)
769 {
770 ✗ return GATE_RESULT_OUTOFMEMORY;
771 }
772 }
773 else
774 {
775 ✗ text_items = NULL;
776 }
777
778 ✗ for (ndx = 0; ndx < col_count; ++ndx)
779 {
780 ✗ text_items[ndx] = NULL;
781 }
782
783 ✗ XtSetArg(args[arg_count], XmNviewType, XmSMALL_ICON); ++arg_count;
784 ✗ XtSetArg(args[arg_count], XmNshadowThickness, 0); ++arg_count;
785 ✗ XtSetArg(args[arg_count], XmNlabelString, main_text); ++arg_count;
786 ✗ XtSetArg(args[arg_count], XmNdetail, text_items); ++arg_count;
787 ✗ XtSetArg(args[arg_count], XmNdetailCount, col_count); ++arg_count;
788 ✗ XtSetArg(args[arg_count], XmNuserData, itemparam); ++arg_count;
789
790 ✗ result = motif_ctrl_get_pixmap_image(&lstvw->ctrl, icon_key, &pm_image, &pm_mask);
791 ✗ if (GATE_SUCCEEDED(result))
792 {
793 ✗ if (pm_image)
794 {
795 ✗ XtSetArg(args[arg_count], XmNsmallIconPixmap, pm_image);
796 ✗ ++arg_count;
797 }
798 ✗ if (pm_mask)
799 {
800 ✗ XtSetArg(args[arg_count], XmNsmallIconMask, pm_mask);
801 ✗ ++arg_count;
802 }
803 }
804
805 ✗ new_widget = XmCreateIconGadget(w_lstvw, NULL, args, arg_count);
806
807 ✗ if (!new_widget)
808 {
809 ✗ return GATE_RESULT_FAILED;
810 }
811 ✗ XtManageChild(new_widget);
812
813 ✗ if (text_items)
814 {
815 ✗ XtFree((char*)text_items);
816 }
817 ✗ if (main_text)
818 {
819 ✗ XmStringFree(main_text);
820 }
821
822 ✗ return GATE_RESULT_OK;
823 }
824
825 ✗ gate_result_t gate_ui_listview_remove_item(gate_ui_listview_t* lstvw, gate_size_t index)
826 {
827 Widget w;
828 ✗ XmString text = NULL;
829 ✗ Cardinal detail_count = 0;
830 ✗ XmStringTable detail_tbl = NULL;
831 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
832 ✗ w = motif_listview_get_item_widget(lstvw, index);
833 ✗ if (w == NULL)
834 {
835 ✗ return GATE_RESULT_NOTAVAILABLE;
836 }
837 ✗ XtVaGetValues(w, XmNlabelString, &text, NULL, NULL);
838 ✗ XtVaSetValues(w, XmNlabelString, NULL, NULL, NULL);
839
840 ✗ if (text)
841 {
842 ✗ XmStringFree(text);
843 }
844
845 ✗ XtUnmanageChild(w);
846 ✗ XtDestroyWidget(w);
847 ✗ return GATE_RESULT_OK;
848 }
849
850 ✗ gate_result_t gate_ui_listview_remove_all_items(gate_ui_listview_t* lstvw)
851 {
852 Widget w_list;
853 ✗ gate_size_t count = 0;
854 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
855
856 ✗ count = gate_ui_listview_get_item_count(lstvw);
857 ✗ while (count-- > 0)
858 {
859 ✗ gate_ui_listview_remove_item(lstvw, count);
860 }
861 ✗ return GATE_RESULT_OK;
862 }
863
864 ✗ gate_size_t gate_ui_listview_get_item_count(gate_ui_listview_t* lstvw)
865 {
866 ✗ WidgetList wl = NULL;
867 ✗ gate_size_t widget_count = 0;
868 ✗ gate_size_t item_count = 0;
869 gate_size_t ndx;
870 Widget w;
871 WidgetClass wc;
872 gate_result_t ret;
873
874 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
875 ✗ ret = gate_ui_motif_ctrl_get_children(&lstvw->ctrl, (void**)&wl, &widget_count);
876 ✗ if (GATE_SUCCEEDED(ret))
877 {
878 ✗ for (ndx = 0; ndx != widget_count; ++ndx)
879 {
880 ✗ w = wl[ndx];
881 ✗ if (!XmIsIconGadget(w))
882 {
883 ✗ continue;
884 }
885 ✗ ++item_count;
886 }
887 }
888 ✗ return item_count;
889 }
890
891 ✗ void* gate_ui_listview_get_item_param(gate_ui_listview_t* lstvw, gate_size_t index)
892 {
893 ✗ void* data = NULL;
894 Widget w;
895
896 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
897 ✗ w = motif_listview_get_item_widget(lstvw, index);
898 ✗ if (w != NULL)
899 {
900 ✗ XtVaGetValues(w, XmNuserData, &data, NULL, NULL);
901 }
902 ✗ return data;
903 }
904
905 ✗ gate_result_t gate_ui_listview_find_param(gate_ui_listview_t* lstvw, void* param, gate_size_t startIndex, gate_size_t* foundIndex)
906 {
907 ✗ WidgetList wl = NULL;
908 ✗ gate_size_t widget_count = 0;
909 ✗ gate_size_t item_count = 0;
910 gate_size_t ndx;
911 Widget w;
912 WidgetClass wc;
913 ✗ void* data = NULL;
914 gate_result_t ret;
915
916 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
917 ✗ ret = motif_listview_get_children(&lstvw->ctrl, (void**)&wl, &widget_count);
918 ✗ if (GATE_SUCCEEDED(ret))
919 {
920 ✗ for (ndx = 0; ndx != widget_count; ++ndx)
921 {
922 ✗ w = wl[ndx];
923 ✗ if (!XmIsIconGadget(w))
924 {
925 ✗ continue;
926 }
927 ✗ if (item_count >= startIndex)
928 {
929 ✗ XtVaGetValues(w, XmNuserData, &data, NULL, NULL);
930 ✗ if (data == param)
931 {
932 ✗ if (foundIndex)
933 {
934 ✗ *foundIndex = ndx;
935 }
936 ✗ return GATE_RESULT_OK;
937 }
938 }
939 ✗ ++item_count;
940 }
941 }
942 ✗ return GATE_RESULT_NOMATCH;
943 }
944
945 ✗ gate_result_t gate_ui_listview_get_text(gate_ui_listview_t* lstvw, gate_size_t index, gate_size_t subindex, gate_string_t* text)
946 {
947 Widget w;
948 ✗ XmString xmstr = NULL;
949 ✗ XmStringTable strtbl = NULL;
950 ✗ Cardinal strcnt = 0;
951
952 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
953 ✗ w = motif_listview_get_item_widget(lstvw, index);
954 ✗ if (!w)
955 {
956 ✗ return GATE_RESULT_OUTOFBOUNDS;
957 }
958 ✗ if (index == 0)
959 {
960 ✗ XtVaGetValues(w, XmNlabelString, &xmstr, NULL, NULL);
961 ✗ if (text)
962 {
963 ✗ return gate_ui_motif_convert_string(xmstr, text);
964 }
965 }
966 else
967 {
968 ✗ XtVaGetValues(w, XmNdetailCount, &strcnt, XmNdetail, &strtbl, NULL, NULL);
969 ✗ if (index >= strcnt)
970 {
971 ✗ return GATE_RESULT_OUTOFBOUNDS;
972 }
973 ✗ if (text)
974 {
975 ✗ return gate_ui_motif_convert_string(strtbl[index], text);
976 }
977 }
978 ✗ return GATE_RESULT_OK;
979 }
980
981 ✗ gate_result_t gate_ui_listview_set_text(gate_ui_listview_t* lstvw, gate_size_t index, gate_size_t subindex, gate_string_t const* text)
982 {
983 Widget w_lstvw;
984 Widget new_widget;
985 Widget item_widget;
986 ✗ XmStringTable text_items = NULL;
987 ✗ XmString xmstr = NULL;
988 ✗ XmString oldstr = NULL;
989 gate_size_t ndx;
990 Cardinal col_count;
991 ✗ Cardinal text_items_count = 0;
992
993 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
994
995 ✗ w_lstvw = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
996 ✗ if (!w_lstvw)
997 {
998 ✗ return GATE_RESULT_INVALIDSTATE;
999 }
1000
1001 ✗ item_widget = motif_listview_get_item_widget(lstvw, index);
1002 ✗ if (!item_widget)
1003 {
1004 ✗ return GATE_RESULT_NOMATCH;
1005 }
1006
1007 ✗ col_count = (Cardinal)gate_ui_listview_get_column_count(lstvw);
1008
1009 ✗ xmstr = gate_ui_motif_create_string(text);
1010 ✗ if (subindex == 0)
1011 {
1012 ✗ XtVaGetValues(item_widget, XmNlabelString, &oldstr, NULL, NULL);
1013 ✗ XtVaSetValues(item_widget, XmNlabelString, xmstr, NULL, NULL);
1014 }
1015 ✗ else if (subindex < col_count)
1016 {
1017 ✗ XtVaGetValues(item_widget, XmNdetailCount, &text_items_count, XmNdetail, &text_items, NULL, NULL);
1018 ✗ if (text_items && (subindex - 1 < text_items_count))
1019 {
1020 ✗ oldstr = text_items[subindex - 1];
1021 ✗ text_items[subindex - 1] = xmstr;
1022 }
1023 }
1024 ✗ if (oldstr)
1025 {
1026 ✗ XmStringFree(oldstr);
1027 }
1028 ✗ return GATE_RESULT_OK;
1029 }
1030
1031 ✗ gate_bool_t gate_ui_listview_is_checked(gate_ui_listview_t* lstvw, gate_size_t index)
1032 {
1033 ✗ return false;
1034 }
1035
1036 ✗ gate_result_t gate_ui_listview_set_checked(gate_ui_listview_t* lstvw, gate_size_t index, gate_bool_t checked)
1037 {
1038 ✗ return GATE_RESULT_NOTIMPLEMENTED;
1039 }
1040
1041 ✗ gate_result_t gate_ui_listview_get_checked_items(gate_ui_listview_t* lstvw, gate_array_t* indexarray)
1042 {
1043 ✗ return GATE_RESULT_NOTIMPLEMENTED;
1044 }
1045
1046 ✗ gate_bool_t gate_ui_listview_is_selected(gate_ui_listview_t* lstvw, gate_size_t index)
1047 {
1048 Widget w_lstvw;
1049 Widget w_item;
1050 ✗ Cardinal selcnt = 0;
1051 ✗ WidgetList selitems = NULL;
1052 unsigned ndx;
1053
1054 ✗ w_item = motif_listview_get_item_widget(lstvw, index);
1055 ✗ if (!w_item)
1056 {
1057 ✗ return false;
1058 }
1059
1060 ✗ w_lstvw = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
1061 ✗ if (!w_lstvw)
1062 {
1063 ✗ return false;
1064 }
1065
1066 ✗ XtVaGetValues(w_lstvw, XmNselectedObjectCount, &selcnt, XmNselectedObjects, &selitems, NULL, NULL);
1067 ✗ if ((selitems == NULL) || (selcnt == 0))
1068 {
1069 ✗ return false;
1070 }
1071 ✗ for (ndx = 0; ndx != selcnt; ++ndx)
1072 {
1073 ✗ if (selitems[ndx] == w_item)
1074 {
1075 ✗ return true;
1076 }
1077 }
1078 ✗ return false;
1079 }
1080
1081 ✗ gate_result_t gate_ui_listview_get_selected_item(gate_ui_listview_t* lstvw, gate_size_t* index)
1082 {
1083 Widget w_lstvw;
1084 ✗ Cardinal selcnt = 0;
1085 ✗ WidgetList selitems = NULL;
1086
1087 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
1088
1089 ✗ w_lstvw = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
1090 ✗ if (!w_lstvw)
1091 {
1092 ✗ return GATE_RESULT_INVALIDSTATE;
1093 }
1094
1095 ✗ XtVaGetValues(w_lstvw, XmNselectedObjectCount, &selcnt, XmNselectedObjects, &selitems, NULL, NULL);
1096 ✗ if ((selcnt == 0) || (selitems == NULL))
1097 {
1098 ✗ return GATE_RESULT_NOTAVAILABLE;
1099 }
1100
1101 ✗ if (index)
1102 {
1103 ✗ *index = motif_listview_resolve_item_widget_index(lstvw, selitems[0]);
1104 }
1105 ✗ return GATE_RESULT_OK;
1106 }
1107
1108 ✗ gate_result_t gate_ui_listview_get_selected_items(gate_ui_listview_t* lstvw, gate_array_t* indexarray)
1109 {
1110 Widget w_lstvw;
1111 ✗ Cardinal selcnt = 0;
1112 Cardinal ndx;
1113 ✗ WidgetList selitems = NULL;
1114 ✗ gate_arraylist_t arr = NULL;
1115 gate_size_t itemndx;
1116
1117 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
1118
1119 ✗ w_lstvw = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
1120 ✗ if (!w_lstvw)
1121 {
1122 ✗ return GATE_RESULT_INVALIDSTATE;
1123 }
1124
1125 ✗ XtVaGetValues(w_lstvw, XmNselectedObjectCount, &selcnt, XmNselectedObjects, &selitems, NULL, NULL);
1126 ✗ if ((selcnt == 0) || (selitems == NULL))
1127 {
1128 ✗ return GATE_RESULT_NOTAVAILABLE;
1129 }
1130
1131 ✗ arr = gate_arraylist_create(sizeof(gate_size_t), NULL, selcnt, NULL, NULL);
1132 ✗ if (arr == NULL)
1133 {
1134 ✗ return GATE_RESULT_OUTOFMEMORY;
1135 }
1136
1137 ✗ for (ndx = 0; ndx != selcnt; ++ndx)
1138 {
1139 ✗ itemndx = motif_listview_resolve_item_widget_index(lstvw, selitems[ndx]);
1140 ✗ if (itemndx != GATE_STR_NPOS)
1141 {
1142 ✗ gate_arraylist_add(arr, &itemndx);
1143 }
1144 }
1145
1146 ✗ if (indexarray)
1147 {
1148 ✗ gate_array_create(indexarray, arr);
1149
1150 }
1151
1152 ✗ gate_arraylist_release(arr);
1153 ✗ return GATE_RESULT_OK;
1154 }
1155
1156 ✗ gate_result_t gate_ui_listview_select_item(gate_ui_listview_t* lstvw, gate_size_t index, gate_bool_t selected)
1157 {
1158 Widget w_lstvw;
1159 Widget w_item;
1160 Widget sel_widgets[1];
1161
1162 ✗ GATE_DEBUG_ASSERT(lstvw != NULL);
1163
1164 ✗ w_lstvw = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&lstvw->ctrl);
1165 ✗ if (!w_lstvw)
1166 {
1167 ✗ return GATE_RESULT_INVALIDSTATE;
1168 }
1169
1170 ✗ w_item = motif_listview_get_item_widget(lstvw, index);
1171 ✗ if (w_item == NULL)
1172 {
1173 ✗ return GATE_RESULT_OUTOFBOUNDS;
1174 }
1175
1176 ✗ if (selected)
1177 {
1178 ✗ sel_widgets[0] = w_item;
1179 ✗ XtVaSetValues(w_lstvw, XmNselectedObjects, &sel_widgets[0], XmNselectedObjectCount, 1, NULL, NULL);
1180 }
1181 else
1182 {
1183 ✗ XtVaSetValues(w_lstvw, XmNselectedObjects, NULL, XmNselectedObjectCount, 0, NULL, NULL);
1184 }
1185
1186 ✗ return GATE_RESULT_OK;
1187 }
1188
1189
1190
1191
1192
1193 ✗ static gate_result_t motif_itemview_destroy(gate_ui_ctrl_t* ctrl)
1194 {
1195 ✗ gate_ui_itemview_t* iv = (gate_ui_itemview_t*)ctrl;
1196 Widget w_scroll;
1197 Widget w_list;
1198
1199 ✗ GATE_DEBUG_ASSERT(iv != NULL);
1200
1201 ✗ gate_ui_itemview_remove_all_items(iv);
1202
1203 ✗ w_scroll = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
1204 ✗ w_list = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
1205
1206 ✗ if (w_list)
1207 {
1208 ✗ XtUnmanageChild(w_list);
1209 ✗ XtDestroyWidget(w_list);
1210 }
1211 ✗ if (w_scroll)
1212 {
1213 ✗ XtUnmanageChild(w_scroll);
1214 ✗ XtDestroyWidget(w_scroll);
1215 }
1216
1217 ✗ motif_free_pixmap_array(ctrl);
1218
1219 ✗ gate_mem_clear(ctrl, sizeof(gate_ui_ctrl_t));
1220 ✗ return GATE_RESULT_OK;
1221 }
1222
1223
1224 static gate_ui_motif_dispatcher_t itemview_dispatcher =
1225 {
1226 &motif_itemview_destroy,
1227 NULL,
1228 NULL,
1229 NULL,
1230 NULL,
1231 NULL,
1232 NULL
1233 };
1234
1235
1236 ✗ static Widget motif_itemview_get_item_widget(gate_ui_itemview_t* itemview, gate_size_t index)
1237 {
1238 gate_result_t result;
1239 ✗ WidgetList wl = NULL;
1240 ✗ gate_size_t widget_count = 0;
1241
1242 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1243 ✗ result = gate_ui_motif_ctrl_get_children(&itemview->ctrl, (void**)&wl, &widget_count);
1244 ✗ if (GATE_FAILED(result))
1245 {
1246 ✗ return NULL;
1247 }
1248 ✗ if ((index >= widget_count) || (wl == NULL))
1249 {
1250 ✗ return NULL;
1251 }
1252 ✗ return wl[index];
1253 }
1254
1255 ✗ static gate_size_t motif_itemview_resolve_item_widget_index(gate_ui_itemview_t* itemview, Widget item_widget)
1256 {
1257 gate_result_t result;
1258 ✗ WidgetList wl = NULL;
1259 ✗ gate_size_t widget_count = 0;
1260 gate_size_t ndx;
1261
1262 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1263 ✗ result = gate_ui_motif_ctrl_get_children(&itemview->ctrl, (void**)&wl, &widget_count);
1264 ✗ if (GATE_FAILED(result))
1265 {
1266 ✗ return GATE_STR_NPOS;
1267 }
1268 ✗ for (ndx = 0; ndx != widget_count; ++ndx)
1269 {
1270 ✗ if (wl[ndx] == item_widget)
1271 {
1272 ✗ return ndx;
1273 }
1274 }
1275 ✗ return GATE_STR_NPOS;
1276 }
1277
1278
1279 ✗ static void motif_itemview_selection_callback(Widget widget, XtPointer client_data, XtPointer call_data)
1280 {
1281 ✗ gate_ui_itemview_t* iv = (gate_ui_itemview_t*)client_data;
1282 ✗ XmContainerSelectCallbackStruct* evt_data = (XmContainerSelectCallbackStruct*)call_data;
1283 gate_size_t item_index;
1284 Widget item_widget;
1285 ✗ void* item_data = NULL;
1286
1287 ✗ if (iv && iv->on_select && evt_data && evt_data->selected_item_count > 0)
1288 {
1289 ✗ item_widget = evt_data->selected_items[0];
1290 ✗ item_index = motif_itemview_resolve_item_widget_index(iv, item_widget);
1291 ✗ if (item_index != GATE_STR_NPOS)
1292 {
1293 ✗ XtVaGetValues(item_widget, XmNuserData, &item_data, NULL, NULL);
1294 ✗ iv->on_select(&iv->ctrl, item_index, item_data);
1295 }
1296 }
1297 ✗ }
1298
1299 ✗ gate_result_t gate_ui_itemview_create(gate_ui_itemview_t* itemview, gate_ui_ctrl_t* parent, gate_ui_position_t const* position,
1300 gate_uint32_t flags, void* userparam)
1301 {
1302 ✗ gate_result_t ret = GATE_RESULT_FAILED;
1303 ✗ Widget parent_widget = NULL;
1304 Widget w;
1305 Widget w_list;
1306 ✗ Widget w_scroll1 = NULL;
1307 ✗ Widget w_scroll2 = NULL;
1308 Arg args[12];
1309 Cardinal args_count;
1310
1311 do
1312 {
1313 ✗ if (!itemview || !parent)
1314 {
1315 ✗ ret = GATE_RESULT_INVALIDARG;
1316 ✗ break;
1317 }
1318
1319 ✗ parent_widget = GATE_UI_MOTIF_GET_CTRL_CONTAINER(parent);
1320 ✗ if (!parent_widget)
1321 {
1322 ✗ parent_widget = GATE_UI_MOTIF_GET_CTRL_WIDGET(parent);
1323 }
1324 ✗ args_count = 0;
1325
1326 ✗ XtSetArg(args[args_count], XmNscrollingPolicy, XmAUTOMATIC); ++args_count;
1327 ✗ XtSetArg(args[args_count], XmNvisualPolicy, XmVARIABLE); ++args_count;
1328 ✗ XtSetArg(args[args_count], XmNscrollBarDisplayPolicy, XmSTATIC); ++args_count;
1329 ✗ XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
1330 ✗ XtSetArg(args[args_count], XmNhighlightThickness, 1); ++args_count;
1331
1332 ✗ w = XmCreateScrolledWindow(parent_widget, NULL, args, args_count);
1333 ✗ if (!w)
1334 {
1335 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
1336 ✗ break;
1337 }
1338
1339 ✗ XtVaGetValues(w, XmNhorizontalScrollBar, &w_scroll1, XmNverticalScrollBar, &w_scroll2, NULL, NULL);
1340 ✗ if (w_scroll1 != NULL)
1341 {
1342 ✗ XtSetSensitive(w_scroll1, False);
1343 }
1344 ✗ if (w_scroll2 != NULL)
1345 {
1346 ✗ XtVaSetValues(w_scroll2, XmNshadowThickness, 1, NULL, NULL);
1347 }
1348
1349 ✗ args_count = 0;
1350 ✗ XtSetArg(args[args_count], XmNlayoutType, XmSPATIAL); ++args_count;
1351 ✗ XtSetArg(args[args_count], XmNspatialStyle, XmGRID); ++args_count;
1352 ✗ XtSetArg(args[args_count], XmNspatialResizeModel, XmGROW_MINOR); ++args_count;
1353 ✗ XtSetArg(args[args_count], XmNspatialSnapModel, XmSNAP_TO_GRID); ++args_count;
1354 ✗ XtSetArg(args[args_count], XmNspatialIncludeModel, XmFIRST_FIT); ++args_count;
1355 ✗ XtSetArg(args[args_count], XmNlayoutDirection, XmTOP_TO_BOTTOM_LEFT_TO_RIGHT); ++args_count;
1356 ✗ XtSetArg(args[args_count], XmNautomaticSelection, XmAUTO_SELECT); ++args_count;
1357 ✗ XtSetArg(args[args_count], XmNselectionPolicy, XmSINGLE_SELECT); ++args_count;
1358 ✗ XtSetArg(args[args_count], XmNlargeCellWidth, 640); ++args_count;
1359
1360 ✗ XtSetArg(args[args_count], XmNshadowThickness, 1); ++args_count;
1361
1362 ✗ w_list = XmCreateContainer(w, NULL, args, args_count);
1363 ✗ if (!w_list)
1364 {
1365 ✗ XtDestroyWidget(w);
1366 ✗ ret = GATE_RESULT_OUTOFRESOURCES;
1367 ✗ break;
1368 }
1369
1370 ✗ ret = gate_ui_motif_ctrl_init(&itemview->ctrl, w, userparam, NULL, parent, w_list, position, &flags, &itemview_dispatcher);
1371 ✗ GATE_BREAK_IF_FAILED(ret);
1372
1373 ✗ XtManageChild(w);
1374 ✗ XtManageChild(w_list);
1375
1376 ✗ XtAddCallback(w_list, XmNselectionCallback, &motif_itemview_selection_callback, itemview);
1377 } while (0);
1378
1379 ✗ return ret;
1380 }
1381
1382 ✗ gate_result_t gate_ui_itemview_add_icon(gate_ui_itemview_t* itemview, gate_ui_icon_t const* icon, gate_intptr_t* icon_key)
1383 {
1384 ✗ return GATE_RESULT_NOTIMPLEMENTED;
1385 }
1386
1387 ✗ gate_result_t gate_ui_itemview_add_icon_image(gate_ui_itemview_t* itemview, gate_rasterimage_t const* image, gate_intptr_t* icon_key)
1388 {
1389 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1390 ✗ return motif_ctrl_add_pixmap_image(&itemview->ctrl, image, icon_key);
1391 }
1392
1393 ✗ static XmString motif_itemview_create_label(gate_string_t const* title, gate_string_t const* subtitle, gate_string_t const* additionals)
1394 {
1395 gate_strbuilder_t sb;
1396 ✗ gate_string_t tmp_text = GATE_STRING_INIT_EMPTY;
1397 XmString ret;
1398
1399 ✗ gate_strbuilder_create(&sb, 32);
1400 ✗ gate_strbuilder_append_string(&sb, title);
1401 ✗ gate_strbuilder_append_cstr(&sb, "\n");
1402 ✗ gate_strbuilder_append_string(&sb, subtitle);
1403 ✗ gate_strbuilder_append_cstr(&sb, "\n");
1404 ✗ gate_strbuilder_append_string(&sb, additionals);
1405
1406 ✗ gate_strbuilder_to_string(&sb, &tmp_text);
1407 ✗ ret = gate_ui_motif_create_string(&tmp_text);
1408 ✗ gate_strbuilder_release(&sb);
1409 ✗ return ret;
1410 }
1411
1412 ✗ gate_result_t gate_ui_itemview_insert(gate_ui_itemview_t* itemview, gate_size_t const* atIndex, gate_string_t const* title,
1413 gate_string_t const* subtitle, gate_string_t const* additionals, gate_intptr_t icon_key, void* itemparam)
1414 {
1415 Widget w_view;
1416 Widget new_widget;
1417 ✗ Arg args[16] = GATE_INIT_EMPTY;
1418 ✗ Cardinal arg_count = 0;
1419 ✗ XmString main_text = NULL;
1420 gate_size_t ndx;
1421 Cardinal col_count;
1422 Pixmap pm_image;
1423 Pixmap pm_mask;
1424 gate_result_t result;
1425
1426 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1427
1428 ✗ w_view = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&itemview->ctrl);
1429 ✗ if (!w_view)
1430 {
1431 ✗ return GATE_RESULT_INVALIDSTATE;
1432 }
1433
1434 ✗ main_text = motif_itemview_create_label(title, subtitle, additionals);
1435
1436 ✗ XtSetArg(args[arg_count], XmNviewType, XmSMALL_ICON); ++arg_count;
1437 ✗ XtSetArg(args[arg_count], XmNshadowThickness, 0); ++arg_count;
1438 ✗ XtSetArg(args[arg_count], XmNlabelString, main_text); ++arg_count;
1439 ✗ XtSetArg(args[arg_count], XmNuserData, itemparam); ++arg_count;
1440
1441 ✗ result = motif_ctrl_get_pixmap_image(&itemview->ctrl, icon_key, &pm_image, &pm_mask);
1442 ✗ if (GATE_SUCCEEDED(result))
1443 {
1444 ✗ if (pm_image)
1445 {
1446 ✗ XtSetArg(args[arg_count], XmNsmallIconPixmap, pm_image);
1447 ✗ ++arg_count;
1448 }
1449 ✗ if (pm_mask)
1450 {
1451 ✗ XtSetArg(args[arg_count], XmNsmallIconMask, pm_mask);
1452 ✗ ++arg_count;
1453 }
1454 }
1455
1456 ✗ new_widget = XmCreateIconGadget(w_view, NULL, args, arg_count);
1457
1458 ✗ if (!new_widget)
1459 {
1460 ✗ return GATE_RESULT_FAILED;
1461 }
1462 ✗ XtManageChild(new_widget);
1463
1464 ✗ if (main_text)
1465 {
1466 ✗ XmStringFree(main_text);
1467 }
1468
1469 ✗ return GATE_RESULT_OK;
1470 }
1471
1472
1473
1474 ✗ gate_result_t gate_ui_itemview_remove(gate_ui_itemview_t* itemview, gate_size_t index)
1475 {
1476 ✗ Widget w = motif_itemview_get_item_widget(itemview, index);
1477 ✗ if (w == NULL)
1478 {
1479 ✗ return GATE_RESULT_NOTAVAILABLE;
1480 }
1481 else
1482 {
1483 ✗ XtDestroyWidget(w);
1484 ✗ return GATE_RESULT_OK;
1485 }
1486 }
1487
1488 ✗ gate_result_t gate_ui_itemview_remove_all_items(gate_ui_itemview_t* itemview)
1489 {
1490 ✗ Widget w_list = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&itemview->ctrl);
1491 ✗ gate_ui_motif_widget_destroy_children(w_list, false);
1492 ✗ return GATE_RESULT_OK;
1493 }
1494
1495 ✗ gate_size_t gate_ui_itemview_get_count(gate_ui_itemview_t* itemview)
1496 {
1497 ✗ WidgetList wl = NULL;
1498 ✗ gate_size_t widget_count = 0;
1499 gate_result_t ret;
1500
1501 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1502 ✗ ret = gate_ui_motif_ctrl_get_children(&itemview->ctrl, (void**)&wl, &widget_count);
1503 ✗ if (GATE_FAILED(ret))
1504 {
1505 ✗ return 0;
1506 }
1507 else
1508 {
1509 ✗ return widget_count;
1510 }
1511 }
1512
1513 ✗ void* gate_ui_itemview_get_item_param(gate_ui_itemview_t* itemview, gate_size_t index)
1514 {
1515 Widget w;
1516 ✗ void* ret = NULL;
1517
1518 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1519
1520 ✗ w = motif_itemview_get_item_widget(itemview, index);
1521 ✗ if (w)
1522 {
1523 ✗ XtVaGetValues(w, XmNuserData, &ret, NULL, NULL);
1524 }
1525 ✗ return ret;
1526 }
1527
1528 ✗ gate_result_t gate_ui_itemview_find_param(gate_ui_itemview_t* itemview, void* find_param, gate_size_t startIndex, gate_size_t* foundIndex)
1529 {
1530 ✗ WidgetList wl = NULL;
1531 Widget w;
1532 ✗ gate_size_t widget_count = 0;
1533 gate_size_t ndx;
1534 gate_result_t ret;
1535 void* item_param;
1536
1537 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1538 do
1539 {
1540 ✗ ret = gate_ui_motif_ctrl_get_children(&itemview->ctrl, (void**)&wl, &widget_count);
1541 ✗ GATE_BREAK_IF_FAILED(ret);
1542
1543 ✗ ret = GATE_RESULT_NOMATCH;
1544 ✗ for (ndx = startIndex; ndx < widget_count; ++ndx)
1545 {
1546 ✗ w = wl[ndx];
1547 ✗ if (!w)
1548 {
1549 ✗ continue;
1550 }
1551 ✗ item_param = NULL;
1552 ✗ XtVaGetValues(w, XmNuserData, &item_param, NULL, NULL);
1553 ✗ if (item_param == find_param)
1554 {
1555 ✗ if (foundIndex)
1556 {
1557 ✗ *foundIndex = ndx;
1558 }
1559 ✗ ret = GATE_RESULT_OK;
1560 ✗ break;
1561 }
1562 }
1563 } while (0);
1564 ✗ return ret;
1565 }
1566
1567 ✗ gate_result_t gate_ui_itemview_get_text(gate_ui_itemview_t* itemview, gate_size_t index,
1568 gate_string_t* title, gate_string_t* subtitle, gate_string_t* additionals)
1569 {
1570 Widget w_item;
1571 XmString xmstr;
1572 ✗ gate_string_t item_str = GATE_STRING_INIT_EMPTY;
1573 ✗ gate_size_t pos1 = GATE_STR_NPOS;
1574 ✗ gate_size_t pos2 = GATE_STR_NPOS;
1575
1576 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1577
1578 ✗ w_item = motif_itemview_get_item_widget(itemview, index);
1579 ✗ if (w_item == NULL)
1580 {
1581 ✗ return GATE_RESULT_OUTOFBOUNDS;
1582 }
1583
1584 ✗ XtVaGetValues(w_item, XmNlabelString, &xmstr, NULL, NULL);
1585 ✗ if (xmstr)
1586 {
1587 ✗ gate_ui_motif_convert_string(xmstr, &item_str);
1588 }
1589
1590 ✗ pos1 = gate_string_char_pos(&item_str, '\n', 0);
1591 ✗ if (pos1 != GATE_STR_NPOS)
1592 {
1593 ✗ pos2 = gate_string_char_pos(&item_str, '\n', pos1 + 1);
1594 }
1595 ✗ if (title)
1596 {
1597 ✗ gate_string_substr(title, &item_str, 0, pos1);
1598 }
1599 ✗ if (subtitle)
1600 {
1601 ✗ gate_string_substr(subtitle, &item_str, pos1 + 1, pos2 - pos1 - 1);
1602 }
1603 ✗ if (additionals)
1604 {
1605 ✗ gate_string_substr(additionals, &item_str, pos2 + 1, GATE_STR_NPOS);
1606 }
1607
1608 ✗ gate_string_release(&item_str);
1609
1610 ✗ return GATE_RESULT_OK;
1611 }
1612
1613 ✗ gate_result_t gate_ui_itemview_set_text(gate_ui_itemview_t* itemview, gate_size_t index,
1614 gate_string_t const* title, gate_string_t const* subtitle, gate_string_t const* additionals)
1615 {
1616 Widget w_item;
1617 XmString xmstr;
1618 ✗ gate_string_t old_title = GATE_STRING_INIT_EMPTY;
1619 ✗ gate_string_t old_subtitle = GATE_STRING_INIT_EMPTY;
1620 ✗ gate_string_t old_add = GATE_STRING_INIT_EMPTY;
1621
1622 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1623
1624 ✗ w_item = motif_itemview_get_item_widget(itemview, index);
1625 ✗ if (w_item == NULL)
1626 {
1627 ✗ return GATE_RESULT_OUTOFBOUNDS;
1628 }
1629
1630 ✗ if (!title || !subtitle || !additionals)
1631 {
1632 ✗ gate_ui_itemview_get_text(itemview, index, &old_title, &old_subtitle, &old_add);
1633 ✗ if (!title) title = &old_title;
1634 ✗ if (!subtitle) subtitle = &old_subtitle;
1635 ✗ if (!additionals) additionals = &old_add;
1636 }
1637
1638 ✗ xmstr = motif_itemview_create_label(title, subtitle, additionals);
1639 ✗ XtVaSetValues(w_item, XmNlabelString, xmstr, NULL, NULL);
1640
1641 ✗ gate_string_release(&old_title);
1642 ✗ gate_string_release(&old_subtitle);
1643 ✗ gate_string_release(&old_add);
1644
1645 ✗ return GATE_RESULT_OK;
1646 }
1647
1648 ✗ gate_bool_t gate_ui_itemview_is_selected(gate_ui_itemview_t* itemview, gate_size_t index)
1649 {
1650 Widget w_iv;
1651 Widget w_item;
1652 ✗ Cardinal selcnt = 0;
1653 ✗ WidgetList selitems = NULL;
1654 unsigned ndx;
1655
1656 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1657
1658 ✗ w_item = motif_itemview_get_item_widget(itemview, index);
1659 ✗ if (!w_item)
1660 {
1661 ✗ return false;
1662 }
1663
1664 ✗ w_iv = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&itemview->ctrl);
1665 ✗ if (!w_iv)
1666 {
1667 ✗ return false;
1668 }
1669
1670 ✗ XtVaGetValues(w_iv, XmNselectedObjectCount, &selcnt, XmNselectedObjects, &selitems, NULL, NULL);
1671 ✗ if ((selitems == NULL) || (selcnt == 0))
1672 {
1673 ✗ return false;
1674 }
1675 ✗ for (ndx = 0; ndx != selcnt; ++ndx)
1676 {
1677 ✗ if (selitems[ndx] == w_item)
1678 {
1679 ✗ return true;
1680 }
1681 }
1682 ✗ return false;
1683 }
1684
1685 ✗ gate_result_t gate_ui_itemview_get_selected_item(gate_ui_itemview_t* itemview, gate_size_t* index)
1686 {
1687 Widget w_iv;
1688 ✗ Cardinal selcnt = 0;
1689 ✗ WidgetList selitems = NULL;
1690
1691 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1692
1693 ✗ w_iv = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&itemview->ctrl);
1694 ✗ if (!w_iv)
1695 {
1696 ✗ return GATE_RESULT_INVALIDSTATE;
1697 }
1698
1699 ✗ XtVaGetValues(w_iv, XmNselectedObjectCount, &selcnt, XmNselectedObjects, &selitems, NULL, NULL);
1700 ✗ if ((selcnt == 0) || (selitems == NULL))
1701 {
1702 ✗ return GATE_RESULT_NOTAVAILABLE;
1703 }
1704
1705 ✗ if (index)
1706 {
1707 ✗ *index = motif_itemview_resolve_item_widget_index(itemview, selitems[0]);
1708 }
1709 ✗ return GATE_RESULT_OK;
1710 }
1711
1712 ✗ gate_result_t gate_ui_itemview_select_item(gate_ui_itemview_t* itemview, gate_size_t index)
1713 {
1714 Widget w_iv;
1715 Widget w_item;
1716 Widget sel_widgets[1];
1717
1718 ✗ GATE_DEBUG_ASSERT(itemview != NULL);
1719
1720 ✗ w_iv = GATE_UI_MOTIF_GET_CTRL_CONTAINER(&itemview->ctrl);
1721 ✗ if (!w_iv)
1722 {
1723 ✗ return GATE_RESULT_INVALIDSTATE;
1724 }
1725
1726 ✗ w_item = motif_itemview_get_item_widget(itemview, index);
1727 ✗ if (w_item == NULL)
1728 {
1729 ✗ XtVaSetValues(w_iv, XmNselectedObjects, NULL, XmNselectedObjectCount, 0, NULL, NULL);
1730 }
1731 else
1732 {
1733 ✗ sel_widgets[0] = w_item;
1734 ✗ XtVaSetValues(w_iv, XmNselectedObjects, &sel_widgets[0], XmNselectedObjectCount, 1, NULL, NULL);
1735 }
1736
1737 ✗ return GATE_RESULT_OK;
1738 }
1739
1740 #endif /* GATE_UI_MOTIF */
1741