home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d562 / intuisup.lha / Intuisup / Gadgets / source.lzh / gadgets3.c < prev    next >
C/C++ Source or Header  |  1991-10-19  |  23KB  |  743 lines

  1.         /*************************************
  2.          *                                   *
  3.          *            Gadgets v2.0           *
  4.          *   by Torsten Jürgeleit in 05/91   *
  5.          *                                   *
  6.          *          Routines - Part 3        *
  7.          *                                   *
  8.          *************************************/
  9.  
  10.     /* Includes */
  11.  
  12. #include <exec/types.h>
  13. #include <exec/memory.h>
  14. #include <devices/inputevent.h>
  15. #include <intuition/intuition.h>
  16. #include <functions.h>
  17. #include <string.h>
  18. #include "/render/render.h"
  19. #include "/texts/texts.h"
  20. #include "/borders/borders.h"
  21. #include "gadgets.h"
  22. #include "imports.h"
  23.  
  24.     /* Refresh gadget */
  25.  
  26.    VOID
  27. refresh_gadget(struct ExtendedGadget  *egad)
  28. {
  29.    struct GadgetList      *gl = egad->eg_GadgetList;
  30.    struct RenderInfo      *ri = gl->gl_RenderInfo;
  31.    struct GadgetData      *gd = gl->gl_Data + egad->eg_DataEntry;
  32.    struct ExtendedGadget  *first_egad = egad;
  33.    struct Window          *win = gl->gl_Window;
  34.    struct RastPort        *rp = win->RPort;
  35.    struct Gadget          *gad;
  36.    struct Image           *image;
  37.    APTR  render;
  38.    UBYTE flags;
  39.    SHORT left_edge, top_edge, width, xoffset;
  40.  
  41.    /* render object text - rendering first because of ghosting by GADGDISABLED */
  42.    switch (gd->gd_Type) {
  43.       case GADGET_DATA_TYPE_CYCLE :
  44.      print_cycle_text(egad);
  45.      break;
  46.       case GADGET_DATA_TYPE_COUNT :
  47.      print_count_text(egad);
  48.      break;
  49.       case GADGET_DATA_TYPE_LISTVIEW :
  50.      print_list_view_text(egad);
  51.      break;
  52.    }
  53.    /* render all gadgets belonging to this object */
  54.    do {
  55.       gad   = &egad->eg_Gadget;
  56.       flags = egad->eg_Flags;
  57.       /* draw additional border or image if any */
  58.       if (flags & (EXTENDED_GADGET_FLAG_RENDER_BORDER |
  59.                        EXTENDED_GADGET_FLAG_RENDER_IMAGE)) {
  60.      left_edge = gad->LeftEdge;
  61.      top_edge  = gad->TopEdge;
  62.      if (flags & EXTENDED_GADGET_FLAG_RENDER_BORDER) {
  63.         DrawBorder(rp, (struct Border *)egad->eg_Render, (LONG)
  64.                          left_edge, (LONG)top_edge);
  65.      } else {
  66.         image     = (struct Image *)egad->eg_Render;
  67.         xoffset   = (gd->gd_Flags & GADGET_DATA_FLAG_NO_BORDER ?
  68.                    IMAGE_HORIZ_OFFSET : IMAGE_HORIZ_OFFSET + 2);
  69.         top_edge += (SHORT)(gad->Height - image->Height) / 2;
  70.         width     = gad->Width;
  71.         switch (egad->eg_Type) {
  72.            case EXTENDED_GADGET_TYPE_CYCLE :
  73.           left_edge += xoffset;
  74.           break;
  75.            case EXTENDED_GADGET_TYPE_COUNT :
  76.           DrawImage(rp, &ri->ri_Images[IMAGE_COUNT_RIGHT], (LONG)
  77.                    (left_edge + width - image->Width - xoffset),
  78.                                 (LONG)top_edge);
  79.           left_edge += xoffset;
  80.           break;
  81.            default :
  82.           left_edge += (SHORT)(width - image->Width) / 2;
  83.           break;
  84.         }
  85.         DrawImage(rp, image, (LONG)left_edge, (LONG)top_edge);
  86.      }
  87.       }
  88.       /* special refresh for disabled selected toggle select gadgets to force correct ghosting */
  89.       if ((gad->Activation & TOGGLESELECT) && (gad->Flags &
  90.           (GADGDISABLED | SELECTED)) == (GADGDISABLED | SELECTED)) {
  91.      render            = gad->GadgetRender;
  92.      gad->GadgetRender = gad->SelectRender;
  93.      gad->Flags       &= ~SELECTED;
  94.      RefreshGList(gad, win, (LONG)NULL, 1L);
  95.      gad->Flags       |= SELECTED;
  96.      gad->GadgetRender = render;
  97.       } else {
  98.      RefreshGList(gad, win, (LONG)NULL, 1L);
  99.       }
  100.    } while (egad = egad->eg_NextGadget);
  101.    print_gadget_text(first_egad);
  102. }
  103.     /* Change gadget */
  104.  
  105.    VOID
  106. change_gadget(struct ExtendedGadget  *egad)
  107. {
  108.    struct GadgetList    *gl = egad->eg_GadgetList;
  109.    struct Window        *win = gl->gl_Window;
  110.    struct Gadget        *gad = &egad->eg_Gadget;
  111.    struct PropInfo      *pinfo;
  112.    struct Image         *image;
  113.    struct MXData        *mx;
  114.    struct SliderData    *sl;
  115.    struct CycleData     *cy;
  116.    struct ScrollerData  *sc;
  117.    struct ListViewData  *lv;
  118.    struct PaletteData   *pd;
  119.    VOID   *data = (VOID *)(egad + 1);
  120.    UBYTE  displayed = gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED;
  121.    USHORT i, data_entry = egad->eg_DataEntry;
  122.    ULONG  min, max, num, body, pot;
  123.  
  124.    switch ((gl->gl_Data + data_entry)->gd_Type) {
  125.       case GADGET_DATA_TYPE_BUTTON :
  126.       case GADGET_DATA_TYPE_CHECK :
  127.       case GADGET_DATA_TYPE_STRING :
  128.       case GADGET_DATA_TYPE_INTEGER :
  129.      if (displayed) {
  130.         RefreshGList(gad, win, (LONG)NULL, 1L);
  131.      }
  132.      break;
  133.       case GADGET_DATA_TYPE_MX :
  134.      mx  = data;
  135.      max = mx->mx_TextEntries;
  136.      num = mx->mx_ActiveEntry;
  137.      for (i = 0; i < max; i++) {
  138.         gad = &egad->eg_Gadget;
  139.         if (i == num) {
  140.            gad->Flags |= SELECTED;
  141.            if (displayed) {
  142.           RefreshGList(gad, win, (LONG)NULL, 1L);
  143.            }
  144.         } else {
  145.            if (gad->Flags & SELECTED) {
  146.           gad->Flags &= ~SELECTED;
  147.           if (displayed) {
  148.              RefreshGList(gad, win, (LONG)NULL, 1L);
  149.           }
  150.            }
  151.            
  152.         }
  153.         egad = egad->eg_NextGadget;
  154.      }
  155.      break;
  156.       case GADGET_DATA_TYPE_SLIDER :
  157.      pinfo = (struct PropInfo *)gad->SpecialInfo;
  158.      sl    = data;
  159.      min   = sl->sl_Min;
  160.      max   = (LONG)sl->sl_Max - (LONG)min;
  161.      num   = (LONG)sl->sl_Level - (LONG)min;
  162.      if (sl->sl_Flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  163.         num = max - num;   /* if vert slider then maximum is at top */
  164.      }
  165.      body = calc_prop_body(max + 1, 1L);
  166.      pot  = calc_prop_pot(max + 1, 1L, num);
  167.      if (sl->sl_Flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  168.         if (displayed) {
  169.            NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, 0L,
  170.                              pot, 0L, body, 1L);
  171.         } else {
  172.            pinfo->VertBody = body;
  173.            pinfo->VertPot  = pot;
  174.         }
  175.      } else {
  176.         if (displayed) {
  177.            NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, pot,
  178.                               0L, body, 0L, 1L);
  179.         } else {
  180.            pinfo->HorizBody = body;
  181.            pinfo->HorizPot  = pot;
  182.         }
  183.      }
  184.      break;
  185.       case GADGET_DATA_TYPE_SCROLLER :
  186.      pinfo = (struct PropInfo *)gad->SpecialInfo;
  187.      sc    = data;
  188.      min   = sc->sc_Visible;
  189.      max   = sc->sc_Total;
  190.      num   = sc->sc_Top;
  191.      body  = calc_prop_body(max, min);
  192.      pot   = calc_prop_pot(max, min, num);
  193.      if (sc->sc_Flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  194.         if (displayed) {
  195.            NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, 0L,
  196.                              pot, 0L, body, 1L);
  197.         } else {
  198.            pinfo->VertBody = body;
  199.            pinfo->VertPot  = pot;
  200.         }
  201.      } else {
  202.         if (displayed) {
  203.            NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, pot,
  204.                               0L, body, 0L, 1L);
  205.         } else {
  206.            pinfo->HorizBody = body;
  207.            pinfo->HorizPot  = pot;
  208.         }
  209.      }
  210.      break;
  211.       case GADGET_DATA_TYPE_CYCLE :
  212.      cy                = data;
  213.      cy->cy_ActiveText = cy->cy_TextArray[cy->cy_ActiveEntry];
  214.      if (displayed) {
  215.         print_cycle_text(egad);
  216.      }
  217.      break;
  218.       case GADGET_DATA_TYPE_COUNT :
  219.      if (displayed) {
  220.         print_count_text(egad);
  221.      }
  222.      break;
  223.       case GADGET_DATA_TYPE_LISTVIEW :
  224.      pinfo = (struct PropInfo *)gad->SpecialInfo;
  225.      lv    = data;
  226.      min   = lv->lv_VisibleEntries;
  227.      max   = lv->lv_ListEntries;
  228.      num   = lv->lv_TopEntry;
  229.      body  = calc_prop_body(max, min);
  230.      pot   = calc_prop_pot(max, min, num);
  231.      if (displayed) {
  232.         NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, 0L, pot,
  233.                                   0L, body, 1L);
  234.         print_list_view_text(egad);
  235.      } else {
  236.         pinfo->VertBody = body;
  237.         pinfo->VertPot  = pot;
  238.      }
  239.      break;
  240.       case GADGET_DATA_TYPE_PALETTE :
  241.      pd = data;
  242.      if (!(pd->pd_Flags & GADGET_DATA_FLAG_PALETTE_NO_INDICATOR)) {
  243.         image             = (struct Image *)egad->eg_Render;
  244.         image->PlaneOnOff = pd->pd_ActiveColor;
  245.         if (displayed) {
  246.            DrawImage(win->RPort, image, (LONG)(gad->LeftEdge + (SHORT)
  247.              (gad->Width - image->Width) / 2), (LONG)(gad->TopEdge +
  248.                  (SHORT)(gad->Height - image->Height) / 2));
  249.         }
  250.      }
  251.      break;
  252.    }
  253. }
  254.     /* Change count gadget value */
  255.  
  256.    VOID
  257. change_count_gadget(struct ExtendedGadget  *egad)
  258. {
  259.    struct GadgetList    *gl = egad->eg_GadgetList;
  260.    struct Window        *win = gl->gl_Window;
  261.    struct MsgPort       *up  = win->UserPort;
  262.    struct IntuiMessage  *msg;
  263.    struct Gadget        *gad = &egad->eg_Gadget;
  264.    struct CountData     *co = (struct CountData *)(egad + 1);
  265.    LONG   new_count, min = co->co_Min, max = co->co_Max, count = co->co_Value;
  266.    ULONG  class, old_idcmp_flags = win->IDCMPFlags;
  267.    USHORT distance, new_delay, max_delay = MAX_COUNT_DELAY,
  268.       delay = MAX_COUNT_DELAY;
  269.    SHORT  count_change, middle = gad->LeftEdge + gad->Width / 2;
  270.    BOOL   keepon = TRUE;
  271.  
  272.    ModifyIDCMP(win, (LONG)(GADGETUP | MOUSEBUTTONS | INTUITICKS));
  273.    /* calc new delay and change value with new mouse pos */
  274.    if (win->MouseX > middle) {
  275.       count_change = +1;
  276.       if (count < max) {
  277.      count++;
  278.       }
  279.    } else {
  280.       count_change = -1;
  281.       if (count > min) {
  282.      count--;
  283.       }
  284.    }
  285.    co->co_Value = count;
  286.    print_count_text(egad);
  287.    do {
  288.       /* calc new delay and change value with new mouse pos */
  289.       if (win->MouseX > middle) {
  290.      distance     = win->MouseX - middle;
  291.      count_change = +1;
  292.       } else {
  293.      if (win->MouseX < 0) {
  294.         distance = middle + win->MouseX;
  295.      } else {
  296.         distance = middle - win->MouseX;
  297.      }
  298.      count_change = -1;
  299.       }
  300.       if (distance > MAX_COUNT_DISTANCE) {
  301.      distance = MAX_COUNT_DISTANCE;
  302.       }
  303.       new_delay = MAX_COUNT_DELAY - distance / MAX_COUNT_STEP_SIZE;
  304.       if (new_delay != max_delay) {
  305.      max_delay = delay = new_delay;
  306.       }
  307.       if (msg = (struct IntuiMessage *)GetMsg(up)) {
  308.      class = msg->Class;
  309.      ReplyMsg((struct Message *)msg);
  310.      if (class == INTUITICKS) {
  311.         if (max_delay) {
  312.            /* delayed change of count value */
  313.            if (! --delay) {
  314.           new_count = count + count_change;
  315.           if (new_count < min) {
  316.              new_count = min;
  317.           } else {
  318.              if (new_count > max) {
  319.             new_count = max;
  320.              }
  321.           }
  322.           /* print new count only if changed */
  323.           if (new_count != count) {
  324.              co->co_Value = count = new_count;
  325.              print_count_text(egad);
  326.           }
  327.           delay = max_delay;
  328.            }
  329.         }
  330.      } else {
  331.         keepon = FALSE;
  332.      }
  333.       }
  334.       if (! max_delay) {
  335.      /* undelayed change of count value */
  336.      if ((count + count_change) >= min && (count + count_change) <=
  337.                                       max) {
  338.         co->co_Value = count += count_change;
  339.         print_count_text(egad);
  340.         timer_delay(0L, MIN_COUNT_DELAY_MICROS);
  341.      }
  342.       }
  343.    } while (keepon == TRUE);
  344.    ModifyIDCMP(win, old_idcmp_flags);
  345.    /* restore normal count gadget state (unselected) */
  346.    if ((gad->Flags & GADGHIGHBITS) == GADGHCOMP) {
  347.       RefreshGList(gad, win, (LONG)NULL, 1L);   /* complement gadget select box */
  348.    }
  349.    gad->Flags &= ~SELECTED;
  350.    RefreshGList(gad, win, (LONG)NULL, 1L);
  351. }
  352.     /* Delay function - can't use Delay() from DOS (no process) */
  353.  
  354.    VOID
  355. timer_delay(ULONG seconds, ULONG micros)
  356. {
  357.    struct MsgPort      *port;
  358.    struct timerequest  *timer;
  359.  
  360.    if (port = CreatePort(NULL, 0L)) {
  361.       if (timer = (struct timerequest *)CreateExtIO(port, (LONG)
  362.                           sizeof(struct timerequest))) {
  363.      if (!OpenDevice(TIMERNAME, (LONG)UNIT_VBLANK, (struct IORequest *)
  364.                                    timer, 0L)) {
  365.         timer->tr_node.io_Command = TR_ADDREQUEST;
  366.         timer->tr_time.tv_secs    = seconds;
  367.         timer->tr_time.tv_micro   = micros;
  368.         DoIO((struct IORequest *)timer);
  369.         CloseDevice((struct IORequest *)timer);
  370.      }
  371.      DeleteExtIO((struct IORequest *)timer);
  372.       }
  373.       DeletePort(port);
  374.    }
  375. }
  376.     /* Print gadget text */
  377.  
  378.    VOID
  379. print_gadget_text(struct ExtendedGadget  *egad)
  380. {
  381.    struct GadgetList  *gl = egad->eg_GadgetList;
  382.    struct RenderInfo  *ri = gl->gl_RenderInfo;
  383.    struct Window      *win = gl->gl_Window;
  384.    struct RastPort    *rp = win->RPort;
  385.    struct GadgetData  *gd = gl->gl_Data + egad->eg_DataEntry;
  386.    struct Gadget      *gad = &egad->eg_Gadget;
  387.    struct TextAttr    *text_attr;
  388.    BYTE   c, *text, *buffer;
  389.    LONG   len;
  390.    USHORT save_left_edge, left_edge, top_edge, pos, flags = (gd->gd_Flags &
  391.         GADGET_DATA_FLAG_TEXT_COLOR2 ? TEXT_DATA_FLAG_ABSOLUTE_POS |
  392.                TEXT_DATA_FLAG_COLOR2 : TEXT_DATA_FLAG_ABSOLUTE_POS);
  393.  
  394.    if (text = egad->eg_Text) {
  395.       left_edge = gad->LeftEdge + egad->eg_TextLeftEdge;
  396.       top_edge  = gad->TopEdge + egad->eg_TextTopEdge;
  397.       if (!(text_attr = gd->gd_TextAttr)) {
  398.      text_attr = &ri->ri_TextAttr;
  399.       }
  400.       if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOT_KEY) {
  401.      len = strlen(text) + 1;
  402.      pos = egad->eg_HotkeyPos;
  403.      if (buffer = AllocMem(len, (LONG)MEMF_PUBLIC)) {
  404.         strcpy(buffer, text);
  405.         *(buffer + pos - 1) = '\0';
  406.         left_edge          += print_text(ri, win, &buffer[0],
  407.         left_edge, top_edge, TEXT_DATA_TYPE_TEXT, flags, text_attr);
  408.         c                   = *(buffer + pos + 1);
  409.         *(buffer + pos + 1) = '\0';
  410.         /* print and mark hot key in gadget text */
  411.         save_left_edge = left_edge;
  412.         left_edge     += print_text(ri, win, &buffer[pos], left_edge,
  413.                top_edge, TEXT_DATA_TYPE_TEXT, flags, text_attr);
  414.         SetDrMd(rp, (LONG)JAM1);
  415.         SetAPen(rp, (LONG)(gd->gd_Flags & GADGET_DATA_FLAG_TEXT_COLOR2 ?
  416.                     ri->ri_TextPen2 : ri->ri_TextPen1));
  417.         RectFill(rp, (LONG)save_left_edge, (LONG)(top_edge +
  418.              text_attr->ta_YSize), (LONG)(left_edge - 1), (LONG)
  419.                       (top_edge + text_attr->ta_YSize));
  420.         *(buffer + pos + 1) = c;
  421.         print_text(ri, win, &buffer[pos + 1], left_edge, top_edge,
  422.                      TEXT_DATA_TYPE_TEXT, flags, text_attr);
  423.         FreeMem(buffer, len);
  424.      } else {
  425.         print_text(ri, win, text, left_edge, top_edge,
  426.                      TEXT_DATA_TYPE_TEXT, flags, text_attr);
  427.      }
  428.       } else {
  429.      print_text(ri, win, text, left_edge, top_edge, TEXT_DATA_TYPE_TEXT,
  430.                               flags, text_attr);
  431.       }
  432.    }
  433. }
  434.     /* Print cycle text */
  435.  
  436.    VOID
  437. print_cycle_text(struct ExtendedGadget  *egad)
  438. {
  439.    struct GadgetList  *gl = egad->eg_GadgetList;
  440.    struct RenderInfo  *ri = gl->gl_RenderInfo;
  441.    struct Window      *win = gl->gl_Window;
  442.    struct RastPort    *rp = win->RPort;
  443.    struct CycleData   *cy = (struct CycleData *)
  444.                    (gl->gl_Gadgets[egad->eg_DataEntry] + 1);
  445.    struct TextAttr    *text_attr = cy->cy_TextAttr;
  446.    struct IntuiText   itext;
  447.    BYTE   *text = cy->cy_ActiveText;
  448.    USHORT flags = (cy->cy_Flags & GADGET_DATA_FLAG_TEXT_COLOR2 ?
  449.                TEXT_DATA_FLAG_ABSOLUTE_POS | TEXT_DATA_FLAG_COLOR2 :
  450.                            TEXT_DATA_FLAG_ABSOLUTE_POS),
  451.       left_edge = cy->cy_LeftEdge, top_edge = cy->cy_TopEdge,
  452.       width = cy->cy_Width, height = cy->cy_Height;
  453.  
  454.    itext.IText     = (UBYTE *)text;
  455.    itext.ITextFont = text_attr;
  456.    SetDrMd(rp, (LONG)JAM1);
  457.    SetAPen(rp, (LONG)ri->ri_BackPen);
  458.    RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge + width -
  459.                      1), (LONG)(top_edge + height - 1));
  460.    print_text(ri, win, text, left_edge + (SHORT)(width -
  461.         IntuiTextLength(&itext)) / 2, top_edge, TEXT_DATA_TYPE_TEXT,
  462.                               flags, text_attr);
  463. }
  464.     /* Print count text */
  465.  
  466.    VOID
  467. print_count_text(struct ExtendedGadget  *egad)
  468. {
  469.    struct GadgetList  *gl = egad->eg_GadgetList;
  470.    struct RenderInfo  *ri = gl->gl_RenderInfo;
  471.    struct Window      *win = gl->gl_Window;
  472.    struct RastPort    *rp = win->RPort;
  473.    struct CountData   *co = (struct CountData *)
  474.                    (gl->gl_Gadgets[egad->eg_DataEntry] + 1);
  475.    struct TextAttr    *text_attr = co->co_TextAttr;
  476.    USHORT type = (co->co_Flags & GADGET_DATA_FLAG_COUNT_SIGNED_DEC ?
  477.                          TEXT_DATA_TYPE_NUM_SIGNED_DEC :
  478.                        TEXT_DATA_TYPE_NUM_UNSIGNED_DEC),
  479.       flags = (co->co_Flags & GADGET_DATA_FLAG_TEXT_COLOR2 ?
  480.            TEXT_DATA_FLAG_ABSOLUTE_POS | TEXT_DATA_FLAG_PLACE_LEFT |
  481.                TEXT_DATA_FLAG_COLOR2 : TEXT_DATA_FLAG_ABSOLUTE_POS |
  482.                          TEXT_DATA_FLAG_PLACE_LEFT),
  483.       left_edge = co->co_LeftEdge, top_edge = co->co_TopEdge,
  484.       width = co->co_Width, height = co->co_Height;
  485.  
  486.    if ((egad->eg_Gadget.Flags & SELECTED) && (egad->eg_Gadget.Flags &
  487.                            GADGHIGHBITS) == GADGHCOMP) {
  488.       flags |= TEXT_DATA_FLAG_COMPLEMENT;
  489.       SetAPen(rp, (LONG)(ri->ri_BackPen ^ ((1 << ri->ri_ScreenDepth) - 1)));
  490.    } else {
  491.       SetAPen(rp, (LONG)ri->ri_BackPen);
  492.    }
  493.    SetDrMd(rp, (LONG)JAM1);
  494.    RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge + width -
  495.                      1), (LONG)(top_edge + height - 1));
  496.    print_text(ri, win, (BYTE *)co->co_Value, left_edge + width,
  497.                       top_edge, type, flags, text_attr);
  498. }
  499.     /* Print list view text */
  500.  
  501.    VOID
  502. print_list_view_text(struct ExtendedGadget  *egad)
  503. {
  504.    struct GadgetList    *gl = egad->eg_GadgetList;
  505.    struct RenderInfo    *ri = gl->gl_RenderInfo;
  506.    struct Window        *win = gl->gl_Window;
  507.    struct RastPort      *rp = win->RPort;
  508.    struct Layer         *layer = rp->Layer;
  509.    struct Region        *region, *old_region;
  510.    struct Rectangle     rect;
  511.    struct ListViewData  *lv = (struct ListViewData *)
  512.                    (gl->gl_Gadgets[egad->eg_DataEntry] + 1);
  513.    struct TextAttr      *text_attr = lv->lv_TextAttr;
  514.    struct Node          *node = lv->lv_TopNode;
  515.    USHORT i, text_width, flags = (lv->lv_Flags &
  516.               GADGET_DATA_FLAG_TEXT_COLOR2 ? TEXT_DATA_FLAG_COLOR2 |
  517.             TEXT_DATA_FLAG_ABSOLUTE_POS | TEXT_DATA_FLAG_BACK_FILL :
  518.             TEXT_DATA_FLAG_ABSOLUTE_POS | TEXT_DATA_FLAG_BACK_FILL),
  519.           left_edge = lv->lv_LeftEdge, top_edge = lv->lv_TopEdge,
  520.       width = lv->lv_Width, height = lv->lv_Height,
  521.       entries = lv->lv_ListEntries, visible = lv->lv_VisibleEntries,
  522.       entry_height = lv->lv_EntryHeight, top = lv->lv_TopEntry;
  523.  
  524.    /* calc offsets for inner window */
  525.    if (region = NewRegion()) {
  526.       /* install clipping region around list view entry area */
  527.       rect.MinX = left_edge;
  528.       rect.MaxX = left_edge + width - 1;
  529.       rect.MinY = top_edge;
  530.       rect.MaxY = top_edge + height - 1;
  531.       OrRectRegion(region, &rect);
  532.       old_region = InstallClipRegion(layer, region);
  533.       /* print list view entry text with clipping */
  534.       SetDrMd(rp, (LONG)JAM1);
  535.       SetAPen(rp, (LONG)ri->ri_BackPen);
  536.       for (i = visible; i; i--, top++, top_edge += entry_height) {
  537.      if (top < entries) {
  538.         text_width = print_text(ri, win, node->ln_Name, left_edge,
  539.                top_edge, TEXT_DATA_TYPE_TEXT, flags, text_attr);
  540.         if (text_width < width) {
  541.            RectFill(rp, (LONG)(left_edge + text_width), (LONG)top_edge,
  542.                 (LONG)(left_edge + width - 1), (LONG)(top_edge +
  543.                              entry_height - 1));
  544.         }
  545.         node = node->ln_Succ;
  546.      } else {
  547.         break;
  548.      }
  549.       }
  550.       if (i) {
  551.      RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge +
  552.                width - 1), (LONG)(top_edge + i * entry_height - 1));
  553.       }
  554.       /* remove clipping region */
  555.       InstallClipRegion(layer, old_region);
  556.       DisposeRegion(region);
  557.    }
  558. }
  559.     /* Proportional gadget support routines (32 bit !!!) */
  560.  
  561. #asm
  562. ; USHORT = calc_prop_body(max_num, size)(d0.l,d1.l)
  563.     XDEF    _calc_prop_body
  564. _calc_prop_body:
  565.     movem.l    d2-d6,-(sp)
  566.  
  567.     ; --- check max_num
  568.     move.l    d0,d6        ; save max_num in d6
  569.     beq.s    cpb_maximum    ; max_num == 0 ?
  570.     cmp.l    d0,d1        ; size > max_num ?
  571.     bhi.s    cpb_maximum
  572.  
  573.     ; --- multiply size [32 bit] by MAXBODY ($ffff) [16 bit] with 48 bit arithmetic
  574.     moveq    #0,d0        ; clear shift out reg for size
  575.     move.l    d1,d3        ; init result by doing the first add
  576.     moveq    #0,d2        ; clear shift out reg of result
  577.     moveq    #16-2,d4    ; init shift count (MAXBODY has only 16 bits - one add already done)
  578.  
  579. cpb_mul_loop:
  580.     ; --- shift size
  581.     add.l    d1,d1        ; shift left of size
  582.     addx.w    d0,d0        ; save shift out
  583.  
  584.     ; --- inc result
  585.     add.l    d1,d3        ; add shifted size to result
  586.     addx.w    d0,d2        ; add shift out and carry
  587.     dbra    d4,cpb_mul_loop
  588.  
  589.     ; --- divide result [48 bit] by max_num [32 bit] with 48 bit arithmetic
  590.     moveq    #0,d0        ; clear result
  591.     moveq    #0,d1        ; clear shift out reg for divident
  592.     moveq    #0,d4        ; clear sub divisor help reg
  593.     moveq    #32-1,d5    ; init shift count
  594.  
  595. cpb_div_loop:
  596.     ; --- shift result and divident
  597.     add.l    d0,d0        ; shift result
  598.     add.l    d3,d3        ; shift left of lower LONG of divident
  599.     addx.l    d2,d2        ; shift left of upper LONG of divident - add shift out
  600.     addx.w    d1,d1        ; save shift out
  601.  
  602.     ; --- check if upper LONG of divident large enough to sub divisor from
  603.     tst.w    d1        ; any shift out ?
  604.     bne.s    cpb_sub_divisor
  605.     cmp.l    d2,d6        ; upper LONG of divident > divisor ?
  606.     bhi.s    cpb_next_div
  607.  
  608. cpb_sub_divisor:
  609.     sub.l    d6,d2        ; sub divisor from upper LONG of divident
  610.     subx.w    d4,d1        ; sub underflow (d4 = 0) from shift out of upper LONG of divident
  611.     addq.l    #1,d0        ; set bit 0 of result
  612.     
  613. cpb_next_div:
  614.     dbra    d5,cpb_div_loop
  615.  
  616.     ; --- don't return ZERO as prop_body
  617.     tst.w    d0
  618.     bne.s    cpb_exit
  619.     moveq    #1,d0
  620.     
  621. cpb_exit:
  622.     movem.l    (sp)+,d2-d6
  623.     rts
  624.  
  625. cpb_maximum:
  626.     move.l    #$ffff,d0    ; prop_body := MAXBODY
  627.     bra    cpb_exit
  628.  
  629.  
  630. ; USHORT = calc_prop_pot(max_num, size, num)(d0.l,d1.l,d2.l)
  631.     XDEF    _calc_prop_pot
  632. _calc_prop_pot:
  633.     movem.l    d3-d6,-(sp)
  634.  
  635.     ; --- prepare max_num
  636.     move.l    d0,d6        ; save max_num
  637.     beq    cpp_minimum
  638.     sub.l    d1,d6        ; max_num -:= size
  639.     bcs    cpp_minimum
  640.  
  641.     ; --- multiply num by MAXPOT ($ffff) by shift num left by 16
  642.     move.l    d2,d3
  643.     swap    d3
  644.     moveq    #0,d2
  645.     move.w    d3,d2        ; d2 := upper LONG of result
  646.     clr.w    d3        ; d3 := lower LONG of result
  647.  
  648.     ; --- divide result [48 bit] by max_num [32 bit] with 48 bit arithmetic
  649.     moveq    #0,d0        ; clear result
  650.     moveq    #0,d1        ; clear shift out reg for divident
  651.     moveq    #0,d4        ; clear sub divisor help reg
  652.     moveq    #32-1,d5    ; init shift count
  653.  
  654. cpp_div_loop:
  655.     ; --- shift result and divident
  656.     add.l    d0,d0        ; shift result
  657.     add.l    d3,d3        ; shift left of lower LONG of divident
  658.     addx.l    d2,d2        ; shift left of upper LONG of divident - add shift out
  659.     addx.w    d1,d1        ; save shift out
  660.  
  661.     ; --- check if upper LONG of divident large enough to sub divisor from
  662.     tst.w    d1        ; any shift out ?
  663.     bne.s    cpp_sub_divisor
  664.     cmp.l    d2,d6        ; upper LONG of divident > divisor ?
  665.     bhi.s    cpp_next_div
  666.  
  667. cpp_sub_divisor:
  668.     sub.l    d6,d2        ; sub divisor from upper LONG of divident
  669.     subx.w    d4,d1        ; sub underflow (d4 = 0) from shift out of upper LONG of divident
  670.     addq.l    #1,d0        ; set bit 0 of result
  671.     
  672. cpp_next_div:
  673.     dbra    d5,cpp_div_loop
  674.  
  675.     ; --- if pot_value > MAXPOT then return MAXPOT
  676.     cmp.l    #$ffff,d0
  677.     bls    cpp_exit
  678.     move.l    #$ffff,d0    ; prop_pot := MAXPOT
  679.  
  680. cpp_exit:
  681.     movem.l    (sp)+,d3-d6
  682.     rts
  683.  
  684. cpp_minimum:
  685.     moveq    #0,d0        ; prop_pot := 0
  686.     bra    cpp_exit
  687.  
  688.  
  689. ; ULONG = get_prop_pos(max_num, size, pot_value)(d0.l,d1.l,d2.w)
  690.     XDEF    _get_prop_pos
  691. _get_prop_pos:
  692.     movem.l    d3-d6,-(sp)
  693.  
  694.     ; --- prepare max_num
  695.     sub.l    d1,d0        ; max_num -:= size
  696.     bcs    gpp_minimum
  697.  
  698.     ; --- if pot_value ]0..MAXPOT[ then inc pot_value
  699.     move.w    d2,d6        ; save pot value
  700.     beq    gpp_minimum    ; pot_value == 0 ?
  701.     addq.w    #1,d6        ; inc pot_value
  702.     bcs    gpp_exit    ; if pot_value == MAXPOT then return (max_num - size)
  703.  
  704.     ; --- multiply max_num [32 bit] by pot_value [16 bit] with 48 bit arithmetic
  705.     moveq    #0,d1        ; clear shift out reg for max_num
  706.     moveq    #0,d2        ; clear result
  707.     moveq    #0,d3        ; clear shift out reg of result
  708.     moveq    #0,d4        ; reset bit count
  709.     moveq    #16-1,d5    ; init shift count (16 bits from pot_value)
  710.     bra    gpp_check_bit
  711.  
  712. gpp_mul_loop:
  713.     add.l    d0,d0        ; shift left of max_num
  714.     addx.w    d1,d1        ; save shift out
  715.  
  716. gpp_check_bit:
  717.     ; --- check bit of pot_value
  718.     btst    d4,d6
  719.     beq    gpp_next_mul    ; bit set ?
  720.  
  721.     ; --- if bit set then inc result
  722.     add.l    d0,d2        ; add shifted max_num to result
  723.     addx.w    d1,d3        ; add shift out and carry
  724.  
  725. gpp_next_mul:
  726.     addq.w    #1,d4        ; inc bit count
  727.     dbra    d5,gpp_mul_loop
  728.  
  729.     ; --- divide result by MAXPOT ($ffff) by shift num right by 16
  730.     move.w    d3,d2        ; replace lower word (fractional part) of result by shifted out result
  731.     swap    d2        ; d2 := bits 16..47 (integer part) of result
  732.     move.l    d2,d0        ; d0 := prop_pos
  733.  
  734. gpp_exit:
  735.     movem.l    (sp)+,d3-d6
  736.     rts
  737.  
  738. gpp_minimum:
  739.     moveq    #0,d0        ; prop_pos := 0
  740.     bra    gpp_exit
  741.  
  742. #endasm
  743.