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