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