7e12b9832fce50357416b42c1ccfe7a2dec9da50
[oweals/cde.git] / cde / lib / DtHelp / SetList.c
1 /* $XConsortium: SetList.c /main/16 1996/11/18 16:35:22 cde-hp $ */
2 /************************************<+>*************************************
3  ****************************************************************************
4  **
5  **   File:     SetList.c
6  **
7  **   Project:     Text Graphic Display Library
8  **
9  **   Description: This body of code creates the Line and Graphic Tables for
10  **             a Display Area.
11  **
12  **
13  ****************************************************************************
14  ************************************<+>*************************************/
15 /*
16  * (c) Copyright 1996 Digital Equipment Corporation.
17  * (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992,
18                  1993, 1994, 1996 Hewlett-Packard Company.
19  * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
20  * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
21  * (c) Copyright 1993, 1994, 1996 Novell, Inc. 
22  * (c) Copyright 1996 FUJITSU LIMITED.
23  * (c) Copyright 1996 Hitachi.
24  */
25
26 /*
27  * system includes
28  */
29 #include <string.h>
30 #include <stdlib.h>
31 #include <X11/Xlib.h>
32
33
34 /*
35  * Canvas Engine
36  */
37 #include "CanvasP.h"
38 #include "CanvasSegP.h"
39
40 /*
41  * private includes
42  */
43 #include "Access.h"
44 #include "CleanUpI.h"
45 #include "DisplayAreaP.h"
46 #include "CallbacksI.h"
47 #include "FontAttrI.h"
48 #include "SetListI.h"
49 #include "XInterfaceI.h"
50 #include "XUICreateI.h"
51
52 #ifdef NLS16
53 #include <nl_types.h>
54 #endif
55
56 /********    Private Function Declarations    ********/
57 /********    End Public Function Declarations    ********/
58
59 /******************************************************************************
60  *
61  * Private defines and variables
62  *
63  *****************************************************************************/
64
65 #define GROW_SIZE       10
66 #define ALL_LINES       -1
67
68 /******************************************************************************
69  *
70  * Private Macros
71  *
72  *****************************************************************************/
73 #define NeedVertScrollbar(x) \
74         _DtHelpIS_AS_NEEDED((x)->neededFlags,_DtHelpVERTICAL_SCROLLBAR)
75 #define NeedHorzScrollbar(x) \
76         _DtHelpIS_AS_NEEDED((x)->neededFlags,_DtHelpHORIZONTAL_SCROLLBAR)
77 /******************************************************************************
78  *
79  * Private Functions
80  *
81  *****************************************************************************/
82 static void
83 SetMaxPositions (
84         DtHelpDispAreaStruct    *pDAS,
85         _DtCvUnit        max_x,
86         _DtCvUnit        max_y)
87 {
88     pDAS->maxX    = max_x;
89     pDAS->maxYpos = max_y + pDAS->marginHeight;
90 }
91
92 /******************************************************************************
93  *
94  * Semi Public Functions - these routines called by other modules within
95  *                         the library.
96  *
97  *****************************************************************************/
98 /******************************************************************************
99  * Function: _DtHelpSetScrollBars
100  *
101  * Sets/Resets the vertical scroll bar values.
102  *****************************************************************************/
103 enum   DoSomething  { DoNothing, DoManage, DoUnmanage };
104 Boolean
105 _DtHelpSetScrollBars (
106         XtPointer       client_data,
107         Dimension        new_width,
108         Dimension        new_height)
109 {
110     int    n = 0;
111     int    dispN = 0;
112
113     int    changeWidth = 0;
114     int    changeHeight = 0;
115     int    oldMaxYpos;
116
117     int    slideSize;
118     int    maximum;
119     int    pageInc;
120     int    oldScrollPercent = 10000;
121
122     _DtCvUnit   ret_width;
123     _DtCvUnit   ret_height;
124
125     Arg    dispArgs[10];
126     Arg    args[10];
127
128     Dimension    marginWidth;
129     Dimension    marginHeight;
130     Dimension    horzHeight;
131     Dimension    vertWidth;
132     Dimension    oldHeight;
133     Dimension    oldWidth;
134
135     XRectangle   rectangle[1];
136
137     enum DoSomething doVert = DoNothing;
138     enum DoSomething doHorz = DoNothing;
139     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
140
141     /*
142      * remember the old first line.
143      */
144     oldMaxYpos = pDAS->maxYpos;
145     if (pDAS->firstVisible && pDAS->maxYpos)
146         oldScrollPercent = pDAS->firstVisible * 10000 / pDAS->maxYpos;
147
148     /*
149      * get the width and height of the scroll bars.
150      */
151     if (pDAS->vertScrollWid)
152       {
153         XtSetArg (args[0], XmNwidth , &vertWidth);
154         XtGetValues (pDAS->vertScrollWid, args, 1);
155       }
156
157     if (pDAS->horzScrollWid)
158       {
159         XtSetArg (args[0], XmNheight , &horzHeight);
160         XtGetValues (pDAS->horzScrollWid, args, 1);
161       }
162
163     /*
164      * remember our old width and height
165      */
166     oldWidth  = pDAS->dispWidth;
167     oldHeight = pDAS->dispHeight;
168
169     /*
170      * Settle the sizing issue before we remap the scroll bars.
171      */
172     do
173       {
174         /*
175          * set the height.
176          */
177         if (new_height != pDAS->dispHeight)
178           {
179             pDAS->dispHeight    = new_height;
180             pDAS->dispUseHeight = new_height - 2 * pDAS->decorThickness;
181             if (((int) new_height) < 2 * ((int) pDAS->decorThickness))
182                 pDAS->dispUseHeight = 0;
183
184             pDAS->visibleCount  = ((int) pDAS->dispUseHeight) /
185                                    pDAS->lineHeight;
186
187             if (pDAS->visibleCount < 0)
188                 pDAS->visibleCount = 0;
189           }
190
191         /*
192          * check to see if we've changed width
193          */
194         if (new_width != pDAS->dispWidth)
195           {
196             /*
197              * set the new width
198              */
199             pDAS->dispWidth    = new_width;
200             pDAS->dispUseWidth = new_width - 2 * pDAS->decorThickness;
201             if (((int)new_width) < 2 * ((int) pDAS->decorThickness))
202                 pDAS->dispUseWidth = 0;
203
204             /*
205              * re-layout the information.
206              */
207             if (_DtCvSTATUS_OK ==
208                         _DtCanvasResize(pDAS->canvas, _DtCvFALSE,
209                                                 &ret_width, &ret_height))
210                 SetMaxPositions (pDAS, ret_width, ret_height);
211
212           }
213
214         /*
215          * Check to see if we have a vertical scrollbar and whether it
216          * is as_needed.  If static, it is always mapped.
217          */
218         if (NULL != pDAS->vertScrollWid && NeedVertScrollbar(pDAS))
219           {
220             /*
221              * will the information fit on one page?
222              */
223             if (pDAS->maxYpos <= ((int) pDAS->dispUseHeight))
224               {
225                 /*
226                  * If the window has not already been 'stretched' by
227                  * the width of the scrollbar and if the scrollbar is
228                  * mapped, grow the window width.
229                  */
230                 if (0 == changeWidth && pDAS->vertIsMapped)
231                   {
232                     /*
233                      * set the flag to indicate that the window width
234                      * has grown. This can occur only if the window
235                      * has its vertical scrollbar already mapped.
236                      */
237                     changeWidth = 1;
238                     new_width += vertWidth;
239                   }
240                 /*
241                  * Else check to see if the window has been shrunk.
242                  * If so, then stretch it back out to its original
243                  * width.
244                  *
245                  * This can occur only if
246                  *    a) The vertical scrollbar is not mapped.
247                  *    b) The previous pass through this code indicates
248                  *       that the window could not hold the length of
249                  *       the information, and therefore calculations and
250                  *       flags were set to map the vertical scrollbar.
251                  *       But a _DtCanvasResize() now indicates that a
252                  *       vertical scrollbar is not needed.  So we don't
253                  *       need the vertical scrollbar and have to nuliify
254                  *       the calculation to include it.
255                  */
256                 else if (-1 == changeWidth)
257                   {
258                     changeWidth = 0;
259                     new_width += vertWidth;
260                   }
261               }
262             /*
263              * The information will not fit on one page.
264              */
265             else
266               {
267                 /*
268                  * If the window has not already been shrunk to
269                  * accomidate the vertical scrollbar (and the scrollbar
270                  * is not already mapped) then set the flags and
271                  * shrink the width.
272                  */
273                 if (False == pDAS->vertIsMapped && 0 == changeWidth)
274                   {
275                     /*
276                      * set the flag to indicate that the window width
277                      * has shrunk (and that consequently, the vertical
278                      * scrollbar is not mapped).
279                      */
280                     changeWidth = -1;
281                     if (new_width > vertWidth)
282                         new_width -= vertWidth;
283                     else
284                         new_width = 0;
285                   }
286                 /*
287                  * Else check to see if the window has been streched.
288                  * If so, then shrink it back out to its original
289                  * width.
290                  *
291                  * This can occur only if
292                  *    a) The vertical scrollbar is mapped.
293                  *    b) The previous pass through this code indicates
294                  *       that the window could hold the length of
295                  *       the information, and therefore calculations and
296                  *       flags were set to unmap the vertical scrollbar.
297                  *       But a _DtCanvasResize() now indicates that a
298                  *       vertical scrollbar is needed.  So we need
299                  *       the vertical scrollbar and have to nuliify
300                  *       the calculation to eliminate it.
301                  */
302                 else if (1 == changeWidth)
303                   {
304                     changeWidth = 0;
305                     new_width  -= vertWidth;
306                   }
307               }
308           }
309
310         /*
311          * Check to see if we have a horizontal scrollbar and whether it
312          * is as_needed.  If static, it is always mapped.
313          */
314         if (NULL != pDAS->horzScrollWid && NeedHorzScrollbar(pDAS))
315           {
316             /*
317              * will the information fit within the right border?
318              */
319             if (pDAS->maxX <= ((int) pDAS->dispUseWidth))
320               {
321                 /*
322                  * If the window has not already been 'stretched' by
323                  * the height of the scrollbar and if the scrollbar is
324                  * mapped, grow the window.
325                  */
326                 if (0 == changeHeight && pDAS->horzIsMapped)
327                   {
328                     /*
329                      * set the flag to indicate that the window has
330                      * grown. This can occur only if the window has
331                      * its horizontal scrollbar already mapped.
332                      */
333                     changeHeight = 1;
334                     new_height += horzHeight;
335                   }
336                 /*
337                  * Else check to see if the window has been shrunk.
338                  * If so, stretch it back to its original height.
339                  *
340                  * This can occur only if
341                  *   a) The horizontal scrollbar is not mapped.
342                  *   b) The previous pass through the code indicated
343                  *      that the information exceeded the right border
344                  *      and therefore calculations and flags were set
345                  *      to map the horizontal scrollbar. But a
346                  *      _DtCanvasResize() now indicates that the
347                  *      horizontal scrollbar is not needed. So we
348                  *      have to nullify the calculations and flags
349                  *      set to include it.
350                  */
351                 else if (-1 == changeHeight)
352                   {
353                     changeHeight = 0;
354                     new_height += horzHeight;
355                   }
356               }
357             /*
358              * The information exceeds the right border of the window.
359              */
360             else
361               {
362                 /*
363                  * If the window has no already been shrunk to
364                  * accomidate the horizontal scrollbar (and the
365                  * scrollbar is not already mapped), then set the
366                  * flags and shrink the height.
367                  */
368                 if (False == pDAS->horzIsMapped && 0 == changeHeight)
369                   {
370                     /*
371                      * set the flag to indicate that the window height
372                      * has shrunk (and that the scrollbar needs mapping).
373                      */
374                     changeHeight = -1;
375                     if (new_height > horzHeight)
376                         new_height -= horzHeight;
377                     else
378                         new_height = 0;
379                   }
380                 /*
381                  * Else check to see if the window has been streched.
382                  * If so, then shrink it back out to its original
383                  * height.
384                  *
385                  * This can occur only if
386                  *   a) The horizontal scrollbar is mapped.
387                  *   b) The previous pass through the code indicated
388                  *      that the information did not exceeded the right
389                  *      border and therefore calculations and flags were
390                  *      set to unmap the horizontal scrollbar. But a
391                  *      _DtCanvasResize() now indicates that the
392                  *      horizontal scrollbar is needed. So we
393                  *      have to nullify the calculations and flags
394                  *      set to exclude it.
395                  */
396                 else if (1 == changeHeight)
397                   {
398                     changeHeight = 0;
399                     new_height  -= horzHeight;
400                   }
401               }
402           }
403
404       } while (new_height != pDAS->dispHeight || new_width != pDAS->dispWidth);
405
406     /*
407      * reset the first visible line, if needed.
408      */
409     if (oldScrollPercent != 10000 && pDAS->maxYpos != oldMaxYpos)
410         pDAS->firstVisible = pDAS->maxYpos * oldScrollPercent / 10000;
411
412     if (pDAS->firstVisible + ((int)pDAS->dispUseHeight) > pDAS->maxYpos)
413         pDAS->firstVisible = pDAS->maxYpos - pDAS->dispUseHeight;
414
415     if (pDAS->firstVisible < 0)
416         pDAS->firstVisible = 0;
417
418     /*
419      * Reset the virtual X value, if needed
420      */
421     if (pDAS->virtualX &&
422                 (pDAS->maxX - pDAS->virtualX < ((int) pDAS->dispUseWidth)))
423       {
424         pDAS->virtualX = pDAS->maxX - pDAS->dispUseWidth;
425         if (pDAS->virtualX < 0)
426             pDAS->virtualX = 0;
427       }
428
429     /*
430      * If I've changed my size, I've got to change my clip masks.
431      */
432     if (oldWidth != pDAS->dispWidth || oldHeight != pDAS->dispHeight)
433       {
434         /*
435          * If the display area hasn't been realized, the resetting of
436          * the bottom right corner offsets will not cause a resize
437          * event to occur. Rather the overall window will grow by
438          * the width or height of the scroll bar and not cause the
439          * display area to shrink. Therefore when the exposure event
440          * is called the width or height will be not be equal to what
441          * I think it should be causing the code to believe a resize
442          * is in process. The short of the matter is that the exposure
443          * will not happen and we end up with a blank window.
444          *
445          * So for this case, resize the display area to what we think it
446          * should be and the exposure event will then happen.
447         if (!XtIsRealized (pDAS->dispWid))
448          */
449           {
450             XtSetArg(dispArgs[dispN], XmNwidth, pDAS->dispWidth);    ++dispN;
451             XtSetArg(dispArgs[dispN], XmNheight, pDAS->dispHeight);  ++dispN;
452           }
453
454         rectangle[0].x      = pDAS->decorThickness;
455         rectangle[0].y      = pDAS->decorThickness;
456         rectangle[0].width  = pDAS->dispUseWidth;
457         rectangle[0].height = pDAS->dispUseHeight;
458
459         XSetClipRectangles(XtDisplay(pDAS->dispWid), pDAS->normalGC, 0, 0,
460                                         rectangle, 1, Unsorted);
461         XSetClipRectangles(XtDisplay(pDAS->dispWid), pDAS->invertGC, 0, 0,
462                                         rectangle, 1, Unsorted);
463
464         if (pDAS->resizeCall)
465             (*(pDAS->resizeCall)) (pDAS->clientData);
466       }
467
468     /*
469      * Has the width changed? If so, then we are mapping or unmapping
470      * the vertical scrollbar.
471      */
472     if (-1 == changeWidth)
473       {
474         /*
475          * manage the scrollbar, the window has shrunk.
476          */
477         doVert = DoManage;
478
479         XtSetArg(dispArgs[dispN], XmNrightAttachment, XmATTACH_WIDGET);
480                                 ++dispN;
481         XtSetArg(dispArgs[dispN], XmNrightWidget, pDAS->vertScrollWid);
482                                 ++dispN;
483       }
484     else if (1 == changeWidth)
485       {
486         /*
487          * unmanage the scrollbar, the window has grown.
488          */
489         doVert = DoUnmanage;
490
491         XtSetArg(dispArgs[dispN], XmNrightAttachment, XmATTACH_FORM);
492                                 ++dispN;
493       }
494
495     /*
496      * Has the height changed? If so, then we are mapping or unmapping
497      * the horizontal scrollbar.
498      */
499     if (-1 == changeHeight)
500       {
501         /*
502          * manage the scrollbar, the window has shrunk.
503          */
504         doHorz = DoManage;
505
506         XtSetArg(dispArgs[dispN], XmNbottomAttachment,XmATTACH_WIDGET);
507                                 ++dispN;
508         XtSetArg(dispArgs[dispN], XmNbottomWidget,pDAS->horzScrollWid);
509                                 ++dispN;
510       }
511     else if (1 == changeHeight)
512       {
513         /*
514          * unmanage the scrollbar, the window has grown.
515          */
516         doHorz = DoUnmanage;
517
518         XtSetArg(dispArgs[dispN], XmNbottomAttachment, XmATTACH_FORM);
519                                 ++dispN;
520       }
521
522     /*
523      * get the margins, widths and height.
524      */
525     XtSetArg (args[0], XmNmarginWidth , &marginWidth);
526     XtSetArg (args[1], XmNmarginHeight, &marginHeight);
527     XtGetValues (XtParent (pDAS->dispWid), args, 2);
528
529     /*
530      * have to map the scroll bars before the drawn button can be
531      * attached to them and can't unmap the scroll bars until
532      * the drawn button has been unattached from them. But we
533      * want to do the re-attachments all at once to minimize the
534      * resizing.
535      */
536     if (doHorz == DoManage)
537       {
538         if (!XtIsRealized(pDAS->horzScrollWid))
539             XtSetMappedWhenManaged (pDAS->horzScrollWid, True);
540         else
541             XtMapWidget (pDAS->horzScrollWid);
542         pDAS->horzIsMapped = True;
543       }
544
545     if (doVert == DoManage)
546       {
547         if (!XtIsRealized(pDAS->vertScrollWid))
548             XtSetMappedWhenManaged (pDAS->vertScrollWid, True);
549         else
550             XtMapWidget (pDAS->vertScrollWid);
551         pDAS->vertIsMapped = True;
552       }
553
554     if (pDAS->vertScrollWid && pDAS->vertIsMapped && doVert != DoUnmanage)
555       {
556         if (pDAS->horzScrollWid && pDAS->horzIsMapped && doHorz != DoUnmanage)
557             XtSetArg(args[0], XmNbottomOffset, (marginHeight + horzHeight));
558         else
559             XtSetArg(args[0], XmNbottomOffset, marginHeight);
560
561         n = 1;
562
563         /*
564          * set the slider size.
565          */
566         slideSize = pDAS->dispUseHeight;
567         if (slideSize < 1)
568         slideSize = 1;
569     
570         /*
571          * determine the maximum size
572          */
573         maximum = pDAS->maxYpos;
574
575         if (maximum < slideSize)
576         maximum = slideSize;
577
578         if (maximum < 1)
579         maximum = 1;
580     
581         /*
582          * determine the page increment.
583          */
584         pageInc = 1;
585         if (((int)pDAS->dispUseHeight) - pDAS->lineHeight > 2)
586         pageInc = pDAS->dispUseHeight - pDAS->lineHeight;
587
588         XtSetArg (args[n], XmNvalue        , pDAS->firstVisible);       ++n;
589         XtSetArg (args[n], XmNsliderSize   , slideSize);                ++n;
590         XtSetArg (args[n], XmNmaximum      , maximum);                  ++n;
591         XtSetArg (args[n], XmNpageIncrement, pageInc);                  ++n;
592         XtSetValues (pDAS->vertScrollWid, args, n);
593       }
594
595     if (pDAS->horzScrollWid && pDAS->horzIsMapped && doHorz != DoUnmanage)
596       {
597         if (pDAS->vertScrollWid && pDAS->vertIsMapped && doVert != DoUnmanage)
598             XtSetArg(args[0], XmNrightOffset, (marginWidth + vertWidth));
599         else
600             XtSetArg(args[0], XmNrightOffset, marginWidth);
601
602         n = 1;
603         /*
604          * determine the slider size.
605          */
606         slideSize = pDAS->dispUseWidth - 1;
607         if (slideSize < 1)
608         slideSize = 1;
609
610         /*
611          * determine the maximum size
612          */
613         maximum = slideSize;
614         if (maximum < pDAS->maxX)
615         maximum = pDAS->maxX - 1;
616
617         if (maximum < 1)
618         maximum = 1;
619
620         /*
621          * determine the page increment.
622          */
623         pageInc = 1;
624         if (((int) pDAS->dispUseWidth) > 2)
625         pageInc = pDAS->dispUseWidth - 1;
626
627         XtSetArg (args[n], XmNvalue        , pDAS->virtualX);   n++;
628         XtSetArg (args[n], XmNsliderSize   , slideSize);        n++;
629         XtSetArg (args[n], XmNmaximum      , maximum);          n++;
630         XtSetArg (args[n], XmNpageIncrement, pageInc);          ++n;
631         XtSetValues (pDAS->horzScrollWid, args, n);
632       }
633
634     /*
635      * set the display area args
636      */
637     if (dispN)
638       XtSetValues (pDAS->dispWid, dispArgs, dispN);
639
640     /*
641      * unmap those we don't want.
642      */
643     if (doHorz == DoUnmanage)
644       {
645         if (!XtIsRealized(pDAS->horzScrollWid))
646             XtSetMappedWhenManaged (pDAS->horzScrollWid, False);
647         else
648             XtUnmapWidget (pDAS->horzScrollWid);
649         pDAS->horzIsMapped = False;
650       }
651
652     if (doVert == DoUnmanage)
653       {
654         if (!XtIsRealized(pDAS->vertScrollWid))
655             XtSetMappedWhenManaged (pDAS->vertScrollWid, False);
656         else
657             XtUnmapWidget (pDAS->vertScrollWid);
658         pDAS->vertIsMapped = False;
659       }
660
661     /*
662      * return whether or not we generated a resize (and hence an expose
663      * event) by resizing the display area.
664      */
665     return (dispN ? True : False);
666
667 } /* End _DtHelpSetScrollBars */
668
669 /******************************************************************************
670  *
671  * Public Functions - those an application developer can call.
672  *
673  *****************************************************************************/
674
675 /*********************************************************************
676  * Function: SetList
677  *
678  *    SetList creates a Text Graphic area with the appropriate scroll bars.
679  *
680  *********************************************************************/
681 void
682 _DtHelpDisplayAreaSetList (
683     XtPointer   client_data,
684     XtPointer   topic_handle,
685     Boolean     append_flag,
686     int         scroll_percent)
687 {
688     _DtCvUnit         width;
689     _DtCvUnit         height;
690     _DtCvUnit         scrollY;
691     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
692
693     /*
694      * clear the selection
695      */
696     _DtHelpClearSelection (client_data);
697
698     /*
699      * If there is anything to do
700      */
701     _DtCanvasSetTopic (pDAS->canvas, (_DtCvTopicPtr) topic_handle,
702                                                 pDAS->honor_size,
703                                                 &width, &height, &scrollY);
704
705     /*
706      * free the old topic and remember the new
707      */
708     _DtHelpDestroyTopicData(pDAS->lst_topic, _DtHelpDADestroyRegion,
709                                                 (_DtCvPointer) pDAS);
710
711     pDAS->lst_topic = (_DtCvTopicPtr) topic_handle;
712
713     /*
714      * do we want to scroll?
715      */
716     if (scroll_percent != -1)
717         scrollY = scroll_percent * height / 1000;
718
719     /*
720      * Reset the scroll bars and perhaps do an expose.
721      */
722     SetMaxPositions (pDAS, width, height);
723
724     pDAS->firstVisible = scrollY;
725
726     if (pDAS->firstVisible + ((int)pDAS->dispUseHeight) > pDAS->maxYpos)
727         pDAS->firstVisible = pDAS->maxYpos - pDAS->dispUseHeight;
728
729     if (pDAS->firstVisible < 0)
730         pDAS->firstVisible = 0;
731
732     (void) _DtHelpSetScrollBars (client_data, pDAS->dispWidth, pDAS->dispHeight);
733     if (XtIsRealized (pDAS->dispWid))
734         _DtHelpCleanAndDrawWholeCanvas(client_data);
735
736 }  /* End _DtHelpDisplayAreaSetList */
737
738 /*****************************************************************************
739  * Function: void _DtHelpDisplayAreaDimensionsReturn (DtHelpDispAreaStruct *pDAS,
740  *                                      int *ret_width, int *ret_height)
741  *
742  * Parameters   pDAS            Specifies the Display Area.
743  *              ret_rows        Returns the number of rows in
744  *                              the Display Area.
745  *              ret_columns     Returns the number of columns in
746  *                              the Display Area.
747  *
748  * Returns:     nothing
749  *
750  * Purpose:     Allows access to the height and width of a Display Area.
751  *
752  *****************************************************************************/
753 void
754 _DtHelpDisplayAreaDimensionsReturn (
755     XtPointer    client_data,
756     short       *ret_rows,
757     short       *ret_columns )
758 {
759     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
760
761     *ret_rows = ((int)pDAS->dispUseHeight) / pDAS->lineHeight;
762     *ret_columns = ((int) pDAS->dispUseWidth) / (pDAS->charWidth / 10);
763
764 }  /* End _DtHelpDisplayAreaDimensionsReturn */
765
766 /*****************************************************************************
767  * Function: int _DtHelpGetScrollbarValue (DtHelpDispAreaStruct *pDAS)
768  *
769  * Parameters   pDAS            Specifies the Display Area.
770  *
771  * Returns:     a value from -1 to 100.
772  *              -1 means the vertical scrollbar was not created when
773  *              the display area was created.
774  *              0 to 100 is the percentage the vertical scroll bar is
775  *              scrolled displaying the current topic.
776  *
777  * Purpose:     Allows the system to query the location of the scrollbar
778  *              and remember for smart-backtracking.
779  *
780  *****************************************************************************/
781 int
782 _DtHelpGetScrollbarValue (XtPointer client_data)
783 {
784     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
785
786     int  percent = -1;
787
788     if (pDAS->vertScrollWid != NULL)
789       {
790         percent = 0;
791         if (pDAS->firstVisible && pDAS->maxYpos)
792             percent = (pDAS->firstVisible * 1000) / pDAS->maxYpos;
793       }
794
795     return percent;
796
797 }  /* End _DtHelpGetScrollbarValue */
798
799 /*****************************************************************************
800  * Function: int _DtHelpUpdatePath (DtHelpDispAreaStruct *pDAS,
801  *
802  * Parameters   pDAS            Specifies the Display Area.
803  *
804  * Returns:     a value from -1 to 100.
805  *              -1 means the vertical scrollbar was not created when
806  *              the display area was created.
807  *              0 to 100 is the percentage the vertical scroll bar is
808  *              scrolled displaying the current topic.
809  *
810  * Purpose:     Allows the system to query the location of the scrollbar
811  *              and remember for smart-backtracking.
812  *
813  *****************************************************************************/
814 int
815 _DtHelpUpdatePath (
816     DtHelpDispAreaStruct        *pDAS,
817     _DtHelpVolumeHdl             volume_handle,
818     char                        *loc_id)
819 {
820     int          result;
821     char        *realId;
822     _DtCvUnit   width;
823     _DtCvUnit   height;
824     _DtCvUnit   tocY;
825     _DtCvUnit   tocHeight;
826     XtPointer   topic_handle;
827
828     /*
829      * turn off the toc marker
830      */
831     _DtHelpDATocMarker(pDAS, False);
832     (void) _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_OFF, False,
833                         ((_DtCvValue) XtIsRealized(pDAS->dispWid)),
834                         NULL, NULL, NULL, NULL, NULL);
835
836     /*
837      * now create and set the topic
838      */
839     result = _DtHelpFormatToc(pDAS,volume_handle,loc_id,&realId,&topic_handle);
840     if (-1 == result)
841         return -1;
842
843     _DtCanvasSetTopic (pDAS->canvas, (_DtCvTopicPtr) topic_handle,
844                                                 pDAS->honor_size,
845                                                 &width, &height, NULL);
846
847     /*
848      * free the old topic and remember the new
849      */
850     _DtHelpDestroyTopicData(pDAS->lst_topic, _DtHelpDADestroyRegion,
851                                                 (_DtCvPointer) pDAS);
852
853     pDAS->lst_topic = (_DtCvTopicPtr) topic_handle;
854
855     /*
856      * Reset the scroll bars and perhaps do an expose.
857      */
858     SetMaxPositions (pDAS, width, height);
859
860     /*
861      * now turn the traversal on - but only if there is a path in
862      * the TOC.
863      */
864     if (1 != result)
865       {
866         (void) _DtCanvasMoveTraversal(pDAS->canvas, _DtCvTRAVERSAL_ID, False,
867                 ((_DtCvStatus) XtIsRealized(pDAS->dispWid)), realId,
868                 NULL, &(pDAS->toc_y), &(pDAS->toc_base), &(pDAS->toc_height));
869
870         /*
871          * figure out where the first line should be...
872          */
873         tocY      = pDAS->toc_y - pDAS->lineThickness;
874         tocHeight = pDAS->toc_height + (2 * pDAS->lineThickness);
875
876         if (tocY < pDAS->firstVisible ||
877             tocY + tocHeight > pDAS->firstVisible + ((int)pDAS->dispUseHeight))
878           {
879             pDAS->firstVisible  = tocY;
880             if (pDAS->firstVisible + ((int)pDAS->dispUseHeight) > pDAS->maxYpos)
881                 pDAS->firstVisible = pDAS->maxYpos - pDAS->dispUseHeight;
882
883             if (pDAS->firstVisible < 0)
884                 pDAS->firstVisible = 0;
885           }
886       }
887
888     /*
889      * Reset the scroll bars and perhaps do an expose.
890      */
891     (void) _DtHelpSetScrollBars((XtPointer) pDAS, pDAS->dispWidth, pDAS->dispHeight);
892     if (XtIsRealized (pDAS->dispWid))
893         _DtHelpCleanAndDrawWholeCanvas((XtPointer) pDAS);
894
895     if (1 != result)
896         _DtHelpDATocMarker((XtPointer) pDAS, True);
897
898     return 0;
899
900 }  /* End _DtHelpUpdatePath */
901
902 /*****************************************************************************
903  * Function:    Widget _DtHelpDisplayAreaWidget ();
904  *
905  * Parameters:
906  *              client_data     Specifies the display area pointer.
907  *
908  * Returns: the widget associated with the display area.
909  *
910  * Purpose:
911  *
912  *****************************************************************************/
913 Widget
914 _DtHelpDisplayAreaWidget (
915     XtPointer    client_data)
916 {
917     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
918
919    return (pDAS->dispWid);
920 }
921
922 /*****************************************************************************
923  * Function:    XtPointer _DtHelpDisplayAreaData ();
924  *
925  * Parameters:
926  *              client_data     Specifies the display area pointer.
927  *
928  * Returns: the client data associated with the display area.
929  *
930  * Purpose:
931  *
932  *****************************************************************************/
933 XtPointer
934 _DtHelpDisplayAreaData (
935     XtPointer    client_data)
936 {
937     DtHelpDispAreaStruct *pDAS = (DtHelpDispAreaStruct *) client_data;
938
939    return (pDAS->clientData);
940 }