home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / OTL-MC7.DMS / in.adf / classsource.lha / ClassSource / BOOPSI / gadgets / listgadget.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-12  |  21.3 KB  |  831 lines

  1. #include <classes/BOOPSI/gadgets.h>
  2. #include <classes/BOOPSI/boopsilib.h>
  3.  
  4. #include <intuition/icclass.h>
  5. #include <string.h>
  6.  
  7. #pragma -
  8. #include <pragma/utility_lib.h>
  9. #include <clib/alib_protos.h>
  10. #include <pragma/intuition_lib.h>
  11. #include <pragma/graphics_lib.h>
  12. #include <pragma/layers_lib.h>
  13. #include <graphics/gfxmacros.h>
  14. #pragma +
  15.  
  16. struct InstanceData {
  17.     struct TextAttr *tattr;
  18.     struct TextFont *font;
  19.     UWORD spacing;
  20.     struct List *members;
  21.     BOOL attached;
  22.     LONG top;
  23.     LONG active;
  24.     BOOL readonly;
  25.     Object *frame;
  26.     IBox framebox;
  27.     WORD frameright;
  28.     WORD framebottom;
  29.     ULONG total;
  30.     UWORD itemheight;
  31.     BOOL customHeight;
  32.     ULONG columns;
  33.     ULONG lines;
  34.     UBYTE labelmark;
  35.     UWORD horizleft;
  36.     Object *horiztarget;
  37.     struct TagItem *horizmap;
  38.     ULONG horizadjust;
  39.     WORD leftborder;
  40.     WORD rightborder;
  41.     WORD topborder;
  42.     WORD bottomborder;
  43.     Object *horizic;
  44.     struct LabelText *label;
  45.  
  46.     UWORD visible; // Anzahl der sichtbaren Zeilen
  47.     UWORD linetop; // relative TopEdge der ersten Zeile
  48.     UWORD horiztotal;
  49.     UWORD horizwidth;
  50. };
  51.  
  52. ListClass::ListClass()
  53.     : BoopsiClass(sizeof(struct InstanceData),(ULONG (*)()) &dispatcher,GADGETCLASS,NULL)
  54. {
  55. }
  56.  
  57. ULONG ListClass::dispatcher(Class *cl, Object *o, Msg msg)
  58. {
  59.     struct InstanceData *data;
  60.     ULONG retval = FALSE;
  61.     switch (msg->MethodID)
  62.     {
  63.         case OM_NEW:
  64.         {
  65.             Object *object;
  66.             if (object = (Object *) DoSuperMethodA(cl,o,msg))
  67.             {
  68.                 data = (struct InstanceData *) INST_DATA(cl,object);
  69.                 data->tattr = NULL;
  70.                 data->font = NULL;
  71.                 data->spacing = 1;
  72.                 data->members = NULL;
  73.                 data->attached = FALSE;
  74.                 data->top = 0;
  75.                 data->active = -1;
  76.                 data->readonly = FALSE;
  77.                 data->frame = NULL;
  78.                 data->itemheight = 0;
  79.                 data->customHeight = FALSE;
  80.                 data->columns = 25;
  81.                 data->lines = 6;
  82.                 data->labelmark = '_';
  83.                 data->horizleft = 0;
  84.                 data->horiztarget = NULL;
  85.                 data->horizmap = NULL;
  86.                 data->horizadjust = LS_AdjustLeft;
  87.                 TagItemCursorC tic(((struct opSet *) msg)->ops_AttrList);
  88.                 while (!tic.isDone()) {
  89.                     /* register */ ULONG ticData = tic.itemData();
  90.                     switch (tic.itemTag())
  91.                     {
  92.                         case LSA_Font:
  93.                             data->tattr = (struct TextAttr *) ticData;
  94.                             break;
  95.                         case LSA_Spacing:
  96.                             data->spacing = (UWORD) ticData;
  97.                             break;
  98.                         case LSA_Attach:
  99.                             data->members = (struct List *) ticData;
  100.                             data->attached = TRUE;
  101.                             break;
  102.                         case LSA_Top:
  103.                             data->top = (LONG) ticData;
  104.                             break;
  105.                         case LSA_Active:
  106.                             data->active = (LONG) ticData;
  107.                             break;
  108.                         case LSA_ReadOnly:
  109.                             data->readonly = (BOOL) ticData;
  110.                             break;
  111.                         case LSA_Frame:
  112.                             data->frame = (Object *) ticData;
  113.                             break;
  114.                         case LSA_ItemHeight:
  115.                             data->itemheight = (UWORD) ticData;
  116.                             data->customHeight = data->itemheight != 0;
  117.                             break;
  118.                         case LSA_Columns:
  119.                             data->columns = (ULONG) ticData;
  120.                             break;
  121.                         case LSA_Lines:
  122.                             data->lines = (ULONG) ticData;
  123.                             break;
  124.                         case LSA_HorizLeft:
  125.                             data->horizleft = (UWORD) ticData;
  126.                             break;
  127.                         case LSA_HorizTarget:
  128.                             data->horiztarget = (Object *) ticData;
  129.                             break;
  130.                         case LSA_HorizMap:
  131.                             data->horizmap = (struct TagItem *) ticData;
  132.                             break;
  133.                         case LSA_HorizAdjust:
  134.                             data->horizadjust = (ULONG) ticData;
  135.                             break;
  136.                         default:
  137.                             break;
  138.                     };
  139.                     tic.next();
  140.                 };
  141.                 if (data->tattr)
  142.                     data->font = OpenFont(data->tattr);
  143.                 data->label = AllocLText(
  144.                     (STRPTR) ((struct Gadget *) object)->GadgetText,
  145.                     data->tattr,1,0,JAM2,data->labelmark);
  146.                 data->total = countListLength(data);
  147.                 if (!data->customHeight && data->font)
  148.                 {
  149.                     data->itemheight = data->font->tf_YSize;
  150.                 };
  151.                 GetInnerFrame((struct Gadget *) object, data->frame,
  152.                     &data->framebox,&data->frameright,&data->framebottom);
  153.                 calcBorders(cl,(struct Gadget *) object, data);
  154.                 data->horizic = (Object *) NewObject(NULL,ICCLASS,
  155.                     ICA_TARGET, data->horiztarget,
  156.                     ICA_MAP, data->horizmap,
  157.                     TAG_END);
  158.                 retval = (ULONG) object;
  159.             };
  160.             break;
  161.         };
  162.         case OM_DISPOSE:
  163.         {
  164.             data = (struct InstanceData *) INST_DATA(cl,o);
  165.             if (data->font)
  166.                 CloseFont(data->font);
  167.             if (data->horizic)
  168.                 DisposeObject(data->horizic);
  169.             FreeLText(data->label);
  170.             retval = DoSuperMethodA(cl,o,msg);
  171.             break;
  172.         };
  173.         case OM_GET:
  174.         {
  175.             data = (struct InstanceData *) INST_DATA(cl,o);
  176.             switch (((struct opGet *) msg)->opg_AttrID)
  177.             {
  178.                 case GA_Left:
  179.                     *(((struct opGet *) msg)->opg_Storage) = ((struct Gadget *) o)->LeftEdge;
  180.                     retval = TRUE;
  181.                     break;
  182.                 case GA_Top:
  183.                     *(((struct opGet *) msg)->opg_Storage) = ((struct Gadget *) o)->TopEdge;
  184.                     retval = TRUE;
  185.                     break;
  186.                 case GA_Width:
  187.                     *(((struct opGet *) msg)->opg_Storage) = ((struct Gadget *) o)->Width;
  188.                     retval = TRUE;
  189.                     break;
  190.                 case GA_Height:
  191.                     *(((struct opGet *) msg)->opg_Storage) = ((struct Gadget *) o)->Height;
  192.                     retval = TRUE;
  193.                     break;
  194.                 case LSA_Font:
  195.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->tattr;
  196.                     retval = TRUE;
  197.                     break;
  198.                 case LSA_Spacing:
  199.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->spacing;
  200.                     retval = TRUE;
  201.                     break;
  202.                 case LSA_Attach:
  203.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->members;
  204.                     retval = TRUE;
  205.                     break;
  206.                 case LSA_Top:
  207.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->top;
  208.                     retval = TRUE;
  209.                     break;
  210.                 case LSA_Active:
  211.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->active;
  212.                     retval = TRUE;
  213.                     break;
  214.                 case LSA_ReadOnly:
  215.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->readonly;
  216.                     retval = TRUE;
  217.                     break;
  218.                 case LSA_Frame:
  219.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->frame;
  220.                     retval = TRUE;
  221.                     break;
  222.                 case LSA_ItemHeight:
  223.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->itemheight;
  224.                     retval = TRUE;
  225.                     break;
  226.                 case LSA_LeftBorder:
  227.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->leftborder;
  228.                     retval = TRUE;
  229.                     break;
  230.                 case LSA_RightBorder:
  231.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->rightborder;
  232.                     retval = TRUE;
  233.                     break;
  234.                 case LSA_TopBorder:
  235.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->topborder;
  236.                     retval = TRUE;
  237.                     break;
  238.                 case LSA_BottomBorder:
  239.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->bottomborder;
  240.                     retval = TRUE;
  241.                     break;
  242.                 case LSA_AutoWidth:
  243.                     *(((struct opGet *) msg)->opg_Storage) =
  244.                         (ULONG) calcWidth(cl,(struct Gadget *) o, data);
  245.                     retval = TRUE;
  246.                     break;
  247.                 case LSA_AutoHeight:
  248.                     *(((struct opGet *) msg)->opg_Storage) =
  249.                         (ULONG) calcHeight(cl,(struct Gadget *) o, data);
  250.                     retval = TRUE;
  251.                     break;
  252.                 case LSA_Columns:
  253.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->columns;
  254.                     retval = TRUE;
  255.                     break;
  256.                 case LSA_Lines:
  257.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->lines;
  258.                     retval = TRUE;
  259.                     break;
  260.                 case LSA_LabelMark:
  261.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->labelmark;
  262.                     retval = TRUE;
  263.                     break;
  264.                 case LSA_HorizLeft:
  265.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->horizleft;
  266.                     retval = TRUE;
  267.                     break;
  268.                 case LSA_HorizTarget:
  269.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->horiztarget;
  270.                     retval = TRUE;
  271.                     break;
  272.                 case LSA_HorizMap:
  273.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->horizmap;
  274.                     retval = TRUE;
  275.                     break;
  276.                 case LSA_HorizAdjust:
  277.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->horizadjust;
  278.                     retval = TRUE;
  279.                     break;
  280.                 default:
  281.                     retval = DoSuperMethodA(cl,o,msg);
  282.                     break;
  283.             };
  284.             break;
  285.         };
  286.         case OM_SET:
  287.         {
  288.             data = (struct InstanceData *) INST_DATA(cl,o);
  289.             BOOL redrawIt = FALSE;
  290.             TagItemCursorC tic(((struct opSet *) msg)->ops_AttrList);
  291.             while (!tic.isDone()) {
  292.                 /* register */ ULONG ticData = tic.itemData();
  293.                 switch (tic.itemTag())
  294.                 {
  295.                     case GA_Width:
  296.                         if (data->frame)
  297.                             SetAttrs(data->frame,IA_Width,ticData,TAG_END);
  298.                         data->framebox.Width = ticData
  299.                             - data->framebox.Left - data->frameright;
  300.                         break;
  301.                     case GA_Height:
  302.                         if (data->frame)
  303.                             SetAttrs(data->frame,IA_Height,ticData,TAG_END);
  304.                         data->framebox.Height = ticData
  305.                             - data->framebox.Top - data->framebottom;
  306.                         break;
  307.                     case LSA_Font:
  308.                         if (data->font)
  309.                         {
  310.                             CloseFont(data->font);
  311.                             data->font = NULL;
  312.                         };
  313.                         data->tattr = (struct TextAttr *) ticData;
  314.                         if (data->tattr)
  315.                             data->font = OpenFont(data->tattr);
  316.                         if (!data->customHeight && data->font)
  317.                         {
  318.                             data->itemheight = data->font->tf_YSize;
  319.                         };
  320.                         data->total = countListLength(data);
  321.                         ChangeLTextFont(data->label,data->tattr);
  322.                         calcBorders(cl,(struct Gadget *) o, data);
  323.                         break;
  324.                     case LSA_Spacing:
  325.                         data->spacing = (UWORD) ticData;
  326.                         redrawIt = TRUE;
  327.                         break;
  328.                     case LSA_Attach:
  329.                         if (ticData != ~0)
  330.                             data->members = (struct List *) ticData;
  331.                         data->total = countListLength(data);
  332.                         data->attached = TRUE;
  333.                         redrawIt = TRUE;
  334.                         break;
  335.                     case LSA_Detach:
  336.                         if ((BOOL) ticData)
  337.                             data->attached = FALSE;
  338.                         redrawIt = TRUE;
  339.                         break;
  340.                     case LSA_Top:
  341.                         data->top = (LONG) ticData;
  342.                         redrawIt = TRUE;
  343.                         break;
  344.                     case LSA_Active:
  345.                         data->active = (LONG) ticData;
  346.                         redrawIt = TRUE;
  347.                         break;
  348.                     case LSA_ReadOnly:
  349.                         data->readonly = (BOOL) ticData;
  350.                         redrawIt = TRUE;
  351.                         break;
  352.                     case LSA_ItemHeight:
  353.                         data->itemheight = (UWORD) ticData;
  354.                         data->customHeight = data->itemheight != 0;
  355.                         redrawIt = TRUE;
  356.                         break;
  357.                     case LSA_Next:
  358.                         (data->active)++;
  359.                         if (data->active >= data->total)
  360.                             data->active = 0;
  361.                         redrawIt = TRUE;
  362.                         break;
  363.                     case LSA_Prev:
  364.                         if (data->active == 0)
  365.                             data->active = data->total - 1
  366.                         else
  367.                             (data->active)--;
  368.                         redrawIt = TRUE;
  369.                         break;
  370.                     case LSA_Columns:
  371.                         data->columns = (ULONG) ticData;
  372.                         break;
  373.                     case LSA_Lines:
  374.                         data->lines = (ULONG) ticData;
  375.                         break;
  376.                     case LSA_HorizLeft:
  377.                         data->horizleft = (UWORD) ticData;
  378.                         redrawIt = TRUE;
  379.                         break;
  380.                     case LSA_HorizTarget:
  381.                         data->horiztarget = (Object *) ticData;
  382.                         if (data->horizic)
  383.                         {
  384.                             SetAttrs(data->horizic,ICA_TARGET,data->horiztarget,TAG_END);
  385.                         };
  386.                         break;
  387.                     case LSA_HorizMap:
  388.                         data->horizmap = (struct TagItem *) ticData;
  389.                         if (data->horizic)
  390.                         {
  391.                             SetAttrs(data->horizic,ICA_MAP,data->horizmap,TAG_END);
  392.                         };
  393.                         break;
  394.                     case LSA_HorizAdjust:
  395.                         data->horizadjust = (ULONG) ticData;
  396.                         redrawIt = TRUE;
  397.                         break;
  398.                     default:
  399.                         break;
  400.                 };
  401.                 tic.next();
  402.             };
  403.             retval = DoSuperMethodA(cl,o,msg);
  404.             if (data->itemheight == 0)
  405.             {
  406.                 if (data->font)
  407.                     data->itemheight = data->font->tf_YSize;
  408.             };
  409.             if (redrawIt)
  410.             {
  411.                 render(cl,(struct Gadget *) o,
  412.                     (struct gpRender *) msg, data);
  413.             };
  414.             break;
  415.         };
  416.         case OM_UPDATE:
  417.         {
  418.             data = (struct InstanceData *) INST_DATA(cl,o);
  419.             BOOL redrawIt = FALSE;
  420.             TagItemCursorC tic(((struct opSet *) msg)->ops_AttrList);
  421.             while (!tic.isDone()) {
  422.                 /* register */ ULONG ticData = tic.itemData();
  423.                 switch (tic.itemTag())
  424.                 {
  425.                     case LSA_Top:
  426.                         if (data->top != (LONG) ticData)
  427.                         {
  428.                             data->top = (LONG) ticData;
  429.                             redrawIt = TRUE;
  430.                         };
  431.                         break;
  432.                     case LSA_Active:
  433.                         if (data->active != (LONG) ticData)
  434.                         {
  435.                             data->active = (LONG) ticData;
  436.                             redrawIt = TRUE;
  437.                         };
  438.                         break;
  439.                     case LSA_Next:
  440.                         (data->active)++;
  441.                         if (data->active >= data->total)
  442.                             data->active = 0;
  443.                         redrawIt = TRUE;
  444.                         break;
  445.                     case LSA_Prev:
  446.                         if (data->active == 0)
  447.                             data->active = data->total - 1
  448.                         else
  449.                             (data->active)--;
  450.                         redrawIt = TRUE;
  451.                         break;
  452.                     case LSA_HorizLeft:
  453.                         if (data->horizleft != (UWORD) ticData)
  454.                         {
  455.                             data->horizleft = (UWORD) ticData;
  456.                             redrawIt = TRUE;
  457.                         };
  458.                         break;
  459.                     default:
  460.                         break;
  461.                 };
  462.                 tic.next();
  463.             };
  464. //            retval = DoSuperMethodA(cl,o,msg);
  465.             if (redrawIt)
  466.             {
  467.                 render(cl,(struct Gadget *) o,
  468.                     (struct gpRender *) msg, data, FALSE);
  469.             };
  470.             break;
  471.         };
  472.         case GM_RENDER:
  473.         {
  474.             data = (struct InstanceData *) INST_DATA(cl,o);
  475.             retval = render(cl,(struct Gadget *) o,
  476.                 (struct gpRender *) msg,data, TRUE);
  477.             break;
  478.         };
  479.         case GM_HITTEST:
  480.         {
  481.             retval = GMR_GADGETHIT;
  482.             break;
  483.         };
  484.         case GM_GOACTIVE:
  485.         {
  486.             data = (struct InstanceData *) INST_DATA(cl,o);
  487.             if (((struct gpInput *) msg)->gpi_IEvent && !data->readonly)
  488.             {
  489.                 ((struct Gadget *) msg)->Flags |= GFLG_SELECTED;
  490.                 struct gpInput *gpi = (struct gpInput *) msg;
  491.                 ULONG a = gpi->gpi_Mouse.Y / (data->itemheight + data->spacing);
  492.                 data->active = data->top + a;
  493.                 if (data->active >= data->total)
  494.                     data->active = data->total-1;
  495.                 render(cl,(struct Gadget *) o,
  496.                     (struct gpRender *) msg,data,FALSE);
  497.                 if (data->active == -1)
  498.                     retval = GMR_NOREUSE
  499.                 else
  500.                     retval = GMR_NOREUSE|GMR_VERIFY;
  501.             }
  502.             else
  503.                 retval = GMR_NOREUSE;
  504.             break;
  505.         };
  506.         case GM_GOINACTIVE:
  507.         {
  508.             data = (struct InstanceData *) INST_DATA(cl,o);
  509.             ((struct Gadget *) o)->Flags &= ~GFLG_SELECTED;
  510.             render(cl,(struct Gadget *) o,
  511.                 (struct gpRender *) msg,data,FALSE);
  512.             break;
  513.         };
  514.         case GM_HANDLEINPUT:
  515.         {
  516.             data = (struct InstanceData *) INST_DATA(cl,o);
  517.             struct gpInput *gpi = (struct gpInput *) msg;
  518.             struct InputEvent *ie = gpi->gpi_IEvent;
  519.             BOOL mouseOverGadget = ((gpi->gpi_Mouse.X >= 0) &&
  520.                     (gpi->gpi_Mouse.X < ((struct Gadget *) o)->Width) &&
  521.                     (gpi->gpi_Mouse.Y >= 0) &&
  522.                     (gpi->gpi_Mouse.Y < ((struct Gadget *) o)->Height));
  523.             if (mouseOverGadget)
  524.             {
  525.                 if (!(((struct Gadget *) o)->Flags & GFLG_SELECTED))
  526.                 {
  527.                     ((struct Gadget *) o)->Flags |= GFLG_SELECTED;
  528.                     render(cl,(struct Gadget *) o,
  529.                         (struct gpRender *) msg,data);
  530.                 };
  531.             };
  532.             else {
  533.                 if (((struct Gadget *) o)->Flags & GFLG_SELECTED)
  534.                 {
  535.                     ((struct Gadget *) o)->Flags &= ~GFLG_SELECTED;
  536.                     render(cl,(struct Gadget *) o,
  537.                         (struct gpRender *) msg,data);
  538.                 };
  539.             };
  540.             switch (ie->ie_Class)
  541.             {
  542.                 case IECLASS_RAWMOUSE:
  543.                 {
  544.                     switch (ie->ie_Code)
  545.                     {
  546.                         case SELECTUP:
  547.                             if (mouseOverGadget)
  548.                             {
  549.                                 retval = GMR_NOREUSE | GMR_VERIFY;
  550.                             }
  551.                             else {
  552.                                 retval = GMR_NOREUSE;
  553.                             };
  554.                             break;
  555.                         case MENUDOWN:
  556.                             retval = GMR_REUSE;
  557.                             break;
  558.                         default:
  559.                             retval = GMR_MEACTIVE;
  560.                             break;
  561.                     };
  562.                     break;
  563.                 };
  564.                 default:
  565.                     retval = GMR_MEACTIVE;
  566.                     break;
  567.             };
  568.             break;
  569.         };
  570.         default:
  571.         {
  572.             retval = DoSuperMethodA(cl,o,msg);
  573.             break;
  574.         };
  575.     };
  576.     return retval;
  577. }
  578.  
  579. ULONG ListClass::render(Class *cl, struct Gadget *g,
  580.     struct gpRender *msg, struct InstanceData *data, BOOL fullrender)
  581. {
  582.     static UWORD ditherData[] = { 0x1111,0x4444 };
  583.  
  584.     struct RastPort *rp;
  585.     struct GadgetInfo *ginfo;
  586.     if (msg->MethodID == OM_SET || msg->MethodID == OM_UPDATE)
  587.         ginfo = ((struct opSet *) msg)->ops_GInfo
  588.     else
  589.         ginfo = msg->gpr_GInfo;
  590.     if (!ginfo)
  591.         return TRUE;
  592.     UWORD *pens = ginfo->gi_DrInfo->dri_Pens;
  593.     if (msg->MethodID == GM_RENDER)
  594.         rp = msg->gpr_RPort
  595.     else
  596.         rp = ObtainGIRPort(ginfo);
  597.     if (rp)
  598.     {
  599.         if (fullrender)
  600.         {
  601.             SetDrMd(rp,JAM1);
  602.             SetAPen(rp,pens[BACKGROUNDPEN]);
  603.             RectFill(rp,g->LeftEdge, g->TopEdge,
  604.                 g->LeftEdge + g->Width - 1, g->TopEdge + g->Height - 1);
  605.             countListLength(data);
  606.         };
  607.         if (fullrender && data->frame)
  608.         {
  609.             DrawImageState(rp,(struct Image *) data->frame,
  610.                     g->LeftEdge, g->TopEdge,
  611.                     IDS_NORMAL,ginfo->gi_DrInfo);
  612.         };
  613.         if (fullrender && data->font && g->GadgetText)
  614.         {
  615.             ChangeLTextPens(data->label,pens[TEXTPEN],pens[BACKGROUNDPEN],JAM2);
  616.             PrintLText(rp,data->label,
  617.                 g->LeftEdge, g->TopEdge - data->topborder,
  618.                 g->Width, data->topborder - 4,
  619.                 STADJUST_Center);
  620.         };
  621.         if (data->font)
  622.         {
  623.             WORD lineheight = data->itemheight + data->spacing;
  624.  
  625.             data->visible = data->framebox.Height / lineheight;
  626.             data->linetop = 0;
  627.  
  628.             if (data->total <= data->visible)
  629.                 data->top = 0
  630.             else if (data->top > data->total - data->visible)
  631.                 data->top = data->total - data->visible;
  632.             if (data->active >= data->total)
  633.                 data->active = -1;
  634.             data->horizwidth = data->framebox.Width - 4;
  635.             NotifyTarget(cl,(Object *) g,data,ginfo,0);
  636.  
  637.             if (data->members && data->attached)
  638.             {
  639.                 struct Rectangle rectangle;
  640.                 struct Region *new_region = NewRegion();
  641.                 struct Region *old_region;
  642.                 if (new_region)
  643.                 {
  644.                     rectangle.MinX = g->LeftEdge + data->framebox.Left + 2;
  645.                     rectangle.MinY = g->TopEdge + data->framebox.Top + data->linetop;
  646.                     rectangle.MaxX = g->LeftEdge + data->framebox.Left + data->framebox.Width - 2;
  647.                     rectangle.MaxY = g->TopEdge + data->framebox.Top + data->framebox.Height - 2;
  648.                     if (OrRectRegion(new_region,&rectangle))
  649.                     {
  650.                         if (ginfo->gi_Window->Flags & WFLG_WINDOWREFRESH)
  651.                         {
  652.                             EndRefresh(ginfo->gi_Window,FALSE);
  653.                             old_region = InstallClipRegion(ginfo->gi_Window->WLayer,new_region);
  654.                             BeginRefresh(ginfo->gi_Window);
  655.                         }
  656.                         else {
  657.                             old_region = InstallClipRegion(ginfo->gi_Window->WLayer,new_region);
  658.                         };
  659.  
  660.                         LONG top = 0;
  661.                         struct Node *topobject = data->members->lh_Head;
  662.                         while (top < data->top && topobject->ln_Succ) {
  663.                             top++;
  664.                             topobject = topobject->ln_Succ;
  665.                         };
  666.                         ULONG leftpixel = g->LeftEdge + data->framebox.Left + 2 - data->horizleft;
  667.                         ULONG toppixel = g->TopEdge + data->framebox.Top + data->linetop;
  668.                         ULONG lines = 0;
  669.                         SetFont(rp,data->font);
  670.                         while (lines < data->visible && topobject->ln_Succ) {
  671.                             SetDrMd(rp,JAM1);
  672.                             UWORD textpen = TEXTPEN;
  673.                             if (top == data->active)
  674.                             {
  675.                                 SetAPen(rp,pens[FILLPEN]);
  676.                                 RectFill(rp,g->LeftEdge + data->framebox.Left,
  677.                                     toppixel,
  678.                                     g->LeftEdge + data->framebox.Left + data->framebox.Width - 1,
  679.                                     toppixel + data->itemheight - 1);
  680.                                 textpen = FILLTEXTPEN;
  681.                             }
  682.                             else {
  683.                                 SetAPen(rp,pens[BACKGROUNDPEN]);
  684.                                 RectFill(rp,g->LeftEdge + data->framebox.Left,
  685.                                     toppixel,
  686.                                     g->LeftEdge + data->framebox.Left + data->framebox.Width - 1,
  687.                                     toppixel + data->itemheight - 1);
  688.                             };
  689.                             if (topobject->ln_Name)
  690.                             {
  691.                                 SetAPen(rp,pens[textpen]);
  692.                                 Move(rp,leftpixel, toppixel +
  693.                                         (data->itemheight - data->font->tf_YSize + 1) / 2
  694.                                         + data->font->tf_Baseline);
  695.                                 Text(rp,topobject->ln_Name,strlen(topobject->ln_Name));
  696.                             };
  697.                             toppixel += lineheight;
  698.                             top++;
  699.                             lines++;
  700.                             topobject = topobject->ln_Succ;
  701.                         };
  702.                         if (ginfo->gi_Window->Flags & WFLG_WINDOWREFRESH)
  703.                         {
  704.                             EndRefresh(ginfo->gi_Window,FALSE);
  705.                             InstallClipRegion(ginfo->gi_Window->WLayer,old_region);
  706.                             BeginRefresh(ginfo->gi_Window);
  707.                         }
  708.                         else {
  709.                             InstallClipRegion(ginfo->gi_Window->WLayer,old_region);
  710.                         };
  711.                     };
  712.                     DisposeRegion(new_region);
  713.                 };
  714.             };
  715.         };
  716.         if (g->Flags & GFLG_DISABLED)
  717.         {
  718.             SetDrMd(rp,JAM1);
  719.             SetAPen(rp,pens[TEXTPEN]);
  720.             SetAfPt(rp,ditherData,1);
  721.             RectFill(rp,g->LeftEdge, g->TopEdge,
  722.                 g->LeftEdge + g->Width - 1, g->TopEdge + g->Height - 1);
  723.             SetAfPt(rp,NULL,0);
  724.         };
  725.         if (msg->MethodID != GM_RENDER)
  726.             ReleaseGIRPort(rp);
  727.         return TRUE;
  728.     };
  729.     return FALSE;
  730. }
  731.  
  732. // *************************************************************
  733.  
  734. ULONG ListClass::countListLength(struct InstanceData *data)
  735. {
  736.     data->horiztotal = 0;
  737.     if (!data->members)
  738.         return 0;
  739.     ULONG ll = 0;
  740.     UWORD total = 0;
  741.     struct Node *n;
  742.     struct IntuiText it;
  743.     it.ITextFont = data->tattr;
  744.     for (n = data->members->lh_Head; n->ln_Succ; n = n->ln_Succ)
  745.     {
  746.         if (n->ln_Name)
  747.         {
  748.             it.IText = (STRPTR) n->ln_Name;
  749.             UWORD t = IntuiTextLength(&it);
  750.             if (t > total)
  751.                 total = t;
  752.         };
  753.         ll++;
  754.     };
  755.     data->horiztotal = total;
  756.     return ll;
  757. }
  758.  
  759. // *************************************************************
  760.  
  761. VOID ListClass::NotifyTarget(Class *cl, Object *o,
  762.     struct InstanceData *data, struct GadgetInfo *ginfo, ULONG flags)
  763. {
  764.     struct TagItem tt[4];
  765.     tt[0].ti_Tag = LSA_Top;
  766.     tt[0].ti_Data = data->top;
  767.     tt[1].ti_Tag = LSA_Visible;
  768.     tt[1].ti_Data = data->visible;
  769.     tt[2].ti_Tag = LSA_Total;
  770.     tt[2].ti_Data = data->total;
  771.     tt[3].ti_Tag = TAG_END;
  772.     DoSuperMethod(cl,o,OM_NOTIFY,tt,ginfo,flags);
  773.     if (data->horizic && data->horiztarget)
  774.     {
  775.         tt[0].ti_Tag = LSA_HorizLeft;
  776.         tt[0].ti_Data = data->horizleft;
  777.         tt[1].ti_Tag = LSA_HorizWidth;
  778.         tt[1].ti_Data = data->horizwidth;
  779.         tt[2].ti_Tag = LSA_HorizTotal;
  780.         tt[2].ti_Data = data->horiztotal;
  781.         tt[3].ti_Tag = TAG_END;
  782.         DoMethod(data->horizic,OM_UPDATE,tt,ginfo,flags);
  783.     };
  784. }
  785.  
  786. // *************************************************************
  787.  
  788. VOID ListClass::calcBorders(Class *cl, struct Gadget *g,
  789.         struct InstanceData *data)
  790. {
  791.     data->leftborder = 0;
  792.     data->rightborder = 0;
  793.     data->topborder = 0;
  794.     data->bottomborder = 0;
  795.     if (g->GadgetText && data->tattr)
  796.     {
  797.         data->topborder = data->tattr->ta_YSize + 4;
  798.     };
  799. }
  800.  
  801. WORD ListClass::calcWidth(Class *cl, struct Gadget *g,
  802.         struct InstanceData *data)
  803. {
  804.     if (data->tattr)
  805.     {
  806.         UWORD cols = data->columns;
  807.         if (cols == 0)
  808.             cols = 16;
  809.         return MeasureTextLength("0",data->tattr)*cols + 8;
  810.     };
  811.     return 100;
  812. }
  813.  
  814. WORD ListClass::calcHeight(Class *cl, struct Gadget *g,
  815.         struct InstanceData *data)
  816. {
  817.     if (data->itemheight == 0)
  818.         return 60;
  819.     UWORD lines = data->lines;
  820.     if (!lines)
  821.         data->lines = 6;
  822.     return (data->itemheight + data->spacing) * lines + 4;
  823. }
  824.  
  825. // *************************************************************
  826.  
  827. ListClass BListC::lic;
  828.  
  829. // *************************************************************
  830.  
  831.