home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 576.lha / DiskSpeed_v4.0 / mks_list.c < prev    next >
C/C++ Source or Header  |  1991-09-11  |  20KB  |  686 lines

  1. /*
  2.  * MKSoft Display List Gadget - Copyright (c) 1989, 1990 by MKSoft Development
  3.  *
  4.  *                          DiskSpeed v4.0
  5.  *                                by
  6.  *                           Michael Sinz
  7.  *
  8.  *             Copyright (c) 1989 by MKSoft Development
  9.  *
  10.  *            MKSoft Development
  11.  *            163 Appledore Drive
  12.  *            Downingtown, PA 19335
  13.  *
  14.  * Yes, this is yet another disk speed testing program, but with a few
  15.  * differences.  It was designed to give the most accurate results of the
  16.  * true disk performance in the system.  For this reason many of
  17.  * DiskSpeed's results may look either lower or higher than current disk
  18.  * performance tests.
  19.  *
  20.  ******************************************************************************
  21.  *                                          *
  22.  *    Reading legal mush can turn your brain into guacamole!              *
  23.  *                                          *
  24.  *        So here is some of that legal mush:                  *
  25.  *                                          *
  26.  * Permission is hereby granted to distribute this program's source          *
  27.  * executable, and documentation for non-commercial purposes, so long as the  *
  28.  * copyright notices are not removed from the sources, executable or          *
  29.  * documentation.  This program may not be distributed for a profit without   *
  30.  * the express written consent of the author Michael Sinz.              *
  31.  *                                          *
  32.  * This program is not in the public domain.                      *
  33.  *                                          *
  34.  * Fred Fish is expressly granted permission to distribute this program's     *
  35.  * source and executable as part of the "Fred Fish freely redistributable     *
  36.  * Amiga software library."                              *
  37.  *                                          *
  38.  * Permission is expressly granted for this program and it's source to be     *
  39.  * distributed as part of the Amicus Amiga software disks, and the          *
  40.  * First Amiga User Group's Hot Mix disks.                      *
  41.  *                                          *
  42.  ******************************************************************************
  43.  */
  44.  
  45. #include    <exec/types.h>
  46. #include    <exec/lists.h>
  47. #include    <exec/nodes.h>
  48. #include    <exec/memory.h>
  49. #include    <graphics/text.h>
  50. #include    <intuition/intuition.h>
  51.  
  52. #include    <clib/intuition_protos.h>
  53. #include    <clib/exec_protos.h>
  54. #include    <clib/graphics_protos.h>
  55. #include    <clib/layers_protos.h>
  56.  
  57. #include    <pragmas/intuition_pragmas.h>
  58. #include    <pragmas/exec_pragmas.h>
  59. #include    <pragmas/graphics_pragmas.h>
  60. #include    <pragmas/layers_pragmas.h>
  61.  
  62. #include    <string.h>
  63.  
  64. #include    "MKS_List.h"
  65. #include    "MakeBoxes.h"
  66.  
  67. extern    struct    Library    *SysBase;
  68. extern    struct    Library    *IntuitionBase;
  69. extern    struct    Library    *GfxBase;
  70. extern    struct    Library    *LayersBase;
  71.  
  72. /*
  73.  * This is the "real" DisplayList structure...
  74.  */
  75. struct    RealDisplayList
  76. {
  77.     /*
  78.      * These fields are from the public structure...
  79.      */
  80.     struct    DisplayList    DisplayList;
  81.  
  82.     /*
  83.      * The following fields are *NOT* public and are
  84.      * 100% maintained by the list gadget...
  85.      */
  86.     struct    Node        *Top;
  87.     struct    MinList        *TheList;
  88.         SHORT        TopNum;
  89.         SHORT        ListSize;
  90.         SHORT        DisplaySize;    /* Number of display lines */
  91.         SHORT        LineYSize;
  92.  
  93.     struct    Region        *Region;
  94.     struct    Rectangle    Rectangle;
  95.  
  96.     struct    IntuiText    Text;
  97.     struct    TextAttr    TextStyle;
  98.     struct    TextFont    *TheFont;
  99.  
  100.     struct    Gadget        ListGadget;
  101.     struct    Gadget        UpGadget;
  102.     struct    Gadget        DnGadget;
  103.     struct    Gadget        PropGadget;
  104.  
  105.     struct    PropInfo    PropInfo;
  106.     struct    Image        PropImage;    /* For AutoKnob stuff... */
  107.  
  108.     struct    Border        ListGadgetBorders[4];
  109.     struct    Border        UpGadgetBorders[5];
  110.     struct    Border        DnGadgetBorders[5];
  111.         SHORT        ListGadgetVectors[5*2*4];
  112.  
  113.         UBYTE        FontName[1];
  114. };
  115.  
  116. /*
  117.  * Whenever we have "list" as a DisplayList, we have REAL_list as a RealDisplayList
  118.  */
  119. #define    REAL_list    ((struct RealDisplayList *)list)
  120.  
  121. #define    LIST_GADGET_ID    (0x7F01)
  122.  
  123. /*
  124.  * Vectors that display the arrows...
  125.  */
  126. static    SHORT    DnArrow_V[7*2]={4,3,7,0,0,0,3,3,6,1,2,1,3,2};
  127. static    SHORT    UpArrow_V[7*2]={4,0,7,3,0,3,3,0,6,2,2,2,3,1};
  128. static    SHORT    ArrowBoxTopLeft_V[5*2]={12,0,0,0,0,7,1,6,1,1};
  129. static    SHORT    ArrowBoxBottomRight_V[5*2]={1,7,13,7,13,0,12,1,12,6};
  130.  
  131. static    struct    Border    DnArrow={3,2,0,0,JAM1,7,DnArrow_V,NULL};
  132. static    struct    Border    UpArrow={3,2,0,0,JAM1,7,UpArrow_V,NULL};
  133.  
  134. /*
  135.  * These two DEFINEs help find the correct RastPort and BackFill colour
  136.  */
  137. #define    PICK_RASTPORT(window,list)    (window->RPort)
  138. #define    PICK_BACKFILL(list)        (0)
  139.  
  140. /*
  141.  * Just a quicky to help fill in the boarder structures...
  142.  */
  143. static void Do_Borders(struct Border *borders,UBYTE Highlight,UBYTE Shadow)
  144. {
  145.     borders[1].FrontPen=Highlight;
  146.     borders[1].DrawMode=JAM1;
  147.     borders[1].Count=5;
  148.     borders[1].XY=ArrowBoxTopLeft_V;
  149.     borders[1].NextBorder=&(borders[0]);
  150.     borders[2].FrontPen=Shadow;
  151.     borders[2].DrawMode=JAM1;
  152.     borders[2].Count=5;
  153.     borders[2].XY=ArrowBoxTopLeft_V;
  154.     borders[2].NextBorder=&(borders[0]);
  155.     borders[3].FrontPen=Shadow;
  156.     borders[3].DrawMode=JAM1;
  157.     borders[3].Count=5;
  158.     borders[3].XY=ArrowBoxBottomRight_V;
  159.     borders[3].NextBorder=&(borders[1]);
  160.     borders[4].FrontPen=Highlight;
  161.     borders[4].DrawMode=JAM1;
  162.     borders[4].Count=5;
  163.     borders[4].XY=ArrowBoxBottomRight_V;
  164.     borders[4].NextBorder=&(borders[2]);
  165. }
  166.  
  167. /*
  168.  * This routine deallocates the DisplayList allocated below...
  169.  * It does not do any unlinking...
  170.  */
  171. void FreeListGadget(struct DisplayList *list)
  172. {
  173.     if (list)
  174.     {
  175.         if (REAL_list->TheFont) CloseFont(REAL_list->TheFont);
  176.         if (REAL_list->Region) DisposeRegion(REAL_list->Region);
  177.         FreeMem(list,sizeof(struct RealDisplayList)+(LONG)strlen(REAL_list->FontName));
  178.     }
  179. }
  180.  
  181. /*
  182.  * This routine allocates and initializes a DisplayList gadget...
  183.  * It will link the gadgets into the gadget list given...
  184.  *
  185.  * Arguments:  TextAttr,**Gadget,TextPen,Highlight,Shadow,Left,Top,Width,Height
  186.  */
  187. struct DisplayList *InitListGadget(struct TextAttr *ta,struct Gadget **gad,UBYTE TextPen,UBYTE Highlight,UBYTE Shadow,SHORT Left,SHORT Top,SHORT Width,SHORT Height)
  188. {
  189. register    struct    RealDisplayList    *rlist;
  190. register        SHORT        tmp;
  191.  
  192.     if (rlist=AllocMem(sizeof(struct RealDisplayList)+(LONG)strlen(ta->ta_Name),MEMF_PUBLIC|MEMF_CLEAR))
  193.     {
  194.         if (rlist->Region=NewRegion())
  195.         {
  196.             rlist->DisplaySize=(Height-4) / (rlist->LineYSize=((ta->ta_YSize)+2));
  197.  
  198.             /*
  199.              * Make borders for the main list box...
  200.              */
  201.             rlist->ListGadgetBorders[0].FrontPen=Shadow;
  202.             rlist->ListGadgetBorders[0].DrawMode=JAM1;
  203.             rlist->ListGadgetBorders[0].Count=5;
  204.             rlist->ListGadgetBorders[0].XY=&(rlist->ListGadgetVectors[0*5*2]);
  205.             rlist->ListGadgetBorders[0].NextBorder=&(rlist->ListGadgetBorders[1]);
  206.             FillTopLeft_Border(&(rlist->ListGadgetBorders[0]),Width-16,Height);
  207.  
  208.             rlist->ListGadgetBorders[1].FrontPen=Highlight;
  209.             rlist->ListGadgetBorders[1].DrawMode=JAM1;
  210.             rlist->ListGadgetBorders[1].Count=5;
  211.             rlist->ListGadgetBorders[1].XY=&(rlist->ListGadgetVectors[1*5*2]);
  212.             rlist->ListGadgetBorders[1].NextBorder=&(rlist->ListGadgetBorders[2]);
  213.             FillBottomRight_Border(&(rlist->ListGadgetBorders[1]),Width-16,Height);
  214.  
  215.             /*
  216.              * Make borders for the prop gadget area...
  217.              * This is linked to the main list box since the prop gadget
  218.              * will be just a borderless AutoKnob...
  219.              */
  220.             rlist->ListGadgetBorders[2].LeftEdge=Width-14;
  221.             rlist->ListGadgetBorders[2].FrontPen=Highlight;
  222.             rlist->ListGadgetBorders[2].DrawMode=JAM1;
  223.             rlist->ListGadgetBorders[2].Count=5;
  224.             rlist->ListGadgetBorders[2].XY=&(rlist->ListGadgetVectors[2*5*2]);
  225.             rlist->ListGadgetBorders[2].NextBorder=&(rlist->ListGadgetBorders[3]);
  226.             FillTopLeft_Border(&(rlist->ListGadgetBorders[2]),14,Height-16);
  227.  
  228.             rlist->ListGadgetBorders[3].LeftEdge=Width-14;
  229.             rlist->ListGadgetBorders[3].FrontPen=Shadow;
  230.             rlist->ListGadgetBorders[3].DrawMode=JAM1;
  231.             rlist->ListGadgetBorders[3].Count=5;
  232.             rlist->ListGadgetBorders[3].XY=&(rlist->ListGadgetVectors[3*5*2]);
  233.             rlist->ListGadgetBorders[3].NextBorder=NULL;
  234.             FillBottomRight_Border(&(rlist->ListGadgetBorders[3]),14,Height-16);
  235.  
  236.             /*
  237.              * The main list gadget...
  238.              */
  239.             rlist->ListGadget.LeftEdge=Left;
  240.             rlist->ListGadget.TopEdge=Top;
  241.             rlist->ListGadget.Width=0;
  242.             rlist->ListGadget.Height=0;
  243.             rlist->ListGadget.Flags=GADGHNONE;
  244.             rlist->ListGadget.Activation=0;
  245.             rlist->ListGadget.GadgetType=BOOLGADGET;
  246.             rlist->ListGadget.GadgetRender=(APTR)&(rlist->ListGadgetBorders[0]);
  247.             rlist->ListGadget.GadgetID=LIST_GADGET_ID;
  248.             rlist->ListGadget.UserData=(APTR)rlist;
  249.  
  250.             /*
  251.              * The AutoKnob is Borderless since we will be making
  252.              * our own 3-D style border...
  253.              */
  254.             rlist->PropInfo.Flags=AUTOKNOB|FREEVERT|PROPBORDERLESS;
  255.             rlist->PropInfo.HorizBody=MAXBODY;
  256.             rlist->PropInfo.VertBody=MAXBODY;
  257.             rlist->PropGadget.LeftEdge=Left+Width-11;
  258.             rlist->PropGadget.TopEdge=Top+2;
  259.             rlist->PropGadget.Width=8;
  260.             rlist->PropGadget.Height=Height-20;
  261.             rlist->PropGadget.Flags=GADGIMAGE;
  262.             rlist->PropGadget.Activation=GADGIMMEDIATE|RELVERIFY|FOLLOWMOUSE;
  263.             rlist->PropGadget.GadgetType=PROPGADGET;
  264.             rlist->PropGadget.GadgetRender=(APTR)&(rlist->PropImage);
  265.             rlist->PropGadget.SpecialInfo=(APTR)&(rlist->PropInfo);
  266.             rlist->PropGadget.GadgetID=LIST_GADGET_ID;
  267.             rlist->PropGadget.UserData=(APTR)rlist;
  268.  
  269.             /*
  270.              * Set up the Up and Down arrow gadgets...
  271.              */
  272.             rlist->UpGadgetBorders[0]=UpArrow;
  273.             rlist->UpGadgetBorders[0].FrontPen=TextPen;
  274.             Do_Borders(rlist->UpGadgetBorders,Highlight,Shadow);
  275.             rlist->UpGadget.LeftEdge=Left+Width-14;
  276.             rlist->UpGadget.TopEdge=Top+Height-16;
  277.             rlist->UpGadget.Width=14;
  278.             rlist->UpGadget.Height=8;
  279.             rlist->UpGadget.Flags=((Shadow!=Highlight) ? GADGHIMAGE : GADGHCOMP);
  280.             rlist->UpGadget.Activation=RELVERIFY|GADGIMMEDIATE;
  281.             rlist->UpGadget.GadgetType=BOOLGADGET;
  282.             rlist->UpGadget.GadgetRender=(APTR)&(rlist->UpGadgetBorders[3]);
  283.             rlist->UpGadget.SelectRender=(APTR)&(rlist->UpGadgetBorders[4]);
  284.             rlist->UpGadget.GadgetID=LIST_GADGET_ID;
  285.             rlist->UpGadget.UserData=(APTR)rlist;
  286.  
  287.             rlist->DnGadgetBorders[0]=DnArrow;
  288.             rlist->DnGadgetBorders[0].FrontPen=TextPen;
  289.             Do_Borders(rlist->DnGadgetBorders,Highlight,Shadow);
  290.             rlist->DnGadget.LeftEdge=Left+Width-14;
  291.             rlist->DnGadget.TopEdge=Top+Height-8;
  292.             rlist->DnGadget.Width=14;
  293.             rlist->DnGadget.Height=8;
  294.             rlist->DnGadget.Flags=((Shadow!=Highlight) ? GADGHIMAGE : GADGHCOMP);
  295.             rlist->DnGadget.Activation=RELVERIFY|GADGIMMEDIATE;
  296.             rlist->DnGadget.GadgetType=BOOLGADGET;
  297.             rlist->DnGadget.GadgetRender=(APTR)&(rlist->DnGadgetBorders[3]);
  298.             rlist->DnGadget.SelectRender=(APTR)&(rlist->DnGadgetBorders[4]);
  299.             rlist->DnGadget.GadgetID=LIST_GADGET_ID;
  300.             rlist->DnGadget.UserData=(APTR)rlist;
  301.  
  302.             /*
  303.              * Set up the rectangle and clipping area for the list box
  304.              */
  305.             rlist->Rectangle.MaxX=(rlist->Rectangle.MinX=(rlist->ListGadget.LeftEdge)+3)+Width-25;
  306.             rlist->Rectangle.MaxY=(rlist->Rectangle.MinY=(rlist->ListGadget.TopEdge)+2)+Height-5;
  307.  
  308.             /*
  309.              * We want to CENTER the rectangle based on the number of
  310.              * text lines and the text hight.
  311.              */
  312.             tmp=(rlist->Rectangle.MaxY)-(rlist->Rectangle.MinY)+1;
  313.             tmp-=(rlist->DisplaySize)*(rlist->LineYSize);
  314.             if (tmp>0)
  315.             {
  316.                 rlist->Rectangle.MinY+=(tmp>>1);
  317.                 rlist->Rectangle.MaxY-=((tmp+1)>>1);
  318.             }
  319.  
  320.             /*
  321.              * Pre-initialize the Intuitext structure as much as possible...
  322.              */
  323.             rlist->Text.FrontPen=TextPen;
  324.             rlist->Text.DrawMode=JAM1;
  325.             rlist->Text.LeftEdge=1;
  326.             rlist->Text.TopEdge=1;
  327.             rlist->Text.ITextFont=&(rlist->TextStyle);
  328.  
  329.             /*
  330.              * Make a copy of the TextAttr for the list display
  331.              */
  332.             rlist->TextStyle=*ta;
  333.             strcpy(rlist->TextStyle.ta_Name=rlist->FontName,ta->ta_Name);
  334.  
  335.             /*
  336.              * Open the font so it stays around...
  337.              * Since the font had to be open when called, this just gets
  338.              * another open on it.  The clean up routine closes this...
  339.              */
  340.             rlist->TheFont=OpenFont(&(rlist->TextStyle));
  341.  
  342.             /*
  343.              * Now, pre-build the region for better speed...
  344.              */
  345.             if (!OrRectRegion(rlist->Region,&(rlist->Rectangle)))
  346.             {
  347.                 FreeListGadget((struct DisplayList *)rlist);
  348.                 rlist=NULL;
  349.             }
  350.         }
  351.         else
  352.         {
  353.             FreeListGadget((struct DisplayList *)rlist);
  354.             rlist=NULL;
  355.         }
  356.     }
  357.     if (rlist)
  358.     {
  359.         rlist->ListGadget.NextGadget=*gad;
  360.         rlist->PropGadget.NextGadget=&(rlist->ListGadget);
  361.         rlist->UpGadget.NextGadget=&(rlist->PropGadget);
  362.         rlist->DnGadget.NextGadget=&(rlist->UpGadget);
  363.         *gad=&(rlist->DnGadget);
  364.     }
  365.     return((struct DisplayList *)rlist);
  366. }
  367.  
  368. /*
  369.  * This routine updates the prop gadget for the list given...
  370.  */
  371. static void UpDate_Prop(struct Window *window,struct DisplayList *list)
  372. {
  373. register    long    diffsize;
  374.  
  375.     diffsize=(REAL_list->ListSize)-(REAL_list->DisplaySize);
  376.  
  377.     if (diffsize>0)
  378.     {
  379.         NewModifyProp(&(REAL_list->PropGadget),window,NULL,REAL_list->PropInfo.Flags,
  380.                 0,
  381.                 (USHORT)(((0xffffL)*(REAL_list->TopNum)+(diffsize>>1))/diffsize),
  382.  
  383.                 0xffff,
  384.                 (USHORT)(((0xffffL)*(REAL_list->DisplaySize))/(REAL_list->ListSize)),
  385.  
  386.                 1L);
  387.     }
  388.     else
  389.     {
  390.         NewModifyProp(&(REAL_list->PropGadget),window,NULL,REAL_list->PropInfo.Flags,
  391.                 0,
  392.                 0,
  393.  
  394.                 0xffff,
  395.                 0xffff,
  396.  
  397.                 1L);
  398.     }
  399. }
  400.  
  401. /*
  402.  * This routine takes the NewTop and sets it into the TopNum and
  403.  * positions *Top to the right node value...
  404.  *
  405.  * Note:  Since this routine does not do ERROR checking, the NewTop value
  406.  *        and TheList *MUST* be valid...
  407.  */
  408. static void SetTopPointer(struct DisplayList *list,SHORT NewTop)
  409. {
  410. struct    Node    *item;
  411.  
  412.     REAL_list->TopNum=NewTop;
  413.     item=(struct Node *)(REAL_list->TheList->mlh_Head);
  414.  
  415.     while(NewTop)
  416.     {
  417.         item=(struct Node *)(item->ln_Succ);
  418.         NewTop--;
  419.     }
  420.     REAL_list->Top=item;
  421. }
  422.  
  423. /*
  424.  * This routine will display the line number given...  (Display line number)
  425.  *
  426.  * If the line is selected, it will be inverted via a Complement RectFill
  427.  *
  428.  * All actions will be clipped via a ClipRect that this routine installs.
  429.  */
  430. static void DisplayLine(struct RastPort *rp,struct DisplayList *list,SHORT line)
  431. {
  432. register    struct    Region    *r;
  433. register    struct    Node    *item;
  434. register        SHORT    y;
  435. register        SHORT    y1;
  436.  
  437.     if ((line>=0)&&(line<(REAL_list->DisplaySize)))
  438.     {
  439.         /*
  440.          * Set up clipping rectangle within the borders of the gadget...
  441.          */
  442.         r=InstallClipRegion(rp->Layer,REAL_list->Region);
  443.  
  444.         y1=(y=(REAL_list->Rectangle.MinY)+(line*(REAL_list->LineYSize)))+(REAL_list->LineYSize)-1;
  445.  
  446.         SetAPen(rp,PICK_BACKFILL(REAL_list));
  447.         SetDrMd(rp,JAM1);
  448.         RectFill(rp,REAL_list->Rectangle.MinX,y,REAL_list->Rectangle.MaxX,y1);
  449.  
  450.         if (item=REAL_list->Top)
  451.         {
  452.             while (line>0)
  453.             {
  454.                 if (item->ln_Succ)
  455.                 {
  456.                     item=(struct Node *)(item->ln_Succ);
  457.                     line--;
  458.                 }
  459.                 else line=0;
  460.             }
  461.             if (item->ln_Succ)
  462.             {
  463.                 REAL_list->Text.IText=item->ln_Name;
  464.                 PrintIText(rp,&(REAL_list->Text),REAL_list->Rectangle.MinX,y);
  465.             }
  466.         }
  467.  
  468.         InstallClipRegion(rp->Layer,r);
  469.     }
  470. }
  471.  
  472. /*
  473.  * This routine will clear the list box to the backfill colour...
  474.  */
  475. static void ClearDisplayBox(struct RastPort *rp,struct DisplayList *list)
  476. {
  477.     SetAPen(rp,PICK_BACKFILL(REAL_list));
  478.     SetDrMd(rp,JAM1);
  479.     RectFill(rp,    REAL_list->Rectangle.MinX,REAL_list->Rectangle.MinY,
  480.             REAL_list->Rectangle.MaxX,REAL_list->Rectangle.MaxY);
  481. }
  482.  
  483. /*
  484.  * This routine displays all of the lines in the list...
  485.  */
  486. static void DisplayAllLines(struct RastPort *rp,struct DisplayList *list)
  487. {
  488. register    SHORT    line;
  489.  
  490.     for (line=0;line<(REAL_list->DisplaySize);line++) DisplayLine(rp,list,line);
  491. }
  492.  
  493. /*
  494.  * This routine moves the list UP or DOWN to the line number give.
  495.  *
  496.  * It will try to make sure that this is done as best as possible...
  497.  * It will update the prop gadget if it is not active...
  498.  */
  499. static void MoveList(struct Window *window,struct DisplayList *list,SHORT line)
  500. {
  501. register    struct    RastPort    *rp;
  502. register        SHORT        newline;
  503.  
  504.     newline=line+(REAL_list->TopNum);
  505.     if (newline<0) line=0-(REAL_list->TopNum);
  506.     else if (newline>((REAL_list->ListSize)-(REAL_list->DisplaySize)))
  507.     {
  508.         line=(REAL_list->ListSize)-(REAL_list->DisplaySize)-(REAL_list->TopNum);
  509.         if (line<0) line=0;
  510.     }
  511.  
  512.     if (line)
  513.     {
  514.         rp=PICK_RASTPORT(window,REAL_list);
  515.         SetTopPointer(list,line+(REAL_list->TopNum));
  516.         if (line>0) newline=line;
  517.         else newline=0-line;
  518.  
  519.         if ((newline*11)>(8*(REAL_list->DisplaySize)))
  520.         {
  521.             DisplayAllLines(rp,list);
  522.         }
  523.         else
  524.         {
  525.             SetDrMd(rp,JAM2);
  526.             SetBPen(rp,PICK_BACKFILL(REAL_list));
  527.  
  528.             ScrollRaster(rp,0,line*(REAL_list->LineYSize),
  529.                     REAL_list->Rectangle.MinX,REAL_list->Rectangle.MinY,
  530.                     REAL_list->Rectangle.MaxX,REAL_list->Rectangle.MaxY);
  531.  
  532.             if (line<0)
  533.             {
  534.                 newline=0-line;
  535.                 line=0;
  536.             }
  537.             else
  538.             {
  539.                 newline=REAL_list->DisplaySize;
  540.                 line=(REAL_list->DisplaySize)-line;
  541.             }
  542.             while (line<newline) DisplayLine(rp,list,line++);
  543.         }
  544.         if (!((REAL_list->PropGadget.Flags)&SELECTED)) UpDate_Prop(window,list);
  545.     }
  546. }
  547.  
  548. /*
  549.  * This routine will initialize a fresh list.  It clears Selected,
  550.  * counts the entries, sets top of the display such that the bottom
  551.  * of the list is displayed and displays the list...
  552.  */
  553. void FreshList(struct Window *window,struct DisplayList *list,struct MinList *newlist)
  554. {
  555. register    struct    Node    *item;
  556. register        SHORT    count;
  557.  
  558.     REAL_list->TheList=newlist;
  559.     REAL_list->Top=REAL_list->DisplayList.Selected=NULL;
  560.     count=0;
  561.     if (newlist)
  562.     {
  563.         item=(struct Node *)(REAL_list->TheList->mlh_Head);
  564.         while (item=(struct Node *)(item->ln_Succ)) count++;
  565.         SetTopPointer(list,(count > REAL_list->DisplaySize) ? count-REAL_list->DisplaySize : 0);
  566.     }
  567.     REAL_list->ListSize=count;
  568.     UpDate_Prop(window,list);
  569.     DisplayAllLines(PICK_RASTPORT(window,REAL_list),REAL_list);
  570. }
  571.  
  572. /*
  573.  * This routine loops while one of the arrow gadgets is pressed and will
  574.  * advance the display accordingly.
  575.  */
  576. static void ArrowGadgetLoop(struct Window *window,struct DisplayList *list,struct Gadget *gad,SHORT change)
  577. {
  578. register    struct    IntuiMessage    *msg;
  579. register        ULONG        old_IDCMP;
  580. register        SHORT        tick_count;
  581. register        SHORT        flag=TRUE;
  582.  
  583.     old_IDCMP=window->IDCMPFlags;
  584.     ModifyIDCMP(window,MOUSEBUTTONS|GADGETUP|INTUITICKS);
  585.  
  586.     MoveList(window,list,change);
  587.     tick_count=-3;
  588.  
  589.     while(flag)
  590.     {
  591.         WaitPort(window->UserPort);
  592.         if (msg=(struct IntuiMessage *)GetMsg(window->UserPort))
  593.         {
  594.             switch (msg->Class)
  595.             {
  596.             case MOUSEBUTTONS:    if (msg->Code==SELECTUP) flag=FALSE;
  597.                         break;
  598.             case GADGETUP:        flag=FALSE;
  599.                         break;
  600.             case INTUITICKS:    tick_count++;
  601.                         if ((tick_count>0)&&(gad->Flags&SELECTED))
  602.                         {
  603.                             MoveList(window,list,change);
  604.                         }
  605.                         break;
  606.             }
  607.             ReplyMsg((struct Message *)msg);
  608.         }
  609.     }
  610.  
  611.     ModifyIDCMP(window,old_IDCMP);
  612. }
  613.  
  614. /*
  615.  * This routine moves the list to match the prop gadget...
  616.  */
  617. static void MoveToProp(struct Window *window,struct DisplayList *list)
  618. {
  619. register    ULONG    tmp;
  620.  
  621.     if ((tmp=((REAL_list->ListSize)-(REAL_list->DisplaySize)))>0)
  622.     {
  623.         tmp=(tmp*(ULONG)(REAL_list->PropInfo.VertPot)+(0xffffL >> 1))/0xffffL;
  624.         MoveList(window,list,(SHORT)tmp-(REAL_list->TopNum));
  625.     }
  626. }
  627.  
  628. /*
  629.  * This routine is entered on GADGETDOWN on the PropGadget and
  630.  * it loops until the user releases it.  It updates the display
  631.  * as needed by user actions...
  632.  */
  633. static void PropGadgetLoop(struct Window *window,struct DisplayList *list)
  634. {
  635. register    struct    IntuiMessage    *msg;
  636. register        ULONG        old_IDCMP;
  637. register        SHORT        flag=TRUE;
  638.  
  639.     old_IDCMP=window->IDCMPFlags;
  640.     ModifyIDCMP(window,GADGETUP|MOUSEMOVE);
  641.  
  642.     while(flag)
  643.     {
  644.         msg=(struct IntuiMessage *)WaitPort(window->UserPort);
  645.         while ((flag)&&(msg)) if (msg=(struct IntuiMessage *)GetMsg(window->UserPort))
  646.         {
  647.             if (msg->Class==GADGETUP) flag=FALSE;
  648.             ReplyMsg((struct Message *)msg);
  649.         }
  650.         MoveToProp(window,list);
  651.     }
  652.  
  653.     ModifyIDCMP(window,old_IDCMP);
  654. }
  655.  
  656. /*
  657.  * This is the InputEvent filter...
  658.  * Call this routine with each message.  If it returns a pointer to
  659.  * a DisplayList, a message was processed, if it returns NULL, nothing
  660.  * was done with the message and you may need to process it.
  661.  * The message is NOT ReplyMsg()ed...
  662.  */
  663. struct DisplayList *Check_ListGadget(struct Window *window,struct IntuiMessage *message)
  664. {
  665. register    struct    Gadget        *gad;
  666. register    struct    DisplayList    *list=NULL;
  667.  
  668.     if (message)
  669.     {
  670.         if (message->Class==GADGETDOWN)
  671.         {
  672.             gad=(struct Gadget *)(message->IAddress);
  673.             if (gad->GadgetID==LIST_GADGET_ID)
  674.             {
  675.                 if (list=(struct DisplayList *)(gad->UserData))
  676.                 {
  677.                     if (&(REAL_list->PropGadget)==gad) PropGadgetLoop(window,list);
  678.                     else if (&(REAL_list->UpGadget)==gad) ArrowGadgetLoop(window,list,gad,-1);
  679.                     else if (&(REAL_list->DnGadget)==gad) ArrowGadgetLoop(window,list,gad,1);
  680.                 }
  681.             }
  682.         }
  683.     }
  684.     return(list);
  685. }
  686.