home *** CD-ROM | disk | FTP | other *** search
- /*************************************
- * *
- * Gadgets v2.0 *
- * by Torsten Jürgeleit in 05/91 *
- * *
- * Routines - Part 3 *
- * *
- *************************************/
-
- /* Includes */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <devices/inputevent.h>
- #include <intuition/intuition.h>
- #include <functions.h>
- #include <string.h>
- #include "/render/render.h"
- #include "/texts/texts.h"
- #include "/borders/borders.h"
- #include "gadgets.h"
- #include "imports.h"
-
- /* Refresh gadget */
-
- VOID
- refresh_gadget(struct ExtendedGadget *egad)
- {
- struct GadgetList *gl = egad->eg_GadgetList;
- struct RenderInfo *ri = gl->gl_RenderInfo;
- struct GadgetData *gd = gl->gl_Data + egad->eg_DataEntry;
- struct ExtendedGadget *first_egad = egad;
- struct Window *win = gl->gl_Window;
- struct RastPort *rp = win->RPort;
- struct Gadget *gad;
- struct Image *image;
- APTR render;
- UBYTE flags;
- SHORT left_edge, top_edge, width, xoffset;
-
- /* render object text - rendering first because of ghosting by GADGDISABLED */
- switch (gd->gd_Type) {
- case GADGET_DATA_TYPE_CYCLE :
- print_cycle_text(egad);
- break;
- case GADGET_DATA_TYPE_COUNT :
- print_count_text(egad);
- break;
- case GADGET_DATA_TYPE_LISTVIEW :
- print_list_view_text(egad);
- break;
- }
- /* render all gadgets belonging to this object */
- do {
- gad = &egad->eg_Gadget;
- flags = egad->eg_Flags;
- /* draw additional border or image if any */
- if (flags & (EXTENDED_GADGET_FLAG_RENDER_BORDER |
- EXTENDED_GADGET_FLAG_RENDER_IMAGE)) {
- left_edge = gad->LeftEdge;
- top_edge = gad->TopEdge;
- if (flags & EXTENDED_GADGET_FLAG_RENDER_BORDER) {
- DrawBorder(rp, (struct Border *)egad->eg_Render, (LONG)
- left_edge, (LONG)top_edge);
- } else {
- image = (struct Image *)egad->eg_Render;
- xoffset = (gd->gd_Flags & GADGET_DATA_FLAG_NO_BORDER ?
- IMAGE_HORIZ_OFFSET : IMAGE_HORIZ_OFFSET + 2);
- top_edge += (SHORT)(gad->Height - image->Height) / 2;
- width = gad->Width;
- switch (egad->eg_Type) {
- case EXTENDED_GADGET_TYPE_CYCLE :
- left_edge += xoffset;
- break;
- case EXTENDED_GADGET_TYPE_COUNT :
- DrawImage(rp, &ri->ri_Images[IMAGE_COUNT_RIGHT], (LONG)
- (left_edge + width - image->Width - xoffset),
- (LONG)top_edge);
- left_edge += xoffset;
- break;
- default :
- left_edge += (SHORT)(width - image->Width) / 2;
- break;
- }
- DrawImage(rp, image, (LONG)left_edge, (LONG)top_edge);
- }
- }
- /* special refresh for disabled selected toggle select gadgets to force correct ghosting */
- if ((gad->Activation & TOGGLESELECT) && (gad->Flags &
- (GADGDISABLED | SELECTED)) == (GADGDISABLED | SELECTED)) {
- render = gad->GadgetRender;
- gad->GadgetRender = gad->SelectRender;
- gad->Flags &= ~SELECTED;
- RefreshGList(gad, win, (LONG)NULL, 1L);
- gad->Flags |= SELECTED;
- gad->GadgetRender = render;
- } else {
- RefreshGList(gad, win, (LONG)NULL, 1L);
- }
- } while (egad = egad->eg_NextGadget);
- print_gadget_text(first_egad);
- }
- /* Change gadget */
-
- VOID
- change_gadget(struct ExtendedGadget *egad)
- {
- struct GadgetList *gl = egad->eg_GadgetList;
- struct Window *win = gl->gl_Window;
- struct Gadget *gad = &egad->eg_Gadget;
- struct PropInfo *pinfo;
- struct Image *image;
- struct MXData *mx;
- struct SliderData *sl;
- struct CycleData *cy;
- struct ScrollerData *sc;
- struct ListViewData *lv;
- struct PaletteData *pd;
- VOID *data = (VOID *)(egad + 1);
- UBYTE displayed = gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED;
- USHORT i, data_entry = egad->eg_DataEntry;
- ULONG min, max, num, body, pot;
-
- switch ((gl->gl_Data + data_entry)->gd_Type) {
- case GADGET_DATA_TYPE_BUTTON :
- case GADGET_DATA_TYPE_CHECK :
- case GADGET_DATA_TYPE_STRING :
- case GADGET_DATA_TYPE_INTEGER :
- if (displayed) {
- RefreshGList(gad, win, (LONG)NULL, 1L);
- }
- break;
- case GADGET_DATA_TYPE_MX :
- mx = data;
- max = mx->mx_TextEntries;
- num = mx->mx_ActiveEntry;
- for (i = 0; i < max; i++) {
- gad = &egad->eg_Gadget;
- if (i == num) {
- gad->Flags |= SELECTED;
- if (displayed) {
- RefreshGList(gad, win, (LONG)NULL, 1L);
- }
- } else {
- if (gad->Flags & SELECTED) {
- gad->Flags &= ~SELECTED;
- if (displayed) {
- RefreshGList(gad, win, (LONG)NULL, 1L);
- }
- }
-
- }
- egad = egad->eg_NextGadget;
- }
- break;
- case GADGET_DATA_TYPE_SLIDER :
- pinfo = (struct PropInfo *)gad->SpecialInfo;
- sl = data;
- min = sl->sl_Min;
- max = (LONG)sl->sl_Max - (LONG)min;
- num = (LONG)sl->sl_Level - (LONG)min;
- if (sl->sl_Flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
- num = max - num; /* if vert slider then maximum is at top */
- }
- body = calc_prop_body(max + 1, 1L);
- pot = calc_prop_pot(max + 1, 1L, num);
- if (sl->sl_Flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
- if (displayed) {
- NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, 0L,
- pot, 0L, body, 1L);
- } else {
- pinfo->VertBody = body;
- pinfo->VertPot = pot;
- }
- } else {
- if (displayed) {
- NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, pot,
- 0L, body, 0L, 1L);
- } else {
- pinfo->HorizBody = body;
- pinfo->HorizPot = pot;
- }
- }
- break;
- case GADGET_DATA_TYPE_SCROLLER :
- pinfo = (struct PropInfo *)gad->SpecialInfo;
- sc = data;
- min = sc->sc_Visible;
- max = sc->sc_Total;
- num = sc->sc_Top;
- body = calc_prop_body(max, min);
- pot = calc_prop_pot(max, min, num);
- if (sc->sc_Flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
- if (displayed) {
- NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, 0L,
- pot, 0L, body, 1L);
- } else {
- pinfo->VertBody = body;
- pinfo->VertPot = pot;
- }
- } else {
- if (displayed) {
- NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, pot,
- 0L, body, 0L, 1L);
- } else {
- pinfo->HorizBody = body;
- pinfo->HorizPot = pot;
- }
- }
- break;
- case GADGET_DATA_TYPE_CYCLE :
- cy = data;
- cy->cy_ActiveText = cy->cy_TextArray[cy->cy_ActiveEntry];
- if (displayed) {
- print_cycle_text(egad);
- }
- break;
- case GADGET_DATA_TYPE_COUNT :
- if (displayed) {
- print_count_text(egad);
- }
- break;
- case GADGET_DATA_TYPE_LISTVIEW :
- pinfo = (struct PropInfo *)gad->SpecialInfo;
- lv = data;
- min = lv->lv_VisibleEntries;
- max = lv->lv_ListEntries;
- num = lv->lv_TopEntry;
- body = calc_prop_body(max, min);
- pot = calc_prop_pot(max, min, num);
- if (displayed) {
- NewModifyProp(gad, win, (LONG)NULL, (LONG)pinfo->Flags, 0L, pot,
- 0L, body, 1L);
- print_list_view_text(egad);
- } else {
- pinfo->VertBody = body;
- pinfo->VertPot = pot;
- }
- break;
- case GADGET_DATA_TYPE_PALETTE :
- pd = data;
- if (!(pd->pd_Flags & GADGET_DATA_FLAG_PALETTE_NO_INDICATOR)) {
- image = (struct Image *)egad->eg_Render;
- image->PlaneOnOff = pd->pd_ActiveColor;
- if (displayed) {
- DrawImage(win->RPort, image, (LONG)(gad->LeftEdge + (SHORT)
- (gad->Width - image->Width) / 2), (LONG)(gad->TopEdge +
- (SHORT)(gad->Height - image->Height) / 2));
- }
- }
- break;
- }
- }
- /* Change count gadget value */
-
- VOID
- change_count_gadget(struct ExtendedGadget *egad)
- {
- struct GadgetList *gl = egad->eg_GadgetList;
- struct Window *win = gl->gl_Window;
- struct MsgPort *up = win->UserPort;
- struct IntuiMessage *msg;
- struct Gadget *gad = &egad->eg_Gadget;
- struct CountData *co = (struct CountData *)(egad + 1);
- LONG new_count, min = co->co_Min, max = co->co_Max, count = co->co_Value;
- ULONG class, old_idcmp_flags = win->IDCMPFlags;
- USHORT distance, new_delay, max_delay = MAX_COUNT_DELAY,
- delay = MAX_COUNT_DELAY;
- SHORT count_change, middle = gad->LeftEdge + gad->Width / 2;
- BOOL keepon = TRUE;
-
- ModifyIDCMP(win, (LONG)(GADGETUP | MOUSEBUTTONS | INTUITICKS));
- /* calc new delay and change value with new mouse pos */
- if (win->MouseX > middle) {
- count_change = +1;
- if (count < max) {
- count++;
- }
- } else {
- count_change = -1;
- if (count > min) {
- count--;
- }
- }
- co->co_Value = count;
- print_count_text(egad);
- do {
- /* calc new delay and change value with new mouse pos */
- if (win->MouseX > middle) {
- distance = win->MouseX - middle;
- count_change = +1;
- } else {
- if (win->MouseX < 0) {
- distance = middle + win->MouseX;
- } else {
- distance = middle - win->MouseX;
- }
- count_change = -1;
- }
- if (distance > MAX_COUNT_DISTANCE) {
- distance = MAX_COUNT_DISTANCE;
- }
- new_delay = MAX_COUNT_DELAY - distance / MAX_COUNT_STEP_SIZE;
- if (new_delay != max_delay) {
- max_delay = delay = new_delay;
- }
- if (msg = (struct IntuiMessage *)GetMsg(up)) {
- class = msg->Class;
- ReplyMsg((struct Message *)msg);
- if (class == INTUITICKS) {
- if (max_delay) {
- /* delayed change of count value */
- if (! --delay) {
- new_count = count + count_change;
- if (new_count < min) {
- new_count = min;
- } else {
- if (new_count > max) {
- new_count = max;
- }
- }
- /* print new count only if changed */
- if (new_count != count) {
- co->co_Value = count = new_count;
- print_count_text(egad);
- }
- delay = max_delay;
- }
- }
- } else {
- keepon = FALSE;
- }
- }
- if (! max_delay) {
- /* undelayed change of count value */
- if ((count + count_change) >= min && (count + count_change) <=
- max) {
- co->co_Value = count += count_change;
- print_count_text(egad);
- timer_delay(0L, MIN_COUNT_DELAY_MICROS);
- }
- }
- } while (keepon == TRUE);
- ModifyIDCMP(win, old_idcmp_flags);
- /* restore normal count gadget state (unselected) */
- if ((gad->Flags & GADGHIGHBITS) == GADGHCOMP) {
- RefreshGList(gad, win, (LONG)NULL, 1L); /* complement gadget select box */
- }
- gad->Flags &= ~SELECTED;
- RefreshGList(gad, win, (LONG)NULL, 1L);
- }
- /* Delay function - can't use Delay() from DOS (no process) */
-
- VOID
- timer_delay(ULONG seconds, ULONG micros)
- {
- struct MsgPort *port;
- struct timerequest *timer;
-
- if (port = CreatePort(NULL, 0L)) {
- if (timer = (struct timerequest *)CreateExtIO(port, (LONG)
- sizeof(struct timerequest))) {
- if (!OpenDevice(TIMERNAME, (LONG)UNIT_VBLANK, (struct IORequest *)
- timer, 0L)) {
- timer->tr_node.io_Command = TR_ADDREQUEST;
- timer->tr_time.tv_secs = seconds;
- timer->tr_time.tv_micro = micros;
- DoIO((struct IORequest *)timer);
- CloseDevice((struct IORequest *)timer);
- }
- DeleteExtIO((struct IORequest *)timer);
- }
- DeletePort(port);
- }
- }
- /* Print gadget text */
-
- VOID
- print_gadget_text(struct ExtendedGadget *egad)
- {
- struct GadgetList *gl = egad->eg_GadgetList;
- struct RenderInfo *ri = gl->gl_RenderInfo;
- struct Window *win = gl->gl_Window;
- struct RastPort *rp = win->RPort;
- struct GadgetData *gd = gl->gl_Data + egad->eg_DataEntry;
- struct Gadget *gad = &egad->eg_Gadget;
- struct TextAttr *text_attr;
- BYTE c, *text, *buffer;
- LONG len;
- USHORT save_left_edge, left_edge, top_edge, pos, flags = (gd->gd_Flags &
- GADGET_DATA_FLAG_TEXT_COLOR2 ? TEXT_DATA_FLAG_ABSOLUTE_POS |
- TEXT_DATA_FLAG_COLOR2 : TEXT_DATA_FLAG_ABSOLUTE_POS);
-
- if (text = egad->eg_Text) {
- left_edge = gad->LeftEdge + egad->eg_TextLeftEdge;
- top_edge = gad->TopEdge + egad->eg_TextTopEdge;
- if (!(text_attr = gd->gd_TextAttr)) {
- text_attr = &ri->ri_TextAttr;
- }
- if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOT_KEY) {
- len = strlen(text) + 1;
- pos = egad->eg_HotkeyPos;
- if (buffer = AllocMem(len, (LONG)MEMF_PUBLIC)) {
- strcpy(buffer, text);
- *(buffer + pos - 1) = '\0';
- left_edge += print_text(ri, win, &buffer[0],
- left_edge, top_edge, TEXT_DATA_TYPE_TEXT, flags, text_attr);
- c = *(buffer + pos + 1);
- *(buffer + pos + 1) = '\0';
- /* print and mark hot key in gadget text */
- save_left_edge = left_edge;
- left_edge += print_text(ri, win, &buffer[pos], left_edge,
- top_edge, TEXT_DATA_TYPE_TEXT, flags, text_attr);
- SetDrMd(rp, (LONG)JAM1);
- SetAPen(rp, (LONG)(gd->gd_Flags & GADGET_DATA_FLAG_TEXT_COLOR2 ?
- ri->ri_TextPen2 : ri->ri_TextPen1));
- RectFill(rp, (LONG)save_left_edge, (LONG)(top_edge +
- text_attr->ta_YSize), (LONG)(left_edge - 1), (LONG)
- (top_edge + text_attr->ta_YSize));
- *(buffer + pos + 1) = c;
- print_text(ri, win, &buffer[pos + 1], left_edge, top_edge,
- TEXT_DATA_TYPE_TEXT, flags, text_attr);
- FreeMem(buffer, len);
- } else {
- print_text(ri, win, text, left_edge, top_edge,
- TEXT_DATA_TYPE_TEXT, flags, text_attr);
- }
- } else {
- print_text(ri, win, text, left_edge, top_edge, TEXT_DATA_TYPE_TEXT,
- flags, text_attr);
- }
- }
- }
- /* Print cycle text */
-
- VOID
- print_cycle_text(struct ExtendedGadget *egad)
- {
- struct GadgetList *gl = egad->eg_GadgetList;
- struct RenderInfo *ri = gl->gl_RenderInfo;
- struct Window *win = gl->gl_Window;
- struct RastPort *rp = win->RPort;
- struct CycleData *cy = (struct CycleData *)
- (gl->gl_Gadgets[egad->eg_DataEntry] + 1);
- struct TextAttr *text_attr = cy->cy_TextAttr;
- struct IntuiText itext;
- BYTE *text = cy->cy_ActiveText;
- USHORT flags = (cy->cy_Flags & GADGET_DATA_FLAG_TEXT_COLOR2 ?
- TEXT_DATA_FLAG_ABSOLUTE_POS | TEXT_DATA_FLAG_COLOR2 :
- TEXT_DATA_FLAG_ABSOLUTE_POS),
- left_edge = cy->cy_LeftEdge, top_edge = cy->cy_TopEdge,
- width = cy->cy_Width, height = cy->cy_Height;
-
- itext.IText = (UBYTE *)text;
- itext.ITextFont = text_attr;
- SetDrMd(rp, (LONG)JAM1);
- SetAPen(rp, (LONG)ri->ri_BackPen);
- RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge + width -
- 1), (LONG)(top_edge + height - 1));
- print_text(ri, win, text, left_edge + (SHORT)(width -
- IntuiTextLength(&itext)) / 2, top_edge, TEXT_DATA_TYPE_TEXT,
- flags, text_attr);
- }
- /* Print count text */
-
- VOID
- print_count_text(struct ExtendedGadget *egad)
- {
- struct GadgetList *gl = egad->eg_GadgetList;
- struct RenderInfo *ri = gl->gl_RenderInfo;
- struct Window *win = gl->gl_Window;
- struct RastPort *rp = win->RPort;
- struct CountData *co = (struct CountData *)
- (gl->gl_Gadgets[egad->eg_DataEntry] + 1);
- struct TextAttr *text_attr = co->co_TextAttr;
- USHORT type = (co->co_Flags & GADGET_DATA_FLAG_COUNT_SIGNED_DEC ?
- TEXT_DATA_TYPE_NUM_SIGNED_DEC :
- TEXT_DATA_TYPE_NUM_UNSIGNED_DEC),
- flags = (co->co_Flags & GADGET_DATA_FLAG_TEXT_COLOR2 ?
- TEXT_DATA_FLAG_ABSOLUTE_POS | TEXT_DATA_FLAG_PLACE_LEFT |
- TEXT_DATA_FLAG_COLOR2 : TEXT_DATA_FLAG_ABSOLUTE_POS |
- TEXT_DATA_FLAG_PLACE_LEFT),
- left_edge = co->co_LeftEdge, top_edge = co->co_TopEdge,
- width = co->co_Width, height = co->co_Height;
-
- if ((egad->eg_Gadget.Flags & SELECTED) && (egad->eg_Gadget.Flags &
- GADGHIGHBITS) == GADGHCOMP) {
- flags |= TEXT_DATA_FLAG_COMPLEMENT;
- SetAPen(rp, (LONG)(ri->ri_BackPen ^ ((1 << ri->ri_ScreenDepth) - 1)));
- } else {
- SetAPen(rp, (LONG)ri->ri_BackPen);
- }
- SetDrMd(rp, (LONG)JAM1);
- RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge + width -
- 1), (LONG)(top_edge + height - 1));
- print_text(ri, win, (BYTE *)co->co_Value, left_edge + width,
- top_edge, type, flags, text_attr);
- }
- /* Print list view text */
-
- VOID
- print_list_view_text(struct ExtendedGadget *egad)
- {
- struct GadgetList *gl = egad->eg_GadgetList;
- struct RenderInfo *ri = gl->gl_RenderInfo;
- struct Window *win = gl->gl_Window;
- struct RastPort *rp = win->RPort;
- struct Layer *layer = rp->Layer;
- struct Region *region, *old_region;
- struct Rectangle rect;
- struct ListViewData *lv = (struct ListViewData *)
- (gl->gl_Gadgets[egad->eg_DataEntry] + 1);
- struct TextAttr *text_attr = lv->lv_TextAttr;
- struct Node *node = lv->lv_TopNode;
- USHORT i, text_width, flags = (lv->lv_Flags &
- GADGET_DATA_FLAG_TEXT_COLOR2 ? TEXT_DATA_FLAG_COLOR2 |
- TEXT_DATA_FLAG_ABSOLUTE_POS | TEXT_DATA_FLAG_BACK_FILL :
- TEXT_DATA_FLAG_ABSOLUTE_POS | TEXT_DATA_FLAG_BACK_FILL),
- left_edge = lv->lv_LeftEdge, top_edge = lv->lv_TopEdge,
- width = lv->lv_Width, height = lv->lv_Height,
- entries = lv->lv_ListEntries, visible = lv->lv_VisibleEntries,
- entry_height = lv->lv_EntryHeight, top = lv->lv_TopEntry;
-
- /* calc offsets for inner window */
- if (region = NewRegion()) {
- /* install clipping region around list view entry area */
- rect.MinX = left_edge;
- rect.MaxX = left_edge + width - 1;
- rect.MinY = top_edge;
- rect.MaxY = top_edge + height - 1;
- OrRectRegion(region, &rect);
- old_region = InstallClipRegion(layer, region);
- /* print list view entry text with clipping */
- SetDrMd(rp, (LONG)JAM1);
- SetAPen(rp, (LONG)ri->ri_BackPen);
- for (i = visible; i; i--, top++, top_edge += entry_height) {
- if (top < entries) {
- text_width = print_text(ri, win, node->ln_Name, left_edge,
- top_edge, TEXT_DATA_TYPE_TEXT, flags, text_attr);
- if (text_width < width) {
- RectFill(rp, (LONG)(left_edge + text_width), (LONG)top_edge,
- (LONG)(left_edge + width - 1), (LONG)(top_edge +
- entry_height - 1));
- }
- node = node->ln_Succ;
- } else {
- break;
- }
- }
- if (i) {
- RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge +
- width - 1), (LONG)(top_edge + i * entry_height - 1));
- }
- /* remove clipping region */
- InstallClipRegion(layer, old_region);
- DisposeRegion(region);
- }
- }
- /* Proportional gadget support routines (32 bit !!!) */
-
- #asm
- ; USHORT = calc_prop_body(max_num, size)(d0.l,d1.l)
- XDEF _calc_prop_body
- _calc_prop_body:
- movem.l d2-d6,-(sp)
-
- ; --- check max_num
- move.l d0,d6 ; save max_num in d6
- beq.s cpb_maximum ; max_num == 0 ?
- cmp.l d0,d1 ; size > max_num ?
- bhi.s cpb_maximum
-
- ; --- multiply size [32 bit] by MAXBODY ($ffff) [16 bit] with 48 bit arithmetic
- moveq #0,d0 ; clear shift out reg for size
- move.l d1,d3 ; init result by doing the first add
- moveq #0,d2 ; clear shift out reg of result
- moveq #16-2,d4 ; init shift count (MAXBODY has only 16 bits - one add already done)
-
- cpb_mul_loop:
- ; --- shift size
- add.l d1,d1 ; shift left of size
- addx.w d0,d0 ; save shift out
-
- ; --- inc result
- add.l d1,d3 ; add shifted size to result
- addx.w d0,d2 ; add shift out and carry
- dbra d4,cpb_mul_loop
-
- ; --- divide result [48 bit] by max_num [32 bit] with 48 bit arithmetic
- moveq #0,d0 ; clear result
- moveq #0,d1 ; clear shift out reg for divident
- moveq #0,d4 ; clear sub divisor help reg
- moveq #32-1,d5 ; init shift count
-
- cpb_div_loop:
- ; --- shift result and divident
- add.l d0,d0 ; shift result
- add.l d3,d3 ; shift left of lower LONG of divident
- addx.l d2,d2 ; shift left of upper LONG of divident - add shift out
- addx.w d1,d1 ; save shift out
-
- ; --- check if upper LONG of divident large enough to sub divisor from
- tst.w d1 ; any shift out ?
- bne.s cpb_sub_divisor
- cmp.l d2,d6 ; upper LONG of divident > divisor ?
- bhi.s cpb_next_div
-
- cpb_sub_divisor:
- sub.l d6,d2 ; sub divisor from upper LONG of divident
- subx.w d4,d1 ; sub underflow (d4 = 0) from shift out of upper LONG of divident
- addq.l #1,d0 ; set bit 0 of result
-
- cpb_next_div:
- dbra d5,cpb_div_loop
-
- ; --- don't return ZERO as prop_body
- tst.w d0
- bne.s cpb_exit
- moveq #1,d0
-
- cpb_exit:
- movem.l (sp)+,d2-d6
- rts
-
- cpb_maximum:
- move.l #$ffff,d0 ; prop_body := MAXBODY
- bra cpb_exit
-
-
- ; USHORT = calc_prop_pot(max_num, size, num)(d0.l,d1.l,d2.l)
- XDEF _calc_prop_pot
- _calc_prop_pot:
- movem.l d3-d6,-(sp)
-
- ; --- prepare max_num
- move.l d0,d6 ; save max_num
- beq cpp_minimum
- sub.l d1,d6 ; max_num -:= size
- bcs cpp_minimum
-
- ; --- multiply num by MAXPOT ($ffff) by shift num left by 16
- move.l d2,d3
- swap d3
- moveq #0,d2
- move.w d3,d2 ; d2 := upper LONG of result
- clr.w d3 ; d3 := lower LONG of result
-
- ; --- divide result [48 bit] by max_num [32 bit] with 48 bit arithmetic
- moveq #0,d0 ; clear result
- moveq #0,d1 ; clear shift out reg for divident
- moveq #0,d4 ; clear sub divisor help reg
- moveq #32-1,d5 ; init shift count
-
- cpp_div_loop:
- ; --- shift result and divident
- add.l d0,d0 ; shift result
- add.l d3,d3 ; shift left of lower LONG of divident
- addx.l d2,d2 ; shift left of upper LONG of divident - add shift out
- addx.w d1,d1 ; save shift out
-
- ; --- check if upper LONG of divident large enough to sub divisor from
- tst.w d1 ; any shift out ?
- bne.s cpp_sub_divisor
- cmp.l d2,d6 ; upper LONG of divident > divisor ?
- bhi.s cpp_next_div
-
- cpp_sub_divisor:
- sub.l d6,d2 ; sub divisor from upper LONG of divident
- subx.w d4,d1 ; sub underflow (d4 = 0) from shift out of upper LONG of divident
- addq.l #1,d0 ; set bit 0 of result
-
- cpp_next_div:
- dbra d5,cpp_div_loop
-
- ; --- if pot_value > MAXPOT then return MAXPOT
- cmp.l #$ffff,d0
- bls cpp_exit
- move.l #$ffff,d0 ; prop_pot := MAXPOT
-
- cpp_exit:
- movem.l (sp)+,d3-d6
- rts
-
- cpp_minimum:
- moveq #0,d0 ; prop_pot := 0
- bra cpp_exit
-
-
- ; ULONG = get_prop_pos(max_num, size, pot_value)(d0.l,d1.l,d2.w)
- XDEF _get_prop_pos
- _get_prop_pos:
- movem.l d3-d6,-(sp)
-
- ; --- prepare max_num
- sub.l d1,d0 ; max_num -:= size
- bcs gpp_minimum
-
- ; --- if pot_value ]0..MAXPOT[ then inc pot_value
- move.w d2,d6 ; save pot value
- beq gpp_minimum ; pot_value == 0 ?
- addq.w #1,d6 ; inc pot_value
- bcs gpp_exit ; if pot_value == MAXPOT then return (max_num - size)
-
- ; --- multiply max_num [32 bit] by pot_value [16 bit] with 48 bit arithmetic
- moveq #0,d1 ; clear shift out reg for max_num
- moveq #0,d2 ; clear result
- moveq #0,d3 ; clear shift out reg of result
- moveq #0,d4 ; reset bit count
- moveq #16-1,d5 ; init shift count (16 bits from pot_value)
- bra gpp_check_bit
-
- gpp_mul_loop:
- add.l d0,d0 ; shift left of max_num
- addx.w d1,d1 ; save shift out
-
- gpp_check_bit:
- ; --- check bit of pot_value
- btst d4,d6
- beq gpp_next_mul ; bit set ?
-
- ; --- if bit set then inc result
- add.l d0,d2 ; add shifted max_num to result
- addx.w d1,d3 ; add shift out and carry
-
- gpp_next_mul:
- addq.w #1,d4 ; inc bit count
- dbra d5,gpp_mul_loop
-
- ; --- divide result by MAXPOT ($ffff) by shift num right by 16
- move.w d3,d2 ; replace lower word (fractional part) of result by shifted out result
- swap d2 ; d2 := bits 16..47 (integer part) of result
- move.l d2,d0 ; d0 := prop_pos
-
- gpp_exit:
- movem.l (sp)+,d3-d6
- rts
-
- gpp_minimum:
- moveq #0,d0 ; prop_pos := 0
- bra gpp_exit
-
- #endasm
-