1 /**
2 *
3 * $Id: Traversal.c,v 1.4 2009/04/29 09:45:14 paulgevers Exp $
4 *
5 * Copyright (C) 1995 Free Software Foundation, Inc.
6 * Copyright � 1995-2001, 2004, 2005 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 **/
25
26 static const char rcsid[] = "$Id: Traversal.c,v 1.4 2009/04/29 09:45:14 paulgevers Exp $";
27
28 #include <LTconfig.h>
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include <XmI/XmI.h>
35 #include <XmI/TraversalI.h>
36
37 #include <Xm/XmP.h>
38 #include <Xm/VendorS.h>
39 #include <Xm/VendorSEP.h>
40 #include <Xm/BaseClassP.h>
41 #include <Xm/GadgetP.h>
42 #include <Xm/PrimitiveP.h>
43 #include <Xm/ManagerP.h>
44 #include <Xm/ScrolledWP.h>
45 #include <Xm/DrawingAP.h>
46 #include <Xm/MenuShellP.h>
47
48 #include <XmI/DebugUtil.h>
49
50
51 #define ALLOC_INCR 8
52
53 /*
54 * forwards
55 */
56 Widget _XmTraverseAway(XmTravTree tree, Widget w, Boolean control);
57 XmNavigability _XmGetNavigability(Widget w);
58 XmNavigationType _XmGetNavigationType(Widget w);
59 Boolean _XmNewTravGraph(XmTravTree tree, Widget shell, Widget first);
60 Boolean _XmIsViewable(Widget w);
61 Widget _XmIsScrollableClipWidget(Widget w, XRectangle *rect);
62 Boolean _XmIntersectionOf(XRectangle *a, XRectangle *b, XRectangle *dest);
63 void _XmTravGraphRemove(XmTravTree tree, Widget w);
64 void _XmTravGraphAdd(XmTravTree tree, Widget w);
65 void _XmTravGraphUpdate(XmTravTree tree, Widget w);
66 Boolean _XmGetEffectiveView(Widget w, XRectangle *rect);
67 Boolean _XmSetInitialOfTabGraph(XmTravTree tree, Widget tab, Widget first);
68 void _XmTabListAdd(XmTravTree tree, Widget w);
69 void _XmTabListDelete(XmTravTree tree, Widget w);
70 Widget _XmGetClippingAncestor(Widget w, XRectangle *rect);
71 Widget _XmTraverse(XmTravTree tree, XmTraversalDirection dir, Widget w);
72
73
74 /************************** Tree Manip functions ***************************/
75
76 /*
77 * MLM: be careful defining this. This turns on _LtDebug *and* dumping of the
78 * traversal graph. If you do turn it on, NOTE that performance will really
79 * suck. You can get visual effects if you turn it on (slooooowwww exposes).
80 */
81 #define DUMP_NODES 0
82
83 #if DUMP_NODES
84 extern void
DumpNode(int which,XmTravTreeNode node)85 DumpNode(int which, XmTravTreeNode node)
86 {
87 if (node == NULL)
88 {
89 DEBUGOUT(_LtDebug0(__FILE__, NULL,
90 " Attempt to dump NULL node!\n"));
91
92 return;
93 }
94 DEBUGOUT(_LtDebug0(__FILE__, NULL,
95 " %d: addr: %p type: %d nav_type: %d tab_parent: %p\n",
96 which, node, node->type, node->nav_type,
97 node->tab_parent.link));
98
99 DEBUGOUT(_LtDebug0(__FILE__, NULL,
100 " %d: widget: %s class: %s rect: %d %d %d %d\n",
101 which, XtName(node->widget),
102 XtClass(node->widget)->core_class.class_name,
103 node->rect.x, node->rect.y,
104 node->rect.width, node->rect.height));
105
106 DEBUGOUT(_LtDebug0(__FILE__, NULL,
107 " %d: next: %p prev: %p up: %p down: %p\n",
108 which, node->next, node->prev, node->up, node->down));
109
110 DEBUGOUT(_LtDebug0(__FILE__, NULL, "\n"));
111 }
112
113
114 extern void
DumpTree(XmTravTree tree)115 DumpTree(XmTravTree tree)
116 {
117 int i;
118
119 if (tree == NULL)
120 {
121 DEBUGOUT(_LtDebug0(__FILE__, NULL,
122 "DumpTree: Tree is NULL\n"));
123 return;
124 }
125
126 DEBUGOUT(_LtDebug0(__FILE__, NULL,
127 "Tree: Widget: %s current: %p num_entries: %d\n",
128 XtName(tree->shell), tree->current, tree->num_entries));
129
130 DEBUGOUT(_LtDebug0(__FILE__, NULL,
131 " num_alloc: %d next_alloc: %d num_excls: %d\n",
132 tree->num_alloc, tree->next_alloc, tree->num_excls));
133
134 DEBUGOUT(_LtDebug0(__FILE__, NULL,
135 " num_tab_alloc: %d num_tab_entries: %d\n",
136 tree->num_tab_alloc, tree->num_tab_entries));
137
138 DEBUGOUT(_LtDebug0(__FILE__, NULL, "Exclusive/tabs\n"));
139 for (i = 0; i < tree->num_tab_entries; i++)
140 DEBUGOUT(_LtDebug0(__FILE__, NULL,
141 " %d: %s\n", i, XtName(tree->excl_tabs[i])));
142
143 DEBUGOUT(_LtDebug0(__FILE__, NULL, "Nodes:\n"));
144 for (i = 0; i < tree->num_entries; i++)
145 DumpNode(i, &tree->head[i]);
146 }
147
148
149 extern void
DumpFocusData(XmFocusData fd)150 DumpFocusData(XmFocusData fd)
151 {
152 DEBUGOUT(_LtDebug0(__FILE__, NULL,
153 "FocusData: active_tab %p focus_item %p old_focus %p\n",
154 fd->active_tab_group, fd->focus_item,
155 fd->old_focus_item));
156
157 DEBUGOUT(_LtDebug0(__FILE__, NULL,
158 " pointer_item: %p old_pointer: %p\n",
159 fd->pointer_item, fd->old_pointer_item));
160
161 DEBUGOUT(_LtDebug0(__FILE__, NULL,
162 " flush: %d focal_point: %d first_focus: %p\n",
163 fd->flush, fd->focal_point, fd->first_focus));
164
165 DEBUGOUT(_LtDebug0(__FILE__, NULL,
166 " focus_policy: %d\n", fd->focus_policy));
167
168 DumpTree(&fd->tree);
169 }
170
171 #else
172
173 /*
174 #undef DEBUGOUT
175 #define DEBUGOUT(x)
176 */
177 #define DumpNode(w,n)
178 #define DumpTree(t)
179 #define DumpFocusData(f)
180
181 #endif
182
183 static XmTravTreeNode
GetNodeOfWidget(XmTravTree tree,Widget w)184 GetNodeOfWidget(XmTravTree tree, Widget w)
185 {
186 int i;
187
188 DEBUGOUT(_LtDebug(__FILE__, w, "GetNodeOfWidget\n"));
189
190 if (!w)
191 {
192 return NULL;
193 }
194
195 for (i = 0; i < tree->num_entries; i++)
196 {
197 if (tree->head[i].widget == w)
198 {
199 return &tree->head[i];
200 }
201 }
202 return NULL;
203 }
204
205 static XmTravTreeNode
GetNodeFromGraph(XmTravTreeNode node,Widget first)206 GetNodeFromGraph(XmTravTreeNode node, Widget first)
207 {
208 XmTravTreeNode tmp;
209
210 DEBUGOUT(_LtDebug(__FILE__, first, "GetNodeFromGraph\n"));
211
212 if (!first)
213 {
214 return NULL;
215 }
216
217 if (node->up == NULL)
218 {
219 return NULL;
220 }
221
222 tmp = node->up;
223 while (1)
224 {
225 if (tmp->widget == first)
226 {
227 return tmp;
228 }
229
230 if (tmp == node->down)
231 {
232 return NULL;
233 }
234
235 tmp = tmp->next;
236
237 if (tmp == NULL)
238 {
239 return NULL;
240 }
241 }
242 }
243
244
245 static XmTravTreeNode
AllocListEntry(XmTravTree tree)246 AllocListEntry(XmTravTree tree)
247 {
248 XmTravTreeNode node;
249
250 if (tree->num_alloc == 0)
251 {
252 if (tree->next_alloc != 0)
253 {
254 tree->num_alloc = tree->next_alloc;
255 }
256 else
257 {
258 tree->num_alloc = ALLOC_INCR * 2;
259 }
260 tree->head = (XmTravTreeNode)XtCalloc(tree->num_alloc,
261 sizeof(XmTravTreeNodeRec));
262 }
263 else if (tree->num_entries == tree->num_alloc)
264 {
265 tree->num_alloc += ALLOC_INCR * 2;
266 tree->head = (XmTravTreeNode)XtRealloc((char *)tree->head,
267 sizeof(XmTravTreeNodeRec) *
268 tree->num_alloc);
269 }
270
271 node = &tree->head[tree->num_entries];
272 tree->num_entries++;
273 return node;
274 }
275
276
277 static Boolean
GetChildList(Widget w,WidgetList * children,Cardinal * nchildren)278 GetChildList(Widget w, WidgetList *children, Cardinal *nchildren)
279 {
280 XmManagerClassExt *mce;
281
282 if (XmIsManager(w))
283 {
284 mce = _XmGetManagerClassExtPtr(XtClass(w), NULLQUARK);
285
286 if (mce && *mce && (*mce)->traversal_children)
287 {
288 return ((*mce)->traversal_children) (w, children, nchildren);
289 }
290 }
291 return False;
292 }
293
294
295 static void
GetNodeList(Widget w,XRectangle * rect,XmTravTree tree,int toffset,int coffset)296 GetNodeList(Widget w, XRectangle *rect, XmTravTree tree,
297 int toffset, int coffset)
298 {
299 XmNavigability nav;
300 XmNavigationType nt;
301 XmTravTreeNode tmp;
302 int num_nodes;
303 XRectangle trect;
304 WidgetList children;
305 Cardinal nchildren, i;
306 Boolean needfree;
307
308 DEBUGOUT(_LtDebug(__FILE__, w,
309 "GetNodeList: toffset: %d coffset: %d\n",
310 toffset, coffset));
311
312 if (CoreBeingDestroyed(w))
313 {
314 DEBUGOUT(_LtDebug(__FILE__, w,
315 "GetNodeList: Widget is being destroyed; return\n"));
316
317 return;
318 }
319
320 nav = _XmGetNavigability(w);
321
322 if (nav == XmNOT_NAVIGABLE && !XtIsShell(w))
323 {
324 DEBUGOUT(_LtDebug(__FILE__, w,
325 "GetNodeList: Widget is not navigable; return\n"));
326
327 return;
328 }
329
330 num_nodes = tree->num_entries;
331
332 tmp = AllocListEntry(tree);
333
334 tmp->widget = w;
335 tmp->rect.x = rect->x + XtX(w) + XtBorderWidth(w);
336 tmp->rect.y = rect->y + XtY(w) + XtBorderWidth(w);
337 tmp->rect.width = XtWidth(w);
338 tmp->rect.height = XtHeight(w);
339
340 if (num_nodes)
341 {
342 nt = _XmGetNavigationType(w);
343 }
344 else
345 {
346 nt = XmSTICKY_TAB_GROUP;
347 }
348
349 DEBUGOUT(_LtDebug(__FILE__, w,
350 "GetNodeList: Got NavigationType %d Navigability: %d\n",
351 nt, nav));
352
353 tmp->nav_type = nt;
354 if (nav == XmCONTROL_NAVIGABLE)
355 {
356 DEBUGOUT(_LtDebug(__FILE__, w,
357 "GetNodeList: Widget is CONTROL NODE; coffset %d\n",
358 coffset));
359
360 tmp->type = XmCONTROL_NODE;
361 tmp->tab_parent.offset = coffset;
362 return;
363 }
364 if (nav == XmTAB_NAVIGABLE)
365 {
366 DEBUGOUT(_LtDebug(__FILE__, w,
367 "GetNodeList: Widget is TAB NODE; toffset %d\n",
368 toffset));
369
370 tmp->type = XmTAB_NODE;
371 tmp->tab_parent.offset = toffset;
372 return;
373 }
374 if ((nav != XmNOT_NAVIGABLE || num_nodes == 0) && !XtIsComposite(w))
375 {
376 tree->num_entries--;
377 return;
378 }
379
380 trect = tmp->rect;
381 rect = &trect;
382 if (nav == XmDESCENDANTS_NAVIGABLE)
383 {
384 DEBUGOUT(_LtDebug(__FILE__, w,
385 "GetNodeList: DESCENDENTS NAVIGABLE; return\n"));
386
387 num_nodes = toffset;
388 tree->num_entries--;
389 }
390 else
391 {
392 DEBUGOUT(_LtDebug(__FILE__, w,
393 "GetNodeList: create tab and control trees\n"));
394
395 tmp->type = XmTAB_TREE_NODE;
396 tmp->tab_parent.offset = toffset;
397 tmp->up = NULL;
398 tmp->down = NULL;
399
400 toffset = num_nodes;
401
402 tmp = AllocListEntry(tree);
403 *tmp = tree->head[num_nodes];
404 num_nodes++;
405
406 tmp->tab_parent.offset = toffset;
407 tmp->type = XmCONTROL_TREE_NODE;
408
409 coffset = num_nodes;
410 }
411
412 if (!(needfree = GetChildList(w, &children, &nchildren)))
413 {
414 children = MGR_Children(w);
415 nchildren = MGR_NumChildren(w);
416 }
417
418 for (i = 0; i < nchildren; i++)
419 {
420 DEBUGOUT(_LtDebug(__FILE__, w,
421 "GetNodeList: recurse: toffset %d coffset %d\n",
422 toffset, coffset));
423
424 GetNodeList(children[i], rect, tree, toffset, coffset);
425 }
426
427 if (needfree)
428 {
429 XtFree((char *)children);
430 }
431 }
432
433
434 static void
GetRectRelativeToShell(Widget w,XRectangle * rect)435 GetRectRelativeToShell(Widget w, XRectangle *rect)
436 {
437 Position cx, cy;
438
439 DEBUGOUT(_LtDebug(__FILE__, w, "GetRectRelativeToShell\n"));
440
441 rect->width = XtWidth(w);
442 rect->height = XtHeight(w);
443
444 do
445 {
446 cx = XtX(w) + XtBorderWidth(w);
447 cy = XtY(w) + XtBorderWidth(w);
448
449 w = XtParent(w);
450 }
451 while (w && !XtIsShell(w));
452
453 rect->x = cx;
454 rect->y = cy;
455 }
456
457
458 static int
CompareExcls(XmConst void * a,XmConst void * b)459 CompareExcls(XmConst void *a, XmConst void *b)
460 {
461 return 0;
462 }
463
464
465 static int
CompareNodesVert(XmConst void * a,XmConst void * b)466 CompareNodesVert(XmConst void *a, XmConst void *b)
467 {
468 XmTravTreeNode nodea = *(XmTravTreeNode *)a, nodeb = *(XmTravTreeNode *)b;
469 Position centera = nodea->rect.x + nodea->rect.width / 2;
470 Position centerb = nodeb->rect.x + nodeb->rect.width / 2;
471
472 if (centera > nodeb->rect.x + nodeb->rect.width &&
473 centerb < nodea->rect.x)
474 {
475 return 1;
476 }
477 else if (centerb > nodea->rect.x + nodea->rect.width &&
478 centera < nodeb->rect.x)
479 {
480 return -1;
481 }
482 else if (nodea->rect.y < nodeb->rect.y)
483 {
484 return -1;
485 }
486 else if (nodea->rect.y > nodeb->rect.y)
487 {
488 return 1;
489 }
490 else
491 {
492 return 0;
493 }
494 }
495
496
497 static int
CompareNodesHoriz(XmConst void * a,XmConst void * b)498 CompareNodesHoriz(XmConst void *a, XmConst void *b)
499 {
500 XmTravTreeNode nodea = *(XmTravTreeNode *)a, nodeb = *(XmTravTreeNode *)b;
501 Position centera = nodea->rect.y + nodea->rect.height / 2;
502 Position centerb = nodeb->rect.y + nodeb->rect.height / 2;
503
504 if (centera > nodeb->rect.y + nodeb->rect.height &&
505 centerb < nodea->rect.y)
506 {
507 return 1;
508 }
509 else if (centerb > nodea->rect.y + nodea->rect.height &&
510 centera < nodeb->rect.y)
511 {
512 return -1;
513 }
514 else if (nodea->rect.x < nodeb->rect.x)
515 {
516 return -1;
517 }
518 else if (nodea->rect.x > nodeb->rect.x)
519 {
520 return 1;
521 }
522 else
523 {
524 return 0;
525 }
526 }
527
528
529 static void
SortGraph(XmTravTreeNode node,Boolean have_excls)530 SortGraph(XmTravTreeNode node, Boolean have_excls)
531 {
532 XmTravTreeNode *block, tmp, *ptr;
533 int cnt, i;
534
535 if (node->up == NULL)
536 {
537 return;
538 }
539
540 cnt = 1;
541 tmp = node->up;
542 while (tmp->next != NULL)
543 {
544 cnt++;
545 tmp = tmp->next;
546 }
547
548 block = (XmTravTreeNode *)XtMalloc(cnt * sizeof(XmTravTreeNode));
549
550 i = 0;
551 tmp = node->up;
552 while (tmp != NULL)
553 {
554 block[i] = tmp;
555 i++;
556 tmp = tmp->next;
557 }
558
559 if (node->type == XmTAB_TREE_NODE && cnt > 1)
560 {
561 if (have_excls)
562 {
563 qsort(block, cnt, sizeof(XmTravTreeNode), CompareExcls);
564 }
565 else
566 {
567 qsort(&block[1], cnt - 1, sizeof(XmTravTreeNode), CompareNodesHoriz);
568 }
569 }
570 else if (cnt > 1 && (have_excls || node->nav_type == XmSTICKY_TAB_GROUP))
571 {
572 qsort(block, cnt, sizeof(XmTravTreeNode), CompareNodesHoriz);
573 }
574
575 node->up = block[0];
576 ptr = block;
577 block[0]->prev = NULL;
578
579 for (i = 1; i < cnt; i++)
580 {
581 (*ptr)->next = *(ptr + 1);
582 ptr++;
583 (*ptr)->prev = *(ptr - 1);
584 }
585 (*ptr)->next = NULL;
586 node->down = *ptr;
587
588 if (node->type == XmCONTROL_TREE_NODE)
589 {
590
591 node->up->prev = *ptr;
592 node->down->next = node->up;
593
594 if (!have_excls || node->type == XmSTICKY_TAB_GROUP)
595 {
596 qsort(block, cnt, sizeof(XmTravTreeNode), CompareNodesVert);
597 }
598
599 ptr = block;
600 block[0]->up = block[cnt - 1];
601 for (i = 1; i < cnt; i++)
602 {
603 (*ptr)->down = *(ptr + 1);
604 ptr++;
605 (*ptr)->up = *(ptr - 1);
606 }
607 (*ptr)->down = block[0];
608 }
609
610 XtFree((char *)block);
611 }
612
613
614 static XmTravTreeNode
GetNextNearestNode(XmTravTreeNode node,XRectangle * rect)615 GetNextNearestNode(XmTravTreeNode node, XRectangle *rect)
616 {
617 XmTravTreeNode tmp, *block;
618 int cnt, i;
619 XmTravTreeNodeRec input;
620
621 DEBUGOUT(_LtDebug(__FILE__, node->widget, "GetNextNearestNode\n"));
622
623 if (!node->up)
624 {
625 return NULL;
626 }
627
628 cnt = 1;
629 tmp = node->up;
630 do
631 {
632 cnt++;
633 if (tmp == node->down)
634 {
635 break;
636 }
637 tmp = tmp->next;
638 }
639 while (tmp != NULL);
640
641 block = (XmTravTreeNode *)XtMalloc(cnt * sizeof(XmTravTreeNode));
642
643 input.widget = NULL;
644 input.rect = *rect;
645 block[0] = &input;
646
647 tmp = node->up;
648 for (i = 1; i < cnt; i++)
649 {
650 block[i] = tmp;
651 tmp = tmp->next;
652 }
653
654 qsort(block, cnt, sizeof(XmTravTreeNode), CompareNodesHoriz);
655
656 i = 0, tmp = NULL;
657 while (i != cnt)
658 {
659 if (block[i] != &input)
660 {
661 i++;
662 continue;
663 }
664 else if (i + 1 == cnt)
665 {
666 tmp = NULL;
667 break;
668 }
669 else
670 {
671 tmp = block[i + 1];
672 break;
673 }
674 }
675
676 XtFree((char *)block);
677
678 return tmp;
679 }
680
681
682 static void
LinkNodeList(XmTravTree tree)683 LinkNodeList(XmTravTree tree)
684 {
685 unsigned short i;
686 XmTravTreeNode tmp, link;
687
688 DEBUGOUT(_LtDebug(__FILE__, tree->shell, "LinkNodeList\n"));
689 DEBUGOUT(DumpTree(tree));
690
691 tmp = tree->head;
692
693 for (i = 0; i < tree->num_entries; i++)
694 {
695 if (tmp->tab_parent.offset >= 0)
696 {
697 link = &tree->head[tmp->tab_parent.offset];
698 }
699 else
700 {
701 link = NULL;
702 }
703
704 tmp->tab_parent.link = link;
705 if (link)
706 {
707 if (link->down)
708 {
709 link->down->next = tmp;
710 }
711 else
712 {
713 link->up = tmp;
714 }
715 tmp->next = NULL;
716 tmp->prev = link->down;
717 link->down = tmp;
718 }
719 else
720 {
721 tmp->next = NULL;
722 tmp->prev = NULL;
723 }
724
725 tmp++;
726 }
727
728 DEBUGOUT(DumpTree(tree));
729 }
730
731
732 static void
SortNodeList(XmTravTree tree)733 SortNodeList(XmTravTree tree)
734 {
735 int i;
736 XmTravTreeNode tmp;
737
738 DEBUGOUT(_LtDebug(__FILE__, tree->shell, "SortNodeList\n"));
739
740 tmp = tree->head;
741
742 for (i = 0; i < tree->num_entries; i++)
743 {
744 if (tmp->type == XmTAB_TREE_NODE || tmp->type == XmCONTROL_TREE_NODE)
745 {
746 if (tree->num_excls != 0)
747 {
748 SortGraph(tmp, True);
749 }
750 else
751 {
752 SortGraph(tmp, False);
753 }
754 }
755
756 tmp++;
757 }
758
759 DEBUGOUT(DumpTree(tree));
760 }
761
762
763 static Boolean
NodeIsTraversable(XmTravTreeNode node)764 NodeIsTraversable(XmTravTreeNode node)
765 {
766 if (node == NULL)
767 return False;
768
769 DEBUGOUT(_LtDebug(__FILE__, node->widget, "NodeIsTraversable\n"));
770
771 if (node->widget == NULL)
772 {
773 return False;
774 }
775
776 if (node->type == XmTAB_TREE_NODE || node->type == XmCONTROL_TREE_NODE)
777 {
778 return False;
779 }
780
781 return XmIsTraversable(node->widget);
782 }
783
784
785 static XmTravTreeNode
NextControl(XmTravTreeNode node)786 NextControl(XmTravTreeNode node)
787 {
788 XmTravTreeNode last, next, ptr, start;
789
790 start = node;
791 last = node;
792 ptr = node;
793 next = NULL;
794
795 do
796 {
797
798 if (ptr > start && ptr < next && next == NULL)
799 {
800 next = ptr;
801 }
802
803 if (ptr <= last)
804 {
805 last = ptr;
806 }
807
808 ptr = ptr->next;
809
810 }
811 while (ptr != node);
812
813 if (next == NULL)
814 {
815 next = last;
816 }
817
818 return next;
819 }
820
821
822 static XmTravTreeNode
PrevControl(XmTravTreeNode node)823 PrevControl(XmTravTreeNode node)
824 {
825 XmTravTreeNode last, prev, ptr, start;
826
827 start = node;
828 last = node;
829 ptr = node;
830 prev = NULL;
831
832 do
833 {
834
835 if (ptr < start && ptr > prev && prev == NULL)
836 {
837 prev = ptr;
838 }
839
840 if (ptr > last)
841 {
842 last = ptr;
843 }
844
845 ptr = ptr->prev;
846
847 }
848 while (ptr != node);
849
850 if (prev == NULL)
851 {
852 prev = last;
853 }
854
855 return prev;
856 }
857
858
859 static XmTravTreeNode
TraverseControl(XmTravTreeNode node,XmTraversalDirection dir)860 TraverseControl(XmTravTreeNode node, XmTraversalDirection dir)
861 {
862 XmTravTreeNode tmp, last;
863
864 if (!node)
865 {
866 DEBUGOUT(_LtDebug(__FILE__, NULL,
867 "TraverseControl> given is NULL\n"));
868
869 return NULL;
870 }
871
872 DEBUGOUT(_LtDebug(__FILE__, node->widget, "TraverseControl\n"));
873
874 if (node->type == XmCONTROL_TREE_NODE)
875 {
876 DEBUGOUT(_LtDebug(__FILE__, node->widget,
877 "TraverseControl: CONTROL_TREE_NODE\n"));
878
879 node = node->up;
880 if (node == NULL)
881 {
882 DEBUGOUT(_LtDebug(__FILE__, NULL,
883 "TraverseControl: node->up is NULL\n"));
884 return NULL;
885 }
886
887 DEBUGOUT(_LtDebug(__FILE__, NULL,
888 "TraverseControl: go HOME in CONTROL_TREE\n"));
889 dir = XmTRAVERSE_HOME;
890 }
891 else if (node->type != XmCONTROL_NODE)
892 {
893 DEBUGOUT(_LtDebug(__FILE__, node->widget,
894 "TraverseControl: not CONTROL node\n"));
895 return NULL;
896 }
897
898 tmp = node;
899 last = NULL;
900 do
901 {
902 switch (dir)
903 {
904 case XmTRAVERSE_CURRENT:
905 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
906 "TraverseControl: TRAVERSE_CURRENT\n"));
907 break;
908
909 case XmTRAVERSE_NEXT:
910 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
911 "TraverseControl: TRAVERSE_NEXT\n"));
912 tmp = NextControl(tmp);
913 break;
914
915 case XmTRAVERSE_PREV:
916 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
917 "TraverseControl: TRAVERSE_PREV\n"));
918 tmp = PrevControl(tmp);
919 break;
920
921 case XmTRAVERSE_HOME:
922 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
923 "TraverseControl: TRAVERSE_HOME\n"));
924 DEBUGOUT(DumpNode(0, tmp));
925 tmp = tmp->tab_parent.link;
926
927 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
928 "TraverseControl: parent_link:\n"));
929 DEBUGOUT(DumpNode(0, tmp));
930 tmp = tmp->up;
931
932 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
933 "TraverseControl: parent up:\n"));
934 DEBUGOUT(DumpNode(0, tmp));
935 node = tmp->tab_parent.link;
936
937 DEBUGOUT(_LtDebug(__FILE__, node->widget,
938 "TraverseControl: parent up parent_link:\n"));
939 DEBUGOUT(DumpNode(0, node));
940 node = node->down;
941
942 DEBUGOUT(_LtDebug(__FILE__, node->widget,
943 "TraverseControl: parent up parent_link down:\n"));
944 DEBUGOUT(DumpNode(0, node));
945 dir = XmTRAVERSE_RIGHT;
946
947 break;
948
949 case XmTRAVERSE_UP:
950 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
951 "TraverseControl: TRAVERSE_UP\n"));
952 tmp = tmp->up;
953 break;
954
955 case XmTRAVERSE_DOWN:
956 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
957 "TraverseControl: TRAVERSE_DOWN\n"));
958 tmp = tmp->down;
959 break;
960
961 case XmTRAVERSE_LEFT:
962 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
963 "TraverseControl: TRAVERSE_LEFT\n"));
964 tmp = tmp->prev;
965 break;
966
967 case XmTRAVERSE_RIGHT:
968 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
969 "TraverseControl: TRAVERSE_RIGHT\n"));
970 DEBUGOUT(DumpNode(0, tmp));
971 tmp = tmp->next;
972 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
973 "TraverseControl: after TRAVERSE_RIGHT\n"));
974 DEBUGOUT(DumpNode(0, tmp));
975 break;
976
977 case XmTRAVERSE_NEXT_TAB_GROUP:
978 case XmTRAVERSE_PREV_TAB_GROUP:
979 default:
980 DEBUGOUT(_LtDebug(__FILE__, node->widget,
981 "TraverseControl: TRAVERSE_NEXT(or PREV)_TAB\n"));
982 tmp = last;
983 }
984
985 if (tmp == NULL)
986 {
987 DEBUGOUT(_LtDebug(__FILE__, NULL,
988 "TraverseControl: traverse to NULL\n"));
989 return NULL;
990 }
991
992 if (NodeIsTraversable(tmp))
993 {
994 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
995 "TraverseControl: node is traversable;return\n"));
996
997 DEBUGOUT(DumpNode(0, tmp));
998
999 return tmp;
1000 }
1001 else
1002 {
1003 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
1004 "TraverseControl: node is not traversable\n"));
1005
1006 DEBUGOUT(DumpNode(0, tmp));
1007 }
1008 }
1009 while (tmp != node);
1010
1011 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
1012 "TraverseControl: No luck; returning\n"));
1013 DEBUGOUT(DumpNode(0, tmp));
1014
1015 return tmp;
1016 }
1017
1018
1019 static XmTravTreeNode
TraverseTab(XmTravTreeNode node,XmTraversalDirection dir)1020 TraverseTab(XmTravTreeNode node, XmTraversalDirection dir)
1021 {
1022 XmTravTreeNode tmp, last;
1023 Boolean dir_is_cur, dir_is_not_cur;
1024
1025 if (!node)
1026 {
1027 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1028 "TraverseTab called with null\n"));
1029 return NULL;
1030 }
1031
1032 DEBUGOUT(_LtDebug(__FILE__, node->widget, "TraverseTab\n"));
1033
1034 if (node->type == XmCONTROL_NODE)
1035 {
1036 if (! node->tab_parent.link) {
1037 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1038 "TraverseTab -> NULL\n"));
1039
1040 return NULL;
1041 }
1042
1043 node = node->tab_parent.link;
1044 }
1045
1046 tmp = node;
1047
1048 dir_is_cur = (dir == XmTRAVERSE_CURRENT);
1049 dir_is_not_cur = !dir_is_cur;
1050
1051 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1052 "TraverseTab -> entering loop\n"));
1053 do
1054 {
1055 if (dir != XmTRAVERSE_PREV_TAB_GROUP)
1056 {
1057 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1058 "TraverseTab -> TRAVERSE_NEXT_TAB_GROUP\n"));
1059
1060 if (tmp->type != XmTAB_TREE_NODE || tmp->up == NULL)
1061 {
1062
1063 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1064 "TraverseTab -> Not TAB_TREE or up NULL\n"));
1065
1066 if (tmp->next == NULL)
1067 {
1068
1069 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1070 "TraverseTab -> next node NULL\n"));
1071 last = tmp;
1072
1073 do
1074 {
1075 tmp = tmp->tab_parent.link;
1076
1077 if (tmp == NULL)
1078 {
1079 break;
1080 }
1081
1082 if (dir_is_not_cur)
1083 {
1084 last = tmp;
1085 continue;
1086 }
1087
1088 if (tmp == node)
1089 {
1090 break;
1091 }
1092
1093 last = tmp;
1094
1095 }
1096 while (tmp->next == NULL);
1097
1098 if (dir_is_cur && tmp == node)
1099 {
1100 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1101 "TraverseTab -> CURRENT and home\n"));
1102 return NULL;
1103 }
1104
1105 if (tmp == NULL)
1106 {
1107 tmp = last;
1108 }
1109 else
1110 {
1111 tmp = tmp->next;
1112 }
1113 }
1114 else
1115 {
1116 tmp = tmp->next;
1117 }
1118 }
1119 else
1120 {
1121 tmp = tmp->up;
1122 }
1123
1124 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1125 "TraverseTab -> TRAVERSE_NEXT_TAB_GROUP\n"));
1126 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1127 "TraverseTab -> Compute to\n"));
1128 DEBUGOUT(DumpNode(0, tmp));
1129 }
1130 else
1131 {
1132
1133 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1134 "TraverseTab -> TRAVERSE_PREV_TAB_GROUP\n"));
1135
1136 if (tmp->type != XmTAB_TREE_NODE || tmp->down == NULL)
1137 {
1138
1139 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1140 "TraverseTab -> Not TAB_TREE or down NULL\n"));
1141
1142 if (tmp->prev == NULL)
1143 {
1144
1145 last = tmp;
1146
1147 do
1148 {
1149 tmp = tmp->tab_parent.link;
1150
1151 if (tmp == NULL)
1152 {
1153 break;
1154 }
1155
1156 last = tmp;
1157
1158 }
1159 while (tmp->prev == NULL);
1160
1161 if (tmp == NULL)
1162 {
1163 tmp = last;
1164 }
1165 else
1166 {
1167 tmp = tmp->prev;
1168 }
1169 }
1170 else
1171 {
1172 tmp = tmp->prev;
1173 }
1174 }
1175 else
1176 {
1177 tmp = tmp->down;
1178 }
1179 }
1180
1181 if (tmp == node)
1182 {
1183 DEBUGOUT(_LtDebug(__FILE__, node->widget,
1184 "TraverseTab -> home\n"));
1185
1186 return NULL;
1187 }
1188
1189 if (tmp->type == XmCONTROL_TREE_NODE)
1190 {
1191 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
1192 "TraverseTab -> goto ControlNode\n"));
1193
1194 DEBUGOUT(DumpNode(0, tmp));
1195
1196 if ((last = TraverseControl(tmp, dir)) != NULL)
1197 {
1198
1199 DEBUGOUT(_LtDebug(__FILE__, tmp->widget,
1200 "TraverseTab -> return Control\n"));
1201
1202 DEBUGOUT(DumpNode(0, last));
1203
1204 return last;
1205 }
1206 }
1207
1208 }
1209 while (!NodeIsTraversable(tmp));
1210
1211 return tmp;
1212 }
1213
1214
1215 static Boolean
EffectiveView(Widget w,XRectangle * src,XRectangle * rect)1216 EffectiveView(Widget w, XRectangle *src, XRectangle *rect)
1217 {
1218 Boolean no_scr_par = True;
1219 XRectangle irect, orect;
1220
1221 DEBUGOUT(_LtDebug(__FILE__, w, "EffectiveView\n"));
1222
1223 if (!_XmIsViewable(w))
1224 {
1225 _XmClearRect(rect);
1226 return False;
1227 }
1228
1229 _XmSetRect(rect, w);
1230
1231 while ((w = XtParent(w)) && !XtIsShell(w))
1232 {
1233
1234 if (!_XmIsViewable(w))
1235 {
1236 _XmClearRect(rect);
1237 return False;
1238 }
1239
1240 if (_XmIsScrollableClipWidget(w, rect))
1241 {
1242 no_scr_par = False;
1243 continue;
1244 }
1245
1246 if (no_scr_par)
1247 {
1248 if (_XmIntersectRect(rect, w, rect))
1249 {
1250 continue;
1251 }
1252 else
1253 {
1254 return False;
1255 }
1256 }
1257
1258 if (!_XmIntersectRect(rect, w, &irect))
1259 {
1260 _XmClearRect(rect);
1261 return False;
1262 }
1263
1264 if (rect->width != irect.width || rect->height != irect.height)
1265 {
1266 _XmClearRect(rect);
1267 return False;
1268 }
1269 }
1270
1271 if (!src)
1272 {
1273 return True;
1274 }
1275
1276 if (no_scr_par)
1277 {
1278 return _XmIntersectionOf(rect, src, rect);
1279 }
1280
1281 if (!_XmIntersectionOf(rect, src, &orect))
1282 {
1283 _XmClearRect(rect);
1284 return False;
1285 }
1286
1287 if (rect->width != irect.width || rect->height != irect.height)
1288 {
1289 _XmClearRect(rect);
1290 return False;
1291 }
1292
1293 return True;
1294 }
1295
1296
1297 static Widget
FindFirstManaged(Widget w)1298 FindFirstManaged(Widget w)
1299 {
1300 Cardinal i;
1301
1302 DEBUGOUT(_LtDebug(__FILE__, w, "FindFirstManaged\n"));
1303
1304 if (!XtIsShell(w))
1305 {
1306 return NULL;
1307 }
1308
1309 for (i = 0; i < MGR_NumChildren(w); i++)
1310 {
1311 if (XtIsManaged(MGR_Children(w)[i]))
1312 return MGR_Children(w)[i];
1313 }
1314 return NULL;
1315 }
1316
1317
1318 static Boolean
SetInitialNode(XmTravTreeNode root,XmTravTreeNode leaf)1319 SetInitialNode(XmTravTreeNode root, XmTravTreeNode leaf)
1320 {
1321 DEBUGOUT(_LtDebug(__FILE__, root->widget, "SetInitialNode\n"));
1322
1323 if (!leaf)
1324 {
1325 return False;
1326 }
1327
1328 if (root->up == leaf)
1329 {
1330 return True;
1331 }
1332
1333 DEBUGOUT(_LtDebug2(__FILE__, root->widget, leaf->widget,
1334 "SetInitialNode leaf\n"));
1335
1336 if (root->type == XmTAB_TREE_NODE)
1337 {
1338 root->down->next = root->up;
1339 root->up->prev = root->down;
1340 root->up = leaf;
1341 root->down = leaf->prev;
1342 leaf->prev->next = NULL;
1343 leaf->prev = NULL;
1344 }
1345 else
1346 {
1347 root->up = leaf;
1348 root->down = leaf->prev;
1349 }
1350
1351 return True;
1352 }
1353
1354
1355 static int
SearchTabList(XmTravTree tree,Widget w)1356 SearchTabList(XmTravTree tree, Widget w)
1357 {
1358 int i;
1359
1360 DEBUGOUT(_LtDebug(__FILE__, w, "SearchTabList\n"));
1361
1362 for (i = 0; i < tree->num_tab_entries; i++)
1363 {
1364 if (tree->excl_tabs[i] == w)
1365 {
1366 return i;
1367 }
1368 }
1369 return -1;
1370 }
1371
1372
1373 static void
DeleteFromTabList(XmTravTree tree,int node)1374 DeleteFromTabList(XmTravTree tree, int node)
1375 {
1376 DEBUGOUT(_LtDebug(__FILE__, NULL, "DeleteFromTabList\n"));
1377
1378 if (node < 0 || tree->num_tab_entries == 0)
1379 {
1380 return;
1381 }
1382
1383 memcpy(&tree->excl_tabs[node], &tree->excl_tabs[node + 1],
1384 (tree->num_tab_entries - node - 1) * sizeof(Widget));
1385
1386 tree->num_tab_entries--;
1387 tree->excl_tabs[tree->num_tab_entries] = NULL;
1388 }
1389
1390
1391 static void
SetInitialWidgets(XmTravTree tree)1392 SetInitialWidgets(XmTravTree tree)
1393 {
1394 XmTravTreeNode tmp, child;
1395 int i;
1396
1397 DEBUGOUT(_LtDebug(__FILE__, tree->shell, "SetInitialWidgets\n"));
1398
1399 tmp = tree->head;
1400 for (i = 0; i < tree->num_entries; i++)
1401 {
1402 if (tmp->type != XmTAB_TREE_NODE && tmp->type != XmCONTROL_TREE_NODE)
1403 {
1404 tmp++;
1405 continue;
1406 }
1407
1408 if (tmp->up == NULL)
1409 {
1410 tmp++;
1411 continue;
1412 }
1413
1414 if (tmp->widget != NULL && XmIsManager(tmp->widget) &&
1415 MGR_InitialFocus(tmp->widget) &&
1416 (child = GetNodeFromGraph(tmp, MGR_InitialFocus(tmp->widget))))
1417 {
1418 SetInitialNode(tmp, child);
1419 }
1420 else if (tmp->type == XmTAB_TREE_NODE)
1421 {
1422 SetInitialNode(tmp, tmp + 1);
1423 }
1424
1425 tmp++;
1426 }
1427
1428 DEBUGOUT(DumpTree(tree));
1429 }
1430
1431
1432 static Boolean
InitializeCurrent(XmTravTree tree,Widget w,Boolean check)1433 InitializeCurrent(XmTravTree tree, Widget w, Boolean check)
1434 {
1435 XmTravTreeNode node;
1436 XmNavigability nav;
1437
1438 DEBUGOUT(_LtDebug(__FILE__, w, "InitializeCurrent\n"));
1439
1440 DEBUGOUT(DumpTree(tree));
1441
1442 if (tree->current != NULL)
1443 {
1444 if (w == NULL)
1445 {
1446 DEBUGOUT(_LtDebug(__FILE__, NULL,
1447 "InitializeCurrent: Widget is null\n"));
1448
1449 return True;
1450 }
1451 if (tree->current->widget == w)
1452 {
1453 DEBUGOUT(_LtDebug(__FILE__, w,
1454 "InitializeCurrent: Widget matches\n"));
1455
1456 return True;
1457 }
1458 }
1459
1460 node = GetNodeOfWidget(tree, w);
1461 if (node == NULL)
1462 {
1463 DEBUGOUT(_LtDebug(__FILE__, w,
1464 "InitializeCurrent: Node is NULL\n"));
1465
1466 if (check && (nav = _XmGetNavigability(w)) != XmNOT_NAVIGABLE)
1467 {
1468 DEBUGOUT(_LtDebug(__FILE__, w,
1469 "InitializeCurrent: Node is NULL: return new "
1470 "trav graph\n"));
1471
1472 return _XmNewTravGraph(tree, tree->shell, w);
1473 }
1474 do
1475 {
1476 if (XtIsShell(w))
1477 {
1478 break;
1479 }
1480
1481 if ((node = GetNodeOfWidget(tree, w)) != NULL)
1482 {
1483 break;
1484 }
1485
1486 w = XtParent(w);
1487 }
1488 while (w != NULL);
1489
1490 DEBUGOUT(_LtDebug(__FILE__, w,
1491 "InitializeCurrent: Climbed to node %08x\n",
1492 node));
1493 }
1494
1495 if (node != NULL)
1496 {
1497 DEBUGOUT(_LtDebug(__FILE__, w,
1498 "InitializeCurrent: set current and return node\n"));
1499 DEBUGOUT(DumpNode(0, node));
1500
1501 tree->current = node;
1502 return True;
1503 }
1504 else if (tree->current != NULL)
1505 {
1506 DEBUGOUT(_LtDebug(__FILE__, w,
1507 "InitializeCurrent: current has value and return\n"));
1508
1509 return True;
1510 }
1511 else
1512 {
1513 DEBUGOUT(_LtDebug(__FILE__, w,
1514 "InitializeCurrent: set current to head; return\n"));
1515
1516 DEBUGOUT(DumpNode(0, tree->head));
1517
1518 tree->current = tree->head;
1519 }
1520 return True;
1521 }
1522
1523
1524 static Widget
FindFirstFocus(Widget w)1525 FindFirstFocus(Widget w)
1526 {
1527 Widget shell = _XmFindTopMostShell(w);
1528
1529 DEBUGOUT(_LtDebug(__FILE__, w, "FindFirstFocus\n"));
1530
1531 return _XmNavigate(shell, XmTRAVERSE_CURRENT);
1532 }
1533
1534 /************************ implementation functions *************************/
1535
1536 extern Widget
_XmFindTopMostShell(Widget w)1537 _XmFindTopMostShell(Widget w)
1538 {
1539 Widget shell;
1540
1541 DEBUGOUT(_LtDebug(__FILE__, w, "_XmFindTopMostShell\n"));
1542
1543 shell = w;
1544
1545 while (shell && !XtIsShell(shell))
1546 {
1547 shell = XtParent(shell);
1548 }
1549
1550 return shell;
1551 }
1552
1553
1554 extern void
_XmFreeTravGraph(XmTravTree tree)1555 _XmFreeTravGraph(XmTravTree tree)
1556 {
1557 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmFreeTravGraph\n"));
1558
1559 if (tree->num_alloc == 0)
1560 {
1561 return;
1562 }
1563
1564 XtFree((char *)tree->head);
1565
1566 tree->num_entries = 0;
1567 tree->head = NULL;
1568 tree->current = NULL;
1569 tree->next_alloc = tree->num_alloc;
1570 tree->num_alloc = 0;
1571 tree->shell = NULL;
1572 }
1573
1574
1575 extern Boolean
_XmNewTravGraph(XmTravTree tree,Widget shell,Widget first)1576 _XmNewTravGraph(XmTravTree tree, Widget shell, Widget first)
1577 {
1578 XRectangle rect;
1579
1580 DEBUGOUT(_LtDebug(__FILE__, shell, "_XmNewTravGraph\n"));
1581
1582 if (shell == NULL)
1583 {
1584 if (tree->shell == NULL)
1585 {
1586 shell = first;
1587 if (shell != NULL)
1588 {
1589 while (!XtIsShell(shell))
1590 {
1591 shell = XtParent(shell);
1592 }
1593 tree->shell = shell;
1594 }
1595 }
1596 }
1597
1598 if (tree->shell == NULL || CoreBeingDestroyed(tree->shell))
1599 {
1600 _XmFreeTravGraph(tree);
1601 return False;
1602 }
1603
1604 tree->num_entries = 0;
1605 rect.x = -(XtBorderWidth(shell) + XtX(shell));
1606 rect.y = -(XtBorderWidth(shell) + XtY(shell));
1607 rect.width = XtWidth(shell);
1608 rect.height = XtHeight(shell);
1609
1610 GetNodeList(shell, &rect, tree, -1, -1);
1611
1612 if (tree->num_entries > tree->num_alloc)
1613 {
1614 tree->num_alloc *= 2;
1615 tree->head = (XmTravTreeNode)XtRealloc((char *)tree->head,
1616 sizeof(XmTravTreeNodeRec) *
1617 tree->num_alloc);
1618 }
1619
1620 LinkNodeList(tree);
1621
1622 SortNodeList(tree);
1623
1624 SetInitialWidgets(tree);
1625
1626 InitializeCurrent(tree, first, False);
1627
1628 return True;
1629 }
1630
1631
1632 extern void
_XmResetTravGraph(Widget wid)1633 _XmResetTravGraph(Widget wid)
1634 {
1635 XmFocusData fd = _XmGetFocusData(wid);
1636
1637 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmResetTravGraph\n"));
1638
1639 if (!fd)
1640 {
1641 return;
1642 }
1643
1644 if (fd->tree.num_entries == 0)
1645 {
1646 return;
1647 }
1648
1649 _XmFreeTravGraph(&fd->tree);
1650 }
1651
1652
1653 extern void
_XmTravGraphRemove(XmTravTree tree,Widget w)1654 _XmTravGraphRemove(XmTravTree tree, Widget w)
1655 {
1656 XmTravTreeNode nd;
1657
1658 DEBUGOUT(_LtDebug(__FILE__, w, "_XmTravGraphRemove\n"));
1659
1660 if (tree->num_entries == 0)
1661 {
1662 return;
1663 }
1664
1665 while ((nd = GetNodeOfWidget(tree, w)) != NULL)
1666 {
1667 nd->widget = NULL;
1668 }
1669 }
1670
1671
1672 extern void
_XmTravGraphAdd(XmTravTree tree,Widget w)1673 _XmTravGraphAdd(XmTravTree tree, Widget w)
1674 {
1675 XmTravTreeNode nd;
1676
1677 DEBUGOUT(_LtDebug(__FILE__, w, "_XmTravGraphAdd\n"));
1678
1679 if (tree->num_entries == 0)
1680 {
1681 return;
1682 }
1683
1684 if ((nd = GetNodeOfWidget(tree, w)) != NULL)
1685 {
1686 return;
1687 }
1688
1689 _XmFreeTravGraph(tree);
1690 }
1691
1692
1693 extern void
_XmTravGraphUpdate(XmTravTree tree,Widget w)1694 _XmTravGraphUpdate(XmTravTree tree, Widget w)
1695 {
1696 DEBUGOUT(_LtDebug(__FILE__, w, "_XmTravGraphUpdate\n"));
1697
1698 _XmFreeTravGraph(tree);
1699 }
1700
1701
1702 extern unsigned char
_XmGetFocusPolicy(Widget w)1703 _XmGetFocusPolicy(Widget w)
1704 {
1705 Widget shell = _XmFindTopMostShell(w);
1706 unsigned char policy = XmEXPLICIT;
1707 Widget ext = NULL;
1708
1709 if (shell)
1710 {
1711 ext = _LtFindVendorExt(shell);
1712 }
1713
1714 if (ext)
1715 {
1716 policy = VSEP_FocusPolicy(ext);
1717 }
1718
1719 if (shell && ext)
1720 {
1721 DEBUGOUT(_LtDebug(__FILE__, w, "_XmGetFocusPolicy\n"));
1722 }
1723 else
1724 {
1725 DEBUGOUT(_LtDebug(__FILE__, w, "_XmGetFocusPolicy shell %p ext %p\n",
1726 shell, ext));
1727 }
1728
1729 return policy;
1730 }
1731
1732
1733 extern XmFocusData
_XmCreateFocusData(void)1734 _XmCreateFocusData(void)
1735 {
1736 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmCreateFocusData\n"));
1737
1738 return (XmFocusData)XtCalloc(1, sizeof(XmFocusDataRec));
1739 }
1740
1741
1742 extern void
_XmDestroyFocusData(XmFocusData focusData)1743 _XmDestroyFocusData(XmFocusData focusData)
1744 {
1745 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmDestroyFocusData\n"));
1746
1747 _XmFreeTravGraph(&focusData->tree);
1748 XtFree((char *)focusData->tree.excl_tabs);
1749 XtFree((char *)focusData);
1750 }
1751
1752
1753 extern XmFocusData
_XmGetFocusData(Widget wid)1754 _XmGetFocusData(Widget wid)
1755 {
1756 Widget orig = wid;
1757 Widget ve;
1758 XmFocusData fd;
1759
1760 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmGetFocusData\n"));
1761
1762 if (!wid)
1763 {
1764 return NULL;
1765 }
1766
1767 while (!XtIsShell(wid))
1768 {
1769 wid = XtParent(wid);
1770 }
1771
1772 DEBUGOUT(_LtDebug2(__FILE__, orig, wid, "_XmGetFocusData: Found shell\n"));
1773
1774 if (!wid)
1775 {
1776 return NULL;
1777 }
1778
1779 if (CoreBeingDestroyed(wid))
1780 {
1781 return NULL;
1782 }
1783
1784 if (XtIsSubclass(wid, vendorShellWidgetClass))
1785 {
1786 ve = _LtFindVendorExt(wid);
1787
1788 if (!ve)
1789 {
1790 DEBUGOUT(_LtDebug(__FILE__, orig,
1791 "_XmGetFocusData: no vendor ext\n"));
1792
1793 return NULL;
1794 }
1795
1796 fd = VSEP_FocusData(ve);
1797
1798 if (!fd)
1799 {
1800 DEBUGOUT(_LtDebug(__FILE__, orig,
1801 "_XmGetFocusData: no focus data\n"));
1802
1803 return NULL;
1804 }
1805
1806 fd->focus_policy = VSEP_FocusPolicy(ve);
1807
1808 return fd;
1809 }
1810
1811 DEBUGOUT(_LtDebug(__FILE__, orig,
1812 "_XmGetFocusData: not LessTif vendorshell subclass\n"));
1813
1814 return NULL;
1815 }
1816
1817
1818 extern XmNavigability
_XmGetNavigability(Widget w)1819 _XmGetNavigability(Widget w)
1820 {
1821 XmBaseClassExt *bce;
1822 XmNavigability r;
1823
1824 if (!XtIsRectObj(w))
1825 {
1826 DEBUGOUT(_LtDebug(__FILE__, w,
1827 "_XmGetNavigability : !XtIsRectObj => XmNOT_NAVIGABLE\n"));
1828
1829 return XmNOT_NAVIGABLE;
1830 }
1831
1832 if (CoreBeingDestroyed(w))
1833 {
1834 DEBUGOUT(_LtDebug(__FILE__, w,
1835 "_XmGetNavigability : CoreBeingDestroyed => XmNOT_NAVIGABLE\n"));
1836
1837 return XmNOT_NAVIGABLE;
1838 }
1839
1840 bce = _XmGetBaseClassExtPtr(XtClass(w), XmQmotif);
1841
1842 if (!bce || !*bce)
1843 {
1844 DEBUGOUT(_LtDebug(__FILE__, w,
1845 "_XmGetNavigability : no bce => XmNOT_NAVIGABLE\n"));
1846
1847 return XmNOT_NAVIGABLE;
1848 }
1849
1850 if (!(*bce)->widgetNavigable)
1851 {
1852 DEBUGOUT(_LtDebug(__FILE__, w,
1853 "_XmGetNavigability : NULL bce->widgetNavigable => XmNOT_NAVIGABLE\n"));
1854
1855 return XmNOT_NAVIGABLE;
1856 }
1857
1858 r = ((*bce)->widgetNavigable) (w);
1859
1860 DEBUGOUT(_LtDebug(__FILE__, w,
1861 "_XmGetNavigability : bce->widgetNavigable => %s\n",
1862 _LtDebugNavigability2String(r)));
1863
1864 return r;
1865 }
1866
1867
1868 extern XmNavigationType
_XmGetNavigationType(Widget w)1869 _XmGetNavigationType(Widget w)
1870 {
1871 DEBUGOUT(_LtDebug(__FILE__, w, "_XmGetNavigationType\n"));
1872
1873 if (XmIsPrimitive(w))
1874 {
1875 return Prim_NavigationType(w);
1876 }
1877
1878 if (XmIsManager(w))
1879 {
1880 return MGR_NavigationType(w);
1881 }
1882
1883 if (XmIsGadget(w))
1884 {
1885 return G_NavigationType(w);
1886 }
1887
1888 return XmNONE;
1889 }
1890
1891
1892 extern Boolean
_XmGetEffectiveView(Widget w,XRectangle * rect)1893 _XmGetEffectiveView(Widget w, XRectangle *rect)
1894 {
1895 DEBUGOUT(_LtDebug(__FILE__, w, "_XmGetEffectiveView\n"));
1896
1897 return EffectiveView(w, NULL, rect);
1898 }
1899
1900
1901 extern Boolean
_XmIsTraversable(Widget w,Boolean vischeck)1902 _XmIsTraversable(Widget w, Boolean vischeck)
1903 {
1904 XRectangle rect;
1905
1906 DEBUGOUT(_LtDebug(__FILE__, w, "_XmIsTraversable\n"));
1907 DEBUGOUT(_LtDebug("MENU", w, "_XmIsTraversable\n"));
1908
1909 if (w == NULL || !XtIsManaged(w))
1910 {
1911 DEBUGOUT(_LtDebug0("MENU", w, "\tNot-managed\n"));
1912 return False;
1913 }
1914
1915 if (!_XmIsNavigable(w))
1916 {
1917 DEBUGOUT(_LtDebug0("MENU", w, "\tNot-navigable\n"));
1918 return False;
1919 }
1920
1921 if (vischeck)
1922 {
1923 if (XmGetVisibility(w) == XmVISIBILITY_FULLY_OBSCURED)
1924 {
1925 return False;
1926 }
1927
1928 return True;
1929 }
1930
1931 return _XmGetEffectiveView(w, &rect);
1932 }
1933
1934
1935 extern Boolean
_XmIsNavigable(Widget w)1936 _XmIsNavigable(Widget w)
1937 {
1938 XmNavigability nav;
1939
1940 DEBUGOUT(_LtDebug(__FILE__, w, "_XmIsNavigable()\n"));
1941 DEBUGOUT(_LtDebug("MENU", w, "_XmIsNavigable()\n"));
1942
1943 if (!w)
1944 {
1945 return False;
1946 }
1947
1948 nav = _XmGetNavigability(w);
1949 if (nav != XmTAB_NAVIGABLE && nav != XmCONTROL_NAVIGABLE)
1950 {
1951 DEBUGOUT(_LtDebug(__FILE__, w, " returns False 1: %s\n", _LtDebugNavigability2String(nav)));
1952 DEBUGOUT(_LtDebug0("MENU", w, " returns False 1: %s\n", _LtDebugNavigability2String(nav)));
1953
1954 return False;
1955 }
1956
1957 w = XtParent(w);
1958
1959 while (w)
1960 {
1961 if (XtIsShell(w))
1962 {
1963 break;
1964 }
1965
1966 nav = _XmGetNavigability(w);
1967 if (nav == XmNOT_NAVIGABLE)
1968 {
1969 DEBUGOUT(_LtDebug(__FILE__, w, " returns False 2: %s\n", _LtDebugNavigability2String(nav)));
1970 DEBUGOUT(_LtDebug("MENU", w, " returns False 2: %s\n", _LtDebugNavigability2String(nav)));
1971 return False;
1972 }
1973
1974 w = XtParent(w);
1975 }
1976
1977 DEBUGOUT(_LtDebug(__FILE__, w, " returns True\n"));
1978 DEBUGOUT(_LtDebug("MENU", w, " returns True\n"));
1979
1980 return True;
1981 }
1982
1983
1984 extern Boolean
_XmIsViewable(Widget w)1985 _XmIsViewable(Widget w)
1986 {
1987 XWindowAttributes wa;
1988
1989 DEBUGOUT(_LtDebug(__FILE__, w, "_XmIsViewable\n"));
1990
1991 if (CoreBeingDestroyed(w))
1992 {
1993 return False;
1994 }
1995
1996 if (!XtIsRealized(w))
1997 {
1998 return False;
1999 }
2000
2001 if (!XtIsManaged(w))
2002 {
2003 return False;
2004 }
2005
2006 if (XmIsGadget(w))
2007 {
2008 return True;
2009 }
2010
2011 if (CoreMappedWhenManaged(w))
2012 {
2013 return True;
2014 }
2015
2016 XGetWindowAttributes(XtDisplay(w), XtWindow(w), &wa);
2017 if (wa.map_state != IsViewable)
2018 {
2019 return False;
2020 }
2021
2022 return True;
2023 }
2024
2025
2026 extern void
_XmValidateFocus(Widget wid)2027 _XmValidateFocus(Widget wid)
2028 {
2029 XmFocusData fd = _XmGetFocusData(wid);
2030 Widget w;
2031
2032 if (fd == NULL)
2033 {
2034 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmValidateFocus(fd NULL)\n"));
2035 return;
2036 }
2037
2038 if (fd->focus_policy != XmEXPLICIT)
2039 {
2040 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmValidateFocus (fp != XmEXPLICIT)\n"));
2041 return;
2042 }
2043
2044 if (fd->focus_item == NULL)
2045 {
2046 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmValidateFocus (fi != NULL)\n"));
2047 return;
2048 }
2049
2050 if (_XmIsTraversable(fd->focus_item, True))
2051 {
2052 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmValidateFocus (fi traversable)\n"));
2053 return;
2054 }
2055
2056 if (fd->focus_item == fd->active_tab_group)
2057 {
2058 w = _XmTraverseAway(&fd->tree, fd->focus_item, False);
2059 }
2060 else
2061 {
2062 w = _XmTraverseAway(&fd->tree, fd->focus_item, True);
2063 }
2064
2065 if (w == NULL)
2066 {
2067 w = wid;
2068 }
2069
2070 _XmMgrTraversal(w, XmTRAVERSE_CURRENT);
2071 }
2072
2073
2074 extern void
_XmSetActiveTabGroup(XmFocusData focusData,Widget tabGroup)2075 _XmSetActiveTabGroup(XmFocusData focusData,
2076 Widget tabGroup)
2077 {
2078 DEBUGOUT(_LtDebug(__FILE__, tabGroup, "_XmSetActiveTabGroup\n"));
2079
2080 focusData->active_tab_group = tabGroup;
2081 }
2082
2083
2084 extern Widget
_XmGetActiveTabGroup(Widget widget)2085 _XmGetActiveTabGroup(Widget widget)
2086 {
2087 XmFocusData fd = _XmGetFocusData(widget);
2088
2089 DEBUGOUT(_LtDebug(__FILE__, widget, "_XmGetActiveTabGroup\n"));
2090
2091 if (!fd)
2092 {
2093 return NULL;
2094 }
2095
2096 return fd->active_tab_group;
2097 }
2098
2099
2100 extern Widget
_XmFindNextTabGroup(Widget wid)2101 _XmFindNextTabGroup(Widget wid)
2102 {
2103 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmFindNextTabGroup\n"));
2104
2105 return _XmNavigate(wid, XmTRAVERSE_NEXT_TAB_GROUP);
2106 }
2107
2108
2109 extern Widget
_XmFindPrevTabGroup(Widget wid)2110 _XmFindPrevTabGroup(Widget wid)
2111 {
2112 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmFindPrevTabGroup\n"));
2113
2114 return _XmNavigate(wid, XmTRAVERSE_PREV_TAB_GROUP);
2115 }
2116
2117
2118 extern Boolean
_XmSetInitialOfTabGraph(XmTravTree tree,Widget tab,Widget first)2119 _XmSetInitialOfTabGraph(XmTravTree tree, Widget tab, Widget first)
2120 {
2121 XmTravTreeNode node, tnode;
2122
2123 DEBUGOUT(_LtDebug(__FILE__, tab, "_XmSetInitialOfTabGraph\n"));
2124
2125 if ((node = GetNodeOfWidget(tree, tab)) == NULL)
2126 {
2127 return False;
2128 }
2129
2130 if (node->type != XmTAB_TREE_NODE)
2131 {
2132 if (node->type != XmCONTROL_TREE_NODE)
2133 return False;
2134 }
2135
2136 if (SetInitialNode(node, GetNodeFromGraph(node, first)))
2137 {
2138 return True;
2139 }
2140
2141 if ((tnode = GetNodeFromGraph(node, tab)) == NULL)
2142 {
2143 return False;
2144 }
2145
2146 if (!SetInitialNode(tnode, GetNodeFromGraph(tnode, first)))
2147 {
2148 return False;
2149 }
2150
2151 if (!SetInitialNode(node, tnode))
2152 {
2153 return False;
2154 }
2155
2156 return True;
2157 }
2158
2159
2160 extern void
_XmSetInitialOfTabGroup(Widget tab_group,Widget init_focus)2161 _XmSetInitialOfTabGroup(Widget tab_group,
2162 Widget init_focus)
2163 {
2164 XmFocusData fd;
2165
2166 DEBUGOUT(_LtDebug(__FILE__, tab_group, "_XmSetInitialOfTabGroup\n"));
2167
2168 if (XmIsManager(tab_group))
2169 {
2170 MGR_InitialFocus(tab_group) = init_focus;
2171 }
2172
2173 if ((fd = _XmGetFocusData(tab_group)) == NULL)
2174 {
2175 return;
2176 }
2177
2178 if (fd->tree.num_entries == 0)
2179 {
2180 return;
2181 }
2182
2183 _XmSetInitialOfTabGraph(&fd->tree, tab_group, init_focus);
2184 }
2185
2186
2187 extern Widget
_XmGetActiveItem(Widget w)2188 _XmGetActiveItem(Widget w)
2189 {
2190 DEBUGOUT(_LtDebug(__FILE__, w, "_XmGetActiveItem\n"));
2191
2192 return XmGetFocusWidget(w);
2193 }
2194
2195
2196 extern void
_XmTabListAdd(XmTravTree tree,Widget w)2197 _XmTabListAdd(XmTravTree tree, Widget w)
2198 {
2199 int node;
2200 Widget shell;
2201
2202 DEBUGOUT(_LtDebug(__FILE__, w, "_XmTabListAdd\n"));
2203
2204 if ((node = SearchTabList(tree, w)) >= 0)
2205 {
2206 return;
2207 }
2208
2209 if (tree->num_tab_alloc == 0)
2210 {
2211 shell = _XmFindTopMostShell(w);
2212
2213 tree->num_tab_alloc = ALLOC_INCR;
2214
2215 tree->excl_tabs = (Widget *)XtCalloc(tree->num_tab_alloc,
2216 sizeof(Widget));
2217
2218 tree->excl_tabs[0] = shell;
2219 tree->num_tab_entries = 1;
2220 }
2221
2222 if (tree->num_tab_entries == tree->num_tab_alloc)
2223 {
2224 tree->num_tab_alloc += ALLOC_INCR;
2225
2226 tree->excl_tabs = (Widget *)XtRealloc((char *)tree->excl_tabs,
2227 tree->num_tab_alloc *
2228 sizeof(Widget));
2229 }
2230
2231 tree->excl_tabs[tree->num_tab_entries] = w;
2232 tree->num_tab_entries++;
2233 }
2234
2235
2236 extern void
_XmTabListDelete(XmTravTree tree,Widget w)2237 _XmTabListDelete(XmTravTree tree, Widget w)
2238 {
2239 int node;
2240
2241 DEBUGOUT(_LtDebug(__FILE__, w, "_XmTabListDelete\n"));
2242
2243 node = SearchTabList(tree, w);
2244
2245 DeleteFromTabList(tree, node);
2246
2247 if (tree->num_tab_entries + ALLOC_INCR < tree->num_tab_alloc)
2248 {
2249 tree->num_tab_alloc -= ALLOC_INCR;
2250 tree->excl_tabs = (Widget *)XtRealloc((char *)tree->excl_tabs,
2251 tree->num_tab_alloc *
2252 sizeof(Widget));
2253 }
2254 }
2255
2256
2257 extern void
_XmClearFocusPath(Widget wid)2258 _XmClearFocusPath(Widget wid)
2259 {
2260 XmFocusData fd;
2261
2262 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmClearFocusPath\n"));
2263
2264 while (wid != NULL)
2265 {
2266 if (XtIsShell(wid))
2267 {
2268 if ((fd = _XmGetFocusData(wid)) == NULL)
2269 {
2270 return;
2271 }
2272
2273 fd->active_tab_group = NULL;
2274 fd->focus_item = NULL;
2275 fd->old_focus_item = NULL;
2276
2277 return;
2278 }
2279
2280 if (XmIsManager(wid))
2281 {
2282 MGR_ActiveChild(wid) = NULL;
2283 }
2284
2285 wid = XtParent(wid);
2286 }
2287 }
2288
2289
2290 extern Boolean
_XmFocusIsHere(Widget w)2291 _XmFocusIsHere(Widget w)
2292 {
2293 XmFocusData fd = _XmGetFocusData(w);
2294 Widget par;
2295
2296 DEBUGOUT(_LtDebug(__FILE__, w, "_XmFocusIsHere\n"));
2297
2298 if (!fd)
2299 {
2300 return False;
2301 }
2302
2303 if (fd->focus_item == NULL)
2304 {
2305 return False;
2306 }
2307
2308 par = fd->focus_item;
2309 while (!XtIsShell(par))
2310 {
2311 if (par == w)
2312 {
2313 return True;
2314 }
2315
2316 par = XtParent(par);
2317 }
2318
2319 return False;
2320 }
2321
2322
2323 extern void
_XmFocusModelChanged(Widget wid,XtPointer client_data,XtPointer call_data)2324 _XmFocusModelChanged(Widget wid,
2325 XtPointer client_data,
2326 XtPointer call_data)
2327 {
2328 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmFocusModelChanged\n"));
2329 }
2330
2331
2332 extern void
_XmSetRect(XRectangle * rect,Widget w)2333 _XmSetRect(XRectangle *rect,
2334 Widget w)
2335 {
2336 Position rx, ry;
2337
2338 DEBUGOUT(_LtDebug(__FILE__, w, "_XmSetRect\n"));
2339
2340 XtTranslateCoords(XtParent(w), XtX(w), XtY(w), &rx, &ry);
2341
2342 rect->x = rx + XtBorderWidth(w);
2343 rect->y = ry + XtBorderWidth(w);
2344 rect->width = XtWidth(w);
2345 rect->height = XtHeight(w);
2346 }
2347
2348
2349 extern Boolean
_XmIntersectionOf(XRectangle * a,XRectangle * b,XRectangle * dest)2350 _XmIntersectionOf(XRectangle *a, XRectangle *b, XRectangle *dest)
2351 {
2352 Position ax, ay, bx, by, tmp;
2353
2354 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmIntersectionOf\n"));
2355
2356 ax = a->x + a->width;
2357 bx = b->x + b->width;
2358 ay = a->y + a->height;
2359 by = b->y + b->height;
2360
2361 ax--;
2362 bx--;
2363 ay--;
2364 by--;
2365
2366 if (a->x >= b->x)
2367 {
2368 dest->x = a->x;
2369 }
2370 else
2371 {
2372 dest->x = b->x;
2373 }
2374
2375 if (a->y >= b->y)
2376 {
2377 dest->y = a->y;
2378 }
2379 else
2380 {
2381 dest->y = b->y;
2382 }
2383
2384 if (ax < bx)
2385 {
2386 tmp = ax - dest->x + 1;
2387 }
2388 else
2389 {
2390 tmp = bx - dest->x + 1;
2391 }
2392
2393 if (tmp < 0)
2394 {
2395 tmp = 0;
2396 }
2397
2398 dest->width = tmp;
2399
2400 if (ay < by)
2401 {
2402 tmp = ay - dest->y + 1;
2403 }
2404 else
2405 {
2406 tmp = by - dest->y + 1;
2407 }
2408
2409 if (tmp < 0)
2410 {
2411 tmp = 0;
2412 }
2413
2414 dest->height = tmp;
2415
2416 if (dest->width == 0 || dest->height == 0)
2417 {
2418 return False;
2419 }
2420
2421 return True;
2422 }
2423
2424
2425 extern int
_XmIntersectRect(XRectangle * srcRectA,Widget widget,XRectangle * dstRect)2426 _XmIntersectRect(XRectangle *srcRectA,
2427 Widget widget,
2428 XRectangle *dstRect)
2429 {
2430 Position rx, ry;
2431 XRectangle rect;
2432
2433 DEBUGOUT(_LtDebug(__FILE__, widget, "_XmIntersectRect\n"));
2434
2435 XtTranslateCoords(XtParent(widget), XtX(widget), XtY(widget), &rx, &ry);
2436
2437 rx += XtBorderWidth(widget);
2438 ry += XtBorderWidth(widget);
2439
2440 rect.x = rx;
2441 rect.y = ry;
2442 rect.width = XtWidth(widget);
2443 rect.height = XtHeight(widget);
2444
2445 return _XmIntersectionOf(srcRectA, &rect, dstRect);
2446 }
2447
2448
2449 extern int
_XmEmptyRect(XRectangle * r)2450 _XmEmptyRect(XRectangle *r)
2451 {
2452 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmEmptyRect\n"));
2453
2454 if (r->x == 0 && r->height == 0)
2455 {
2456 return True;
2457 }
2458
2459 return False;
2460 }
2461
2462
2463 extern void
_XmClearRect(XRectangle * r)2464 _XmClearRect(XRectangle *r)
2465 {
2466 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmClearRect\n"));
2467
2468 r->x = 0;
2469 r->y = 0;
2470 r->width = 0;
2471 r->height = 0;
2472 }
2473
2474
2475 extern Widget
_XmGetClippingAncestor(Widget w,XRectangle * rect)2476 _XmGetClippingAncestor(Widget w, XRectangle *rect)
2477 {
2478 XRectangle rect_in, rect_out;
2479
2480 DEBUGOUT(_LtDebug(__FILE__, w, "_XmGetClippingAncestor\n"));
2481
2482 if (w == NULL)
2483 {
2484 return NULL;
2485 }
2486
2487 w = XtParent(w);
2488
2489 while (w && !XtIsShell(w))
2490 {
2491 _XmSetRect(&rect_in, w);
2492 if (!_XmIntersectionOf(rect, &rect_in, &rect_out))
2493 {
2494 return w;
2495 }
2496 if (rect->width != rect_out.width || rect->height != rect_out.height)
2497 {
2498 return w;
2499 }
2500
2501 w = XtParent(w);
2502 }
2503
2504 return NULL;
2505 }
2506
2507
2508 extern Widget
_XmIsScrollableClipWidget(Widget w,XRectangle * rect)2509 _XmIsScrollableClipWidget(Widget w, XRectangle *rect)
2510 {
2511 DEBUGOUT(_LtDebug(__FILE__, w, "_XmIsScrollableClipWidget\n"));
2512
2513 if (!XmIsDrawingArea(w))
2514 {
2515 return NULL;
2516 }
2517
2518 if (DA_ResizePolicy(w) == XmRESIZE_NONE)
2519 {
2520 return NULL;
2521 }
2522
2523 if (!XmIsScrolledWindow(XtParent(w)) ||
2524 ((Widget)SW_ClipWindow(XtParent(w)) != w &&
2525 SW_WorkWindow(XtParent(w)) != w))
2526 {
2527 return NULL;
2528 }
2529
2530 _XmSetRect(rect, w);
2531
2532 return XtParent(w);
2533 }
2534
2535 /*
2536 * Function Name: _XmCreateVisibilityRect
2537 *
2538 * If the widget isn�t visible the function returns False, else it
2539 * creates the intersection between the widget and all it�s parents execpt
2540 * the shell and returns True.
2541 */
2542
2543 extern Boolean
_XmCreateVisibilityRect(Widget w,XRectangle * rectPtr)2544 _XmCreateVisibilityRect(Widget w,
2545 XRectangle *rectPtr)
2546 {
2547 Widget cw;
2548 DEBUGOUT(_LtDebug(__FILE__, w, "_XmCreateVisibilityRect\n"));
2549
2550 if (!_XmIsViewable(w))
2551 {
2552 _XmClearRect(rectPtr);
2553 return False;
2554 }
2555 if (w && XtParent(w) &&
2556 (cw =_XmIsScrollableClipWidget(XtParent(w), rectPtr)))
2557 {
2558 w = cw;
2559 if (!_XmIsViewable(w))
2560 {
2561 _XmClearRect(rectPtr);
2562 return False;
2563 }
2564 }
2565
2566 _XmSetRect(rectPtr, w);
2567
2568 while (w && !XtIsShell(w))
2569 {
2570 if (_XmIsViewable(w) && _XmIntersectRect(rectPtr, w, rectPtr))
2571 {
2572 w = XtParent(w);
2573 }
2574 else
2575 {
2576 _XmClearRect(rectPtr);
2577 return False;
2578 }
2579 }
2580 return True;
2581 }
2582
2583
2584 extern Boolean
_XmCallFocusMoved(Widget old,Widget new_wid,XEvent * event)2585 _XmCallFocusMoved(Widget old,
2586 Widget new_wid,
2587 XEvent *event)
2588 {
2589 Widget tsh;
2590 Widget ve;
2591 XmFocusMovedCallbackStruct cbs;
2592
2593 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmCallFocusMoved(): %s %s\n",
2594 old ? XtName(old) : "(null)",
2595 new_wid ? XtName(new_wid) : "(null)"));
2596
2597 if (old)
2598 {
2599 tsh = _XmFindTopMostShell(old);
2600 }
2601 else
2602 {
2603 tsh = _XmFindTopMostShell(new_wid);
2604 }
2605 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmCallFocusMoved(): tsh %s\n",
2606 tsh ? XtName(tsh) : "(null)"
2607 ));
2608
2609 if (!XtIsSubclass(tsh, vendorShellWidgetClass))
2610 {
2611 return True;
2612 }
2613
2614 ve = _LtFindVendorExt(tsh);
2615 if (!ve)
2616 {
2617 return True;
2618 }
2619
2620 if (!VSEP_FocusMovedCallback(ve))
2621 {
2622 return True;
2623 }
2624
2625 cbs.reason = XmCR_FOCUS;
2626 cbs.event = event;
2627 cbs.cont = True;
2628 cbs.old_focus = old;
2629 cbs.new_focus = new_wid;
2630 cbs.focus_policy = VSEP_FocusPolicy(ve);
2631
2632 XtCallCallbackList(tsh, VSEP_FocusMovedCallback(ve), (XtPointer)&cbs);
2633
2634 return cbs.cont;
2635 }
2636
2637
2638 static Boolean
_XmCallTraverseObscured(Widget w,XmTraversalDirection dir)2639 _XmCallTraverseObscured(Widget w, XmTraversalDirection dir)
2640 {
2641 XRectangle rect;
2642 XmTraverseObscuredCallbackStruct cbs;
2643 Widget anc, scr;
2644
2645 DEBUGOUT(_LtDebug(__FILE__, w, "_XmCallTraverseObscured\n"));
2646
2647 cbs.reason = XmCR_OBSCURED_TRAVERSAL;
2648 cbs.event = NULL;
2649 cbs.traversal_destination = w;
2650 cbs.direction = dir;
2651
2652 _XmSetRect(&rect, w);
2653 anc = w;
2654
2655 while ((anc = _XmGetClippingAncestor(anc, &rect)) != NULL)
2656 {
2657 if ((scr = _XmIsScrollableClipWidget(anc, &rect)) != NULL)
2658 {
2659 XtCallCallbackList(scr, SW_TraverseObscuredCallback(scr),
2660 (XtPointer)&cbs);
2661 anc = scr;
2662 }
2663 else
2664 {
2665 _XmIntersectRect(&rect, anc, &rect);
2666 }
2667 }
2668
2669 return _XmIsTraversable(w, True);
2670 }
2671
2672
2673 extern void
_XmWidgetFocusChange(Widget wid,XmFocusChange change)2674 _XmWidgetFocusChange(Widget wid,
2675 XmFocusChange change)
2676 {
2677 XmBaseClassExt *bce;
2678
2679 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmWidgetFocusChange: %s\n",
2680 _LtDebugFocusChange2String(change)));
2681
2682 if (!XtIsRectObj(wid))
2683 return;
2684
2685 if (CoreBeingDestroyed(wid))
2686 {
2687 return;
2688 }
2689
2690 bce = _XmGetBaseClassExtPtr(XtClass(wid), XmQmotif);
2691
2692 if (bce && *bce && (*bce)->focusChange)
2693 {
2694 ((*bce)->focusChange) (wid, change);
2695 }
2696 else
2697 {
2698 DEBUGOUT(_LtDebug(__FILE__, wid,
2699 "_XmWidgetFocusChange: couldn't call (*bce)->focusChange\n"));
2700 }
2701 }
2702
2703
2704 extern Boolean
_XmFocusIsInShell(Widget wid)2705 _XmFocusIsInShell(Widget wid)
2706 {
2707 XmFocusData fd;
2708 Window fw;
2709 int revert;
2710 Widget w;
2711
2712 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmFocusIsInShell\n"));
2713
2714 wid = _XmFindTopMostShell(wid);
2715
2716 if (XtIsSubclass(wid, vendorShellWidgetClass))
2717 {
2718 fd = _XmGetFocusData(wid);
2719 if (fd)
2720 {
2721 if (fd->focal_point == XmNO_RELATION)
2722 {
2723 return False;
2724 }
2725 else
2726 {
2727 return True;
2728 }
2729 }
2730 }
2731
2732 XGetInputFocus(XtDisplay(wid), &fw, &revert);
2733 if (fw == PointerRoot)
2734 return False;
2735
2736 if (fw == None)
2737 {
2738 return False;
2739 }
2740
2741 w = XtWindowToWidget(XtDisplay(wid), fw);
2742 if (w == NULL)
2743 {
2744 return False;
2745 }
2746
2747 w = _XmFindTopMostShell(w);
2748
2749 if (wid == w)
2750 {
2751 return True;
2752 }
2753
2754 return False;
2755 }
2756
2757
2758 extern Boolean
_XmShellIsExclusive(Widget wid)2759 _XmShellIsExclusive(Widget wid)
2760 {
2761 XmFocusData fd = _XmGetFocusData(wid);
2762
2763 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmShellIsExclusive\n"));
2764
2765 if (!fd)
2766 {
2767 return False;
2768 }
2769
2770 DEBUGOUT(_LtDebug(__FILE__, wid,
2771 "XmShell is eclusive: %d\n", fd->tree.num_excls));
2772
2773 if (fd->tree.num_excls != 0)
2774 {
2775 return True;
2776 }
2777
2778 return False;
2779 }
2780
2781
2782 extern Boolean
_XmGrabTheFocus(Widget w,XEvent * event)2783 _XmGrabTheFocus(Widget w,
2784 XEvent *event)
2785 {
2786 DEBUGOUT(_LtDebug(__FILE__, w, "_XmGrabTheFocus\n"));
2787
2788 return _XmMgrTraversal(w, XmTRAVERSE_CURRENT);
2789 }
2790
2791
2792 extern Widget
_XmTraverse(XmTravTree tree,XmTraversalDirection dir,Widget w)2793 _XmTraverse(XmTravTree tree, XmTraversalDirection dir, Widget w)
2794 {
2795 XmNavigability nv;
2796 XmTravTreeNode nd;
2797
2798 DEBUGOUT(_LtDebug(__FILE__, w, "_XmTraverse\n"));
2799
2800 if (dir == XmTRAVERSE_CURRENT && w != NULL)
2801 {
2802 nv = _XmGetNavigability(w);
2803 if ((nv == XmTAB_NAVIGABLE || nv == XmCONTROL_NAVIGABLE)
2804 && XmIsTraversable(w))
2805 {
2806 return w;
2807 }
2808
2809 return NULL;
2810 }
2811
2812 if (tree->num_entries == 0)
2813 {
2814 if (!_XmNewTravGraph(tree, tree->shell, w))
2815 {
2816 return NULL;
2817 }
2818 }
2819 else
2820 {
2821 if (!InitializeCurrent(tree, w, True))
2822 {
2823 return NULL;
2824 }
2825 }
2826
2827 if (dir == XmTRAVERSE_CURRENT)
2828 {
2829 if (tree->current->widget != w)
2830 {
2831 return NULL;
2832 }
2833
2834 if (tree->current->type == XmTAB_NODE ||
2835 tree->current->type == XmCONTROL_NODE)
2836 {
2837 if (NodeIsTraversable(tree->current))
2838 {
2839 return w;
2840 }
2841 else
2842 {
2843 return NULL;
2844 }
2845 }
2846 }
2847
2848 if (dir == XmTRAVERSE_NEXT_TAB_GROUP || dir == XmTRAVERSE_PREV_TAB_GROUP)
2849 {
2850 DEBUGOUT(_LtDebug(__FILE__, w,
2851 "_XmTraverseAway: call TraverseTab(%d GROUP)\n",
2852 dir));
2853
2854 nd = TraverseTab(tree->current, dir);
2855 }
2856 else
2857 {
2858 if (dir != XmTRAVERSE_CURRENT ||
2859 tree->current->type == XmCONTROL_TREE_NODE)
2860 {
2861 DEBUGOUT(_LtDebug(__FILE__, w,
2862 "_XmTraverseAway: call TraverseControl(%d)\n",
2863 dir));
2864
2865 nd = TraverseControl(tree->current, dir);
2866 }
2867 else
2868 {
2869 DEBUGOUT(_LtDebug(__FILE__, w,
2870 "_XmTraverseAway: call TraverseTab(%d)\n",
2871 dir));
2872
2873 nd = TraverseTab(tree->current, dir);
2874 }
2875 }
2876
2877 if (nd)
2878 {
2879 tree->current = nd;
2880 return nd->widget;
2881 }
2882
2883 return NULL;
2884 }
2885
2886
2887 extern Widget
_XmTraverseAway(XmTravTree tree,Widget w,Boolean control)2888 _XmTraverseAway(XmTravTree tree, Widget w, Boolean control)
2889 {
2890 XmTravTreeNode node = NULL;
2891 XRectangle rect;
2892
2893 DEBUGOUT(_LtDebug(__FILE__, w, "_XmTraverseAway\n"));
2894
2895 if (tree->num_entries == 0)
2896 {
2897 if (!_XmNewTravGraph(tree, tree->shell, w))
2898 {
2899 return NULL;
2900 }
2901
2902 if (!InitializeCurrent(tree, w, True))
2903 {
2904 return NULL;
2905 }
2906 }
2907
2908 if (tree->current->widget != w && tree->current->type == XmTAB_TREE_NODE)
2909 {
2910 if (control)
2911 {
2912 tree->current++;
2913 }
2914
2915 GetRectRelativeToShell(w, &rect);
2916 node = GetNextNearestNode(tree->current, &rect);
2917
2918 if (node)
2919 {
2920 tree->current = node;
2921 }
2922 }
2923
2924 if (tree->current->widget == w || NodeIsTraversable(tree->current))
2925 {
2926
2927 node = NULL;
2928
2929 if (tree->current->type == XmCONTROL_NODE ||
2930 tree->current->type == XmCONTROL_TREE_NODE)
2931 {
2932 DEBUGOUT(_LtDebug(__FILE__, w,
2933 "_XmTraverse: call TraverseControl(RIGHT)\n"));
2934
2935 node = TraverseControl(tree->current, XmTRAVERSE_RIGHT);
2936 }
2937
2938 if (!node)
2939 {
2940 DEBUGOUT(_LtDebug(__FILE__, w,
2941 "_XmTraverseAway: call TraverseTab\n"));
2942
2943 node = TraverseTab(tree->current, XmTRAVERSE_NEXT_TAB_GROUP);
2944 }
2945
2946 tree->current = node;
2947 }
2948
2949 if (tree->current && tree->current->widget == w)
2950 {
2951 return tree->current->widget;
2952 }
2953
2954 return NULL;
2955 }
2956
2957
2958 extern Boolean
_XmMgrTraversal(Widget widget,XmTraversalDirection direction)2959 _XmMgrTraversal(Widget widget, XmTraversalDirection direction)
2960 {
2961 Widget shell = _XmFindTopMostShell(widget);
2962 Widget tg, cur_focus;
2963 XmFocusData fd;
2964 static Boolean in_traversal = False;
2965 Boolean ret = False;
2966
2967 shell = _XmFindTopMostShell(widget);
2968 DEBUGOUT(_LtDebug(__FILE__, widget, "_XmMgrTraversal\n"));
2969
2970 if (in_traversal)
2971 {
2972 DEBUGOUT(_LtDebug(__FILE__, widget,
2973 "_XmMgrTraversal: InTraversal already\n"));
2974 return False;
2975 }
2976
2977 if (shell == NULL)
2978 {
2979 DEBUGOUT(_LtDebug(__FILE__, widget, "_XmMgrTraversal: NoShell\n"));
2980 return False;
2981 }
2982
2983 if (CoreBeingDestroyed(shell))
2984 {
2985 DEBUGOUT(_LtDebug(__FILE__, widget,
2986 "_XmMgrTraversal: BeingDestroyed\n"));
2987 return False;
2988 }
2989
2990 if ((fd = _XmGetFocusData(shell)) == NULL)
2991 {
2992 DEBUGOUT(_LtDebug(__FILE__, widget, "_XmMgrTraversal: NoFocusData\n"));
2993 return False;
2994 }
2995
2996 if (fd->focus_policy != XmEXPLICIT)
2997 {
2998 DEBUGOUT(_LtDebug(__FILE__, widget, "_XmMgrTraversal: NotExplicit\n"));
2999 return False;
3000 }
3001
3002 in_traversal = True;
3003
3004 cur_focus = fd->focus_item;
3005
3006 if (cur_focus == NULL && widget == shell && fd->first_focus != NULL
3007 && _XmIsTraversable(fd->first_focus, True))
3008 {
3009 DEBUGOUT(_LtDebug(__FILE__, widget, "_XmMgrTraversal: first_focus\n"));
3010 widget = fd->first_focus;
3011 }
3012 else
3013 {
3014 Widget ow = widget;
3015 widget = _XmTraverse(&fd->tree, direction, widget);
3016 DEBUGOUT(_LtDebug2(__FILE__, ow, widget, "_XmMgrTraversal: _XmTraverse\n"));
3017 if (widget && shell != _XmFindTopMostShell(widget))
3018 {
3019 /* FIX ME */
3020 _XmWarning(shell, "%s:_XmMgrTraversal(%d) - I just Traversed into a different shell!!!", __FILE__, __LINE__);
3021 widget = NULL;
3022 }
3023 }
3024
3025 if (widget == NULL || widget != cur_focus || fd->old_focus_item == NULL)
3026 {
3027
3028 if (widget != NULL && ((tg = XmGetTabGroup(widget)) != NULL) &&
3029 _XmCallFocusMoved(cur_focus, widget, NULL) &&
3030 _XmCallTraverseObscured(widget, direction))
3031 {
3032
3033 _XmSetFocusResetFlag(shell, True);
3034
3035 XtSetKeyboardFocus(shell, NULL);
3036
3037 _XmSetFocusResetFlag(shell, False);
3038
3039 _XmClearFocusPath(cur_focus);
3040
3041 fd->active_tab_group = tg;
3042 if (widget != tg && XmIsManager(tg))
3043 {
3044 MGR_ActiveChild(tg) = widget;
3045 }
3046
3047 if (XtParent(widget) != tg)
3048 {
3049 if (XmIsManager(XtParent(widget)))
3050 MGR_ActiveChild(XtParent(widget)) = widget;
3051 }
3052
3053 if (cur_focus == NULL)
3054 {
3055 cur_focus = widget;
3056 }
3057
3058 fd->focus_item = widget;
3059 fd->old_focus_item = cur_focus;
3060
3061 #if defined(DEBUG)
3062 if (strcmp(XtName(shell), "mgdiff") == 0 &&
3063 strcmp(XtName(widget), "Text") == 0)
3064 {
3065 Widget tmp = widget;
3066
3067 printf("%s %d\n", __FILE__, __LINE__);
3068 while (tmp != NULL)
3069 {
3070 printf("%s %s %s\n",
3071 XtName(tmp),
3072 XtClass(tmp)->core_class.class_name,
3073 _XmFindTopMostShell(tmp) ? XtName(_XmFindTopMostShell(tmp)) : "NULL"
3074 );
3075 tmp = XtParent(tmp);
3076 }
3077 }
3078 #endif /* DEBUG */
3079 DEBUGOUT(_LtDebug("RWS1", shell,
3080 "KeyboardFocus set to %s %s %p\n",
3081 shell ? XtName(shell) : "(null)",
3082 widget ? XtName(widget) : "(null)",
3083 widget));
3084 DEBUGOUT(_LtDebug(__FILE__, shell,
3085 "KeyboardFocus set to %s %s\n",
3086 shell ? XtName(shell) : "(null)",
3087 widget ? XtName(widget) : "(null)"));
3088
3089 XtSetKeyboardFocus(shell, widget);
3090
3091 ret = True;
3092 }
3093 else if (!_XmIsTraversable(cur_focus, True))
3094 {
3095
3096 widget = FindFirstManaged(shell);
3097
3098 _XmSetFocusResetFlag(shell, True);
3099
3100 DEBUGOUT(_LtDebug2(__FILE__, shell, widget,
3101 "XtSetKeyboardFocus -> child\n"));
3102
3103 XtSetKeyboardFocus(shell, widget);
3104
3105 _XmSetFocusResetFlag(shell, False);
3106
3107 _XmClearFocusPath(cur_focus);
3108
3109 _XmFreeTravGraph(&fd->tree);
3110 }
3111 }
3112 else
3113 {
3114 ret = True;
3115 }
3116
3117 if (fd->tree.num_entries != 0 && fd->focal_point == XmNO_RELATION)
3118 {
3119 if (XtIsSubclass(shell, vendorShellWidgetClass)
3120 && _XmFocusIsInShell(shell))
3121 {
3122 _XmFreeTravGraph(&fd->tree);
3123 }
3124 }
3125
3126 in_traversal = False;
3127
3128 return ret;
3129 }
3130
3131
3132 extern void
_XmProcessTraversal(Widget widget,XmTraversalDirection direction,Boolean check)3133 _XmProcessTraversal(Widget widget,
3134 XmTraversalDirection direction,
3135 Boolean check)
3136 {
3137 DEBUGOUT(_LtDebug(__FILE__, widget, "_XmProcessTraversal\n"));
3138
3139 _XmMgrTraversal(widget, direction);
3140 }
3141
3142
3143 extern Widget
_XmNavigate(Widget wid,XmTraversalDirection direction)3144 _XmNavigate(Widget wid,
3145 XmTraversalDirection direction)
3146 {
3147 Widget shell = _XmFindTopMostShell(wid), ret;
3148 XmFocusData fd = _XmGetFocusData(shell);
3149
3150 if (fd == NULL)
3151 {
3152 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmNavigate (fd NULL) => NULL\n"));
3153 return NULL;
3154 }
3155
3156 if (fd->focus_policy != XmEXPLICIT)
3157 {
3158 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmNavigate (fp != explicit) => NULL\n"));
3159 return NULL;
3160 }
3161
3162 ret = _XmTraverse(&fd->tree, direction, wid);
3163
3164 if (fd->tree.num_entries == 0)
3165 {
3166 DEBUGOUT(_LtDebug2(__FILE__, wid, ret, "_XmNavigate (#entries == 0)\n"));
3167 return ret;
3168 }
3169
3170 if (fd->focal_point != XmNO_RELATION)
3171 {
3172 DEBUGOUT(_LtDebug2(__FILE__, wid, ret, "_XmNavigate (NO_RELATION)\n"));
3173 return ret;
3174 }
3175
3176 if (XtIsSubclass(shell, vendorShellWidgetClass) &&
3177 _XmFocusIsInShell(shell))
3178 {
3179 _XmFreeTravGraph(&fd->tree);
3180 }
3181
3182 return ret;
3183 }
3184
3185
3186 extern Widget
_XmGetFirstFocus(Widget wid)3187 _XmGetFirstFocus(Widget wid)
3188 {
3189 XmFocusData fd;
3190 Widget hierarchy;
3191
3192 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmGetFirstFocus\n"));
3193
3194 fd = _XmGetFocusData(wid);
3195
3196 if (fd == NULL)
3197 {
3198 return NULL;
3199 }
3200
3201 if (fd->focus_item)
3202 {
3203 return fd->focus_item;
3204 }
3205
3206 if (fd->first_focus)
3207 {
3208 return fd->first_focus;
3209 }
3210
3211 hierarchy = _XmFindTopMostShell(wid);
3212
3213 fd->first_focus = _XmNavigate(hierarchy, XmTRAVERSE_CURRENT);
3214
3215 return fd->first_focus;
3216 }
3217
3218 /************************* method functions *****************************/
3219
3220
3221 extern void
_XmNavigInitialize(Widget request,Widget new_wid,ArgList args,Cardinal * num_args)3222 _XmNavigInitialize(Widget request,
3223 Widget new_wid,
3224 ArgList args,
3225 Cardinal *num_args)
3226 {
3227 XmFocusData fd;
3228 XmNavigationType nt = _XmGetNavigationType(new_wid);
3229
3230 DEBUGOUT(_LtDebug("RWS", new_wid, "_XmNavigInitialize\n"));
3231 DEBUGOUT(_LtDebug(__FILE__, new_wid, "_XmNavigInitialize\n"));
3232
3233 fd = _XmGetFocusData(new_wid);
3234 if (fd == NULL)
3235 {
3236 DEBUGOUT(_LtDebug(__FILE__, new_wid,
3237 "_XmNavigInitialize : NULL FocusData\n"));
3238 return;
3239 }
3240
3241 DEBUGOUT(_LtDebug(__FILE__, new_wid,
3242 "_XmNavigInitialize, navigation type %s\n",
3243 _LtDebugNavigationType2String(nt)));
3244
3245 if (nt == XmEXCLUSIVE_TAB_GROUP)
3246 {
3247 fd->tree.num_excls++;
3248 }
3249
3250 if (nt == XmEXCLUSIVE_TAB_GROUP || nt == XmSTICKY_TAB_GROUP)
3251 {
3252 _XmTabListAdd(&fd->tree, new_wid);
3253 }
3254
3255 if (fd->tree.num_entries != 0 &&
3256 _XmGetNavigability(new_wid) != XmNOT_NAVIGABLE)
3257 {
3258 _XmTravGraphAdd(&fd->tree, new_wid);
3259 }
3260 }
3261
3262
3263 extern Boolean
_XmNavigSetValues(Widget current,Widget request,Widget new_wid,ArgList args,Cardinal * num_args)3264 _XmNavigSetValues(Widget current,
3265 Widget request,
3266 Widget new_wid,
3267 ArgList args,
3268 Cardinal *num_args)
3269 {
3270 XmFocusData fd = _XmGetFocusData(new_wid);
3271 XmNavigationType cur_nt, new_nt;
3272 XmNavigability cur_nav, new_nav;
3273 Boolean tchange = False;
3274 Widget tmp;
3275
3276 DEBUGOUT(_LtDebug(__FILE__, new_wid, "_XmNavigSetValues\n"));
3277
3278 if (!fd)
3279 {
3280 return False;
3281 }
3282
3283 new_nt = _XmGetNavigationType(new_wid);
3284 cur_nt = _XmGetNavigationType(current);
3285
3286 if (cur_nt != new_nt)
3287 {
3288 if (cur_nt == XmEXCLUSIVE_TAB_GROUP &&
3289 new_nt != XmEXCLUSIVE_TAB_GROUP)
3290 {
3291 tchange = True;
3292 fd->tree.num_excls--;
3293 }
3294 else if (cur_nt != XmEXCLUSIVE_TAB_GROUP &&
3295 new_nt == XmEXCLUSIVE_TAB_GROUP)
3296 {
3297 tchange = True;
3298 fd->tree.num_excls++;
3299 }
3300 }
3301
3302 if (new_nt == XmEXCLUSIVE_TAB_GROUP || new_nt == XmSTICKY_TAB_GROUP)
3303 {
3304 if (cur_nt != XmEXCLUSIVE_TAB_GROUP && cur_nt != XmSTICKY_TAB_GROUP)
3305 {
3306 _XmTabListAdd(&fd->tree, new_wid);
3307 }
3308 }
3309 else
3310 {
3311 if (cur_nt == XmEXCLUSIVE_TAB_GROUP && cur_nt == XmSTICKY_TAB_GROUP)
3312 {
3313 _XmTabListDelete(&fd->tree, new_wid);
3314 }
3315 }
3316
3317 if (!XtIsRealized(new_wid))
3318 {
3319 return False;
3320 }
3321
3322 if (fd->focus_policy != XmEXPLICIT)
3323 {
3324 return False;
3325 }
3326
3327 if (fd->tree.num_entries != 0)
3328 {
3329 new_nav = _XmGetNavigability(new_wid);
3330 cur_nav = _XmGetNavigability(current);
3331 if (!tchange)
3332 {
3333 if (cur_nav == XmNOT_NAVIGABLE && new_nav != XmNOT_NAVIGABLE)
3334 {
3335 _XmTravGraphAdd(&fd->tree, new_wid);
3336 }
3337 }
3338 if (tchange || cur_nav != new_nav)
3339 {
3340 _XmFreeTravGraph(&fd->tree);
3341 }
3342 }
3343
3344 if (fd->focus_item == NULL)
3345 {
3346 if (!XmIsTraversable(new_wid))
3347 {
3348 return False;
3349 }
3350
3351 tmp = _XmFindTopMostShell(new_wid);
3352 if (!tmp)
3353 {
3354 return False;
3355 }
3356
3357 if (!_XmFocusIsInShell(tmp))
3358 {
3359 return False;
3360 }
3361
3362 if (fd->focal_point == XmME)
3363 {
3364 return False;
3365 }
3366
3367 _XmMgrTraversal(new_wid, XmTRAVERSE_CURRENT);
3368
3369 return False;
3370 }
3371
3372 if (fd->focus_item != new_wid)
3373 {
3374 return False;
3375 }
3376
3377 if (_XmIsTraversable(new_wid, True))
3378 {
3379 return False;
3380 }
3381
3382 if (fd->active_tab_group == new_wid)
3383 {
3384 tchange = False;
3385 }
3386 else
3387 {
3388 tchange = True;
3389 }
3390
3391 tmp = _XmTraverseAway(&fd->tree, new_wid, tchange);
3392
3393 if (tmp == NULL)
3394 {
3395 tmp = new_wid;
3396 }
3397
3398 _XmMgrTraversal(tmp, XmTRAVERSE_CURRENT);
3399
3400 if (!XtSensitive(new_wid))
3401 {
3402 _XmWidgetFocusChange(new_wid, XmFOCUS_OUT);
3403 }
3404
3405 return True;
3406 }
3407
3408
3409 extern void
_XmNavigChangeManaged(Widget w)3410 _XmNavigChangeManaged(Widget w)
3411 {
3412 XmFocusData fd;
3413 Widget tmp;
3414
3415 DEBUGOUT(_LtDebug(__FILE__, w, "_XmNavigChangeManaged\n"));
3416
3417 if (!XtIsRealized(w))
3418 {
3419 return;
3420 }
3421
3422 if ((fd = _XmGetFocusData(w)) == NULL)
3423 {
3424 return;
3425 }
3426
3427 if (fd->focus_policy != XmEXPLICIT)
3428 {
3429 return;
3430 }
3431
3432 if (fd->focus_item == NULL)
3433 {
3434 if (!XtIsRectObj(w))
3435 {
3436 return;
3437 }
3438
3439 if (fd->first_focus == NULL)
3440 {
3441 fd->first_focus = FindFirstFocus(w);
3442 }
3443
3444 if ((tmp = FindFirstManaged(w)) == NULL)
3445 {
3446 return;
3447 }
3448
3449 XtSetKeyboardFocus(w, tmp);
3450
3451 return;
3452 }
3453
3454 if (CoreBeingDestroyed(fd->focus_item))
3455 {
3456 return;
3457 }
3458
3459 if (_XmIsTraversable(fd->focus_item, True))
3460 {
3461 return;
3462 }
3463
3464 if (fd->focus_item == fd->active_tab_group)
3465 {
3466 tmp = _XmTraverseAway(&fd->tree, fd->focus_item, False);
3467 }
3468 else
3469 {
3470 tmp = _XmTraverseAway(&fd->tree, fd->focus_item, True);
3471 }
3472
3473 if (tmp == NULL)
3474 {
3475 tmp = fd->focus_item;
3476 }
3477
3478 _XmMgrTraversal(tmp, XmTRAVERSE_CURRENT);
3479 }
3480
3481
3482 extern void
_XmNavigResize(Widget wid)3483 _XmNavigResize(Widget wid)
3484 {
3485 XmFocusData fd;
3486 Widget tmp;
3487
3488 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmNavigResize\n"));
3489
3490 if (!XtIsRealized(wid))
3491 {
3492 return;
3493 }
3494
3495 if (XtIsRectObj(wid))
3496 {
3497 return;
3498 }
3499
3500 if ((fd = _XmGetFocusData(wid)) == NULL)
3501 {
3502 return;
3503 }
3504
3505 if (fd->focus_policy != XmEXPLICIT)
3506 {
3507 return;
3508 }
3509
3510 if (fd->focus_item != NULL)
3511 {
3512 if (CoreBeingDestroyed(fd->focus_item))
3513 {
3514 return;
3515 }
3516 }
3517
3518 if (fd->focus_item == NULL)
3519 {
3520 if (XtParent(wid) == NULL)
3521 {
3522 return;
3523 }
3524
3525 if ((tmp = FindFirstManaged(wid)) == NULL)
3526 {
3527 return;
3528 }
3529
3530 XtSetKeyboardFocus(wid, tmp);
3531
3532 return;
3533 }
3534
3535 if (_XmIsTraversable(fd->focus_item, True))
3536 {
3537 return;
3538 }
3539
3540 if (_XmIsTraversable(fd->focus_item, False))
3541 {
3542 if (_XmMgrTraversal(fd->focus_item, XmTRAVERSE_CURRENT))
3543 {
3544 return;
3545 }
3546 }
3547
3548 if (fd->focus_item == fd->active_tab_group)
3549 {
3550 tmp = _XmTraverseAway(&fd->tree, fd->focus_item, False);
3551 }
3552 else
3553 {
3554 tmp = _XmTraverseAway(&fd->tree, fd->focus_item, True);
3555 }
3556
3557 if (tmp == NULL)
3558 {
3559 tmp = fd->focus_item;
3560 }
3561
3562 _XmMgrTraversal(tmp, XmTRAVERSE_CURRENT);
3563 }
3564
3565
3566 extern void
_XmNavigDestroy(Widget wid)3567 _XmNavigDestroy(Widget wid)
3568 {
3569 XmFocusData fd = _XmGetFocusData(wid);
3570 XmNavigationType nt;
3571 Widget tmp, shell;
3572
3573 DEBUGOUT(_LtDebug("RWS", wid, "_XmNavigDestroy\n"));
3574 DEBUGOUT(_LtDebug(__FILE__, wid, "_XmNavigDestroy\n"));
3575
3576 if (!fd)
3577 {
3578 return;
3579 }
3580 DEBUGOUT(_LtDebug("RWS", wid, "_XmNavigDestroy %s\n",
3581 fd->focus_item ? XtName(fd->focus_item) : "NULL"
3582 ));
3583
3584 if (fd->first_focus == wid)
3585 {
3586 fd->first_focus = NULL;
3587 }
3588
3589 nt = _XmGetNavigationType(wid);
3590
3591 if (nt == XmEXCLUSIVE_TAB_GROUP || nt == XmSTICKY_TAB_GROUP)
3592 {
3593 if (nt == XmEXCLUSIVE_TAB_GROUP)
3594 {
3595 fd->tree.num_excls--;
3596 }
3597 _XmTabListDelete(&fd->tree, wid);
3598 }
3599
3600 if (fd->focus_item == wid)
3601 {
3602 if (fd->focus_policy != XmEXPLICIT)
3603 {
3604 fd->focus_item = NULL;
3605 }
3606 else
3607 {
3608 if (wid == fd->active_tab_group)
3609 {
3610 tmp = _XmTraverseAway(&fd->tree, fd->focus_item, False);
3611 }
3612 else
3613 {
3614 tmp = _XmTraverseAway(&fd->tree, fd->focus_item, True);
3615 }
3616
3617 if (tmp && (shell = _XmFindTopMostShell(wid)))
3618 {
3619 if (!_XmMgrTraversal(shell, XmTRAVERSE_CURRENT))
3620 {
3621 fd->focus_item = NULL;
3622 }
3623 }
3624 else
3625 {
3626 fd->focus_item = NULL;
3627 }
3628 }
3629 DEBUGOUT(_LtDebug("RWS", wid, "_XmNavigDestroy %s\n",
3630 fd->focus_item ? XtName(fd->focus_item) : "NULL"
3631 ));
3632 }
3633
3634 if (fd->tree.num_entries != 0)
3635 {
3636 _XmTravGraphRemove(&fd->tree, wid);
3637 }
3638
3639 if (fd->active_tab_group == wid)
3640 {
3641 fd->active_tab_group = NULL;
3642 }
3643
3644 if (fd->old_focus_item == wid)
3645 {
3646 fd->old_focus_item = NULL;
3647 }
3648
3649 if (fd->pointer_item == wid)
3650 {
3651 fd->pointer_item = NULL;
3652 }
3653 }
3654
3655 /************************ EXPORTED FUNCTIONS ************************/
3656 extern void
XmAddTabGroup(Widget tab_group)3657 XmAddTabGroup(Widget tab_group)
3658 {
3659 Arg args[1];
3660
3661 DEBUGOUT(_LtDebug(__FILE__, tab_group, "XmAddTabGroup\n"));
3662
3663 XtSetArg(args[0], XmNnavigationType, XmEXCLUSIVE_TAB_GROUP);
3664 XtSetValues(tab_group, args, 1);
3665 }
3666
3667
3668 extern void
XmRemoveTabGroup(Widget tab_group)3669 XmRemoveTabGroup(Widget tab_group)
3670 {
3671 Arg args[1];
3672
3673 DEBUGOUT(_LtDebug(__FILE__, tab_group, "XmRemoveTabGroup\n"));
3674
3675 XtSetArg(args[0], XmNnavigationType, XmNONE);
3676 XtSetValues(tab_group, args, 1);
3677 }
3678
3679
3680 extern Widget
XmGetTabGroup(Widget widget)3681 XmGetTabGroup(Widget widget)
3682 {
3683 XmFocusData fd;
3684 XmNavigationType nt;
3685 Boolean loop;
3686
3687 DEBUGOUT(_LtDebug(__FILE__, widget, "XmGetTabGroup\n"));
3688
3689 if (!widget)
3690 {
3691 return NULL;
3692 }
3693
3694 if (_XmGetFocusPolicy(widget) != XmEXPLICIT)
3695 {
3696 return NULL;
3697 }
3698
3699 fd = _XmGetFocusData(widget);
3700
3701 if (!fd)
3702 {
3703 return NULL;
3704 }
3705
3706 if (fd->tree.num_excls == 0)
3707 {
3708 loop = False;
3709 }
3710 else
3711 {
3712 loop = True;
3713 }
3714
3715 for (;;)
3716 {
3717 nt = _XmGetNavigationType(widget);
3718
3719 if (nt == XmSTICKY_TAB_GROUP || nt == XmEXCLUSIVE_TAB_GROUP)
3720 {
3721 return widget;
3722 }
3723
3724 if (nt == XmTAB_GROUP && !loop)
3725 {
3726 return widget;
3727 }
3728 else
3729 {
3730 widget = XtParent(widget);
3731 }
3732
3733 if (XtIsShell(widget))
3734 {
3735 break;
3736 }
3737 }
3738 return widget;
3739 }
3740
3741
3742 extern Boolean
XmProcessTraversal(Widget widget,XmTraversalDirection direction)3743 XmProcessTraversal(Widget widget, XmTraversalDirection direction)
3744 {
3745 Widget shell = _XmFindTopMostShell(widget);
3746 Widget ve;
3747
3748 DEBUGOUT(_LtDebug(__FILE__, widget, "XmProcessTraversal\n"));
3749
3750 ve = _LtFindVendorExt(shell);
3751
3752 if (!ve) {
3753 return False;
3754 }
3755
3756 if (VSEP_FocusPolicy(ve) != XmEXPLICIT) {
3757 return False;
3758 }
3759
3760 return _XmMgrTraversal(widget, direction);
3761 }
3762
3763
3764 extern Widget
XmGetFocusWidget(Widget widget)3765 XmGetFocusWidget(Widget widget)
3766 {
3767 XmFocusData fd = _XmGetFocusData(widget);
3768 Widget w;
3769
3770 DEBUGOUT(_LtDebug(__FILE__, widget, "XmGetFocusWidget\n"));
3771
3772 if (!fd)
3773 {
3774 return NULL;
3775 }
3776
3777 if (fd->focus_policy == XmEXPLICIT)
3778 {
3779 w = fd->focus_item;
3780 }
3781 else
3782 {
3783 w = fd->pointer_item;
3784 }
3785
3786 if (w == NULL)
3787 {
3788 return NULL;
3789 }
3790
3791 if (XmIsManager(w) && MGR_HighlightedWidget(w))
3792 {
3793 return MGR_HighlightedWidget(w);
3794 }
3795
3796 return w;
3797 }
3798
3799
3800 extern Boolean
XmIsTraversable(Widget widget)3801 XmIsTraversable(Widget widget)
3802 {
3803 DEBUGOUT(_LtDebug(__FILE__, widget, "XmIsTraversable\n"));
3804
3805 return _XmIsTraversable(widget, False);
3806 }
3807
3808
3809 extern XmVisibility
XmGetVisibility(Widget widget)3810 XmGetVisibility(Widget widget)
3811 {
3812 XRectangle rect;
3813
3814 DEBUGOUT(_LtDebug(__FILE__, widget, "XmGetVisibility\n"));
3815
3816 if (!widget)
3817 {
3818 return XmVISIBILITY_FULLY_OBSCURED;
3819 }
3820
3821 if (!_XmCreateVisibilityRect(widget, &rect))
3822 {
3823 return XmVISIBILITY_FULLY_OBSCURED;
3824 }
3825
3826 if (XtWidth(widget) != rect.width || XtHeight(widget) != rect.height)
3827 {
3828 return XmVISIBILITY_PARTIALLY_OBSCURED;
3829 }
3830
3831 return XmVISIBILITY_UNOBSCURED;
3832 }
3833