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