home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff218.lzh / Mandel / src / Misc.c < prev    next >
C/C++ Source or Header  |  1989-06-04  |  16KB  |  592 lines

  1. /*
  2.  * M A N D E L B R O T    C O N S T R U C T I O N   S E T
  3.  *
  4.  * (C) Copyright 1989 by Olaf Seibert.
  5.  * Mandel may be freely distributed. See file 'doc/Notice' for details.
  6.  *
  7.  * Main Program, including some general routines
  8.  */
  9.  
  10. #include <exec/types.h>
  11. #include <intuition/intuition.h>
  12. #ifdef DEBUG
  13. #   include <stdio.h>
  14. #   undef STATIC
  15. #   define STATIC   /* EMPTY */
  16. #endif
  17. #include "mandel.h"
  18.  
  19. extern struct NewWindow XYNWindow;
  20. extern struct Window *XYwindow;
  21.  
  22. #define BORDERLEFT    3
  23. #define BORDERTOP    11
  24. #define BORDERBOTTOM    3
  25.  
  26. #define CHARS        16    /* Change UpdateXYwindow also with this */
  27.  
  28. struct NewWindow XYNWindow =
  29. {
  30.     2 * BORDERLEFT, 2 * BORDERTOP,
  31.     CHARS*8+BORDERLEFT*2, 2*8+BORDERTOP+BORDERBOTTOM,
  32.     2, 1,            /* DetailPen, BlockPen */
  33.     0,                /* CLOSEWINDOW */
  34.     WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH | SIMPLE_REFRESH,
  35.     NULL,            /* FirstGadget */
  36.     NULL,            /* default CheckMark */
  37.     (UBYTE *) "Re and Im",  /* Title */
  38.     NULL,            /* Screen */
  39.     NULL,            /* BitMap */
  40.     0, 0,            /* MinWidth, MinHeight */
  41.     0, 0,            /* MaxWidth, MaxHeight */
  42.     CUSTOMSCREEN        /* Screen type */
  43. };
  44.  
  45. double ReMouse, ImMouse;
  46.  
  47. /*
  48.  *  We always ask for INTUITICKS, since this window will only be open
  49.  *  as long as we have the flashing lines.
  50.  */
  51.  
  52. void OpenXYwindow()
  53. {
  54.     if (XYwindow == NULL) {
  55.     XYNWindow.Screen = MandelScreen;
  56.  
  57.     if (XYwindow = OpenWindow(&XYNWindow)) {
  58.         XYwindow->UserPort = MainWindow->UserPort;
  59.         ModifyIDCMP(XYwindow, (long)CLOSEWINDOW | MOUSEBUTTONS | INTUITICKS);
  60.         SetDrMd(XYwindow->RPort, (long)JAM2);
  61.         SetAPen(XYwindow->RPort, (long)1);
  62.         SetBPen(XYwindow->RPort, (long)0);
  63.     }
  64.     }
  65. }
  66.  
  67. void CloseXYwindow()
  68. {
  69.     if (XYwindow) {
  70.     CloseWindowSafely(XYwindow);
  71.     XYwindow = NULL;
  72.     }
  73. }
  74.  
  75. void UpdateXYwindow(x, y)   /* corrected: 0..max */
  76. int x, y;
  77. {
  78.     register int chars;
  79.     register struct RastPort *rp;
  80.     register long left, top;
  81.     char buffer[CHARS+2];    /* 1 extra for \0, and 1 for safety */
  82.     static char format[] = "%-16.10g";      /* 16 == CHARS */
  83.     /* -1.234567890e-99 is 16 chars with a precision of 10 digits */
  84.  
  85.     ReMouse = LeftEdge + CXStep * x;
  86.     ImMouse = TopEdge - CYStep * y;
  87.  
  88.     if (XYwindow) {
  89.     rp = XYwindow->RPort;
  90.     left = XYwindow->BorderLeft;
  91.     top = XYwindow->BorderTop;
  92.  
  93.     chars = sprintf(buffer, format, ReMouse);
  94.     Move(rp, left, top+7);
  95.     Text(rp, buffer, (long)chars);
  96.  
  97.     chars = sprintf(buffer, format, ImMouse);
  98.     Move(rp, left, top+15);
  99.     Text(rp, buffer, (long)chars);
  100.     }
  101. }
  102.  
  103. void MyExit(status)
  104. char *status;
  105. {
  106.     static char message[] = "\
  107. \0\144\25Mandelbrot Construction Set -- By KosmoSoft Productions\0a\
  108. \0\144\41                                  \0";
  109. /*    3^5^  10^    ^    20^    ^  30^     ^  40^    ^  50^  55^58^     */
  110.     register char *c=message+63;
  111.  
  112. #ifdef AREXX
  113.     dnRexxPort();
  114. #endif
  115.  
  116.     if (status) {
  117.     /* Center the message. */
  118.  
  119.     {
  120.         register int halfway = 320 - (strlen(status) << 2);
  121.         message[60] = halfway >> 8; /* High byte */
  122.         message[61] = halfway;    /* Low byte */
  123.     }
  124.     while ((*(c++) = *(status++)) && c < message + 127);
  125.     *c = 0;
  126.  
  127.     /* Let's be paranoid for a change... */
  128.     if (!IntuitionBase) IntuitionBase = (struct IntuitionBase *)
  129.         OpenLibrary ("intuition.library", 0L);
  130.     if (IntuitionBase)
  131.         DisplayAlert(RECOVERY_ALERT, message, 50L);
  132.     else {    /* AT_Recovery | AG_OpenLib | AO_Intuition */
  133.         CPTR AlertParameter = (CPTR) FindTask(NULL);
  134.         Alert(0x00038004L, &AlertParameter);
  135.     }
  136.  
  137.     status=1;
  138.     }
  139.     CleanupDisplay((bool) TRUE);
  140.     if (DrawSigBit != -1) FreeSignal((long)DrawSigBit);
  141.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  142.     if (LayersBase) CloseLibrary(LayersBase);
  143.     if (GfxBase) CloseLibrary(GfxBase);
  144.     exit ((int) (status != NULL));
  145. }
  146.  
  147. void _abort()
  148. {
  149.     MyExit("_abort() called...");
  150. }
  151.  
  152. bool Sure()
  153. {
  154.     bool Result;
  155.     ULONG OldIDCMP = MainWindow->IDCMPFlags;
  156.  
  157.     static struct IntuiText Body[] =
  158.     {
  159.     {   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
  160.         25, 10, NULL, (UBYTE *) "You are going to", &Body[1]    },
  161.     {   MYFRONTPEN+1, AUTOBACKPEN, AUTODRAWMODE,
  162.         57, 25, &Topaz60, (UBYTE *) "destroy", &Body[2] },
  163.     {   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
  164.         33, 40, NULL, (UBYTE *) "your picture !", NULL  }
  165.     };
  166.  
  167.     if (Saved) return TRUE;
  168.  
  169.     ModifyIDCMP(MainWindow, OldIDCMP &~ (MENUVERIFY | SIZEVERIFY | REQVERIFY));
  170.     Result = AutoRequest(MainWindow, &Body[0], &PositiveText, &NegativeText,
  171.     NULL, NULL, 200L, 90L);
  172.     ModifyIDCMP(MainWindow, OldIDCMP);
  173.  
  174.     return Result;
  175. }
  176.  
  177. /*
  178.  * Render a requester in a window. If it won't fit, open a new window.
  179.  * This new window will share the IDCMP port with the original
  180.  * window. This is to save memory, signal bits and VERIFY deadlocks.
  181.  * Returns the window in which the requester actually appears.
  182.  */
  183.  
  184. struct Window *MyRequest(request, window)
  185. struct Requester *request;
  186. struct Window *window;
  187. {
  188.     static struct NewWindow newwindow = {
  189.     0, 0, 0, 0, 2, 1,
  190.     NULL,        /* IDCMP flags -- port shared with main window */
  191.     WINDOWDEPTH | WINDOWDRAG | ACTIVATE | SIMPLE_REFRESH | NOCAREREFRESH,
  192.     NULL, NULL, NULL, NULL,
  193.     NULL, 0, 0, 0, 0, NULL    };
  194.     int width, height;
  195.     int borderleft, borderright, bordertop, borderbottom;
  196.     struct Window *oldwindow = window;
  197.  
  198.     borderleft     = window->WScreen->WBorLeft;
  199.     borderright  = window->BorderRight;
  200.     bordertop     = window->WScreen->BarHeight + 1;
  201.     borderbottom = window->BorderBottom;
  202.  
  203.     /* Center the requester in the given window.
  204.      * If impossible, open a new window to the place the requester in.
  205.      */
  206.  
  207.      width = window->GZZWidth;
  208.      height = window->GZZHeight;
  209.  
  210.      if (width < request->Width || height < request-> Height) {
  211.     /* Window too small. Open a new one */
  212.     newwindow.Screen = window->WScreen;
  213.     newwindow.Type = window->WScreen->Flags & SCREENTYPE;
  214.     newwindow.Title = window->Title;
  215.     newwindow.Width = request->Width + 2 * borderleft;
  216.     newwindow.Height = request->Height + bordertop + borderbottom;
  217.     newwindow.LeftEdge = (newwindow.Screen->Width - newwindow.Width) / 2;
  218.     newwindow.TopEdge = (newwindow.Screen->Height - newwindow.Height) / 2;
  219.  
  220.     if (window = OpenWindow(&newwindow)) {
  221.         window->UserPort = oldwindow->UserPort;
  222.         /* Upen up the other port */
  223.         ModifyIDCMP(window, GADGETUP);
  224.     }
  225.  
  226.     request->LeftEdge = borderleft;
  227.     request->TopEdge = bordertop;
  228.     } else {    /* The requester fits. Center it! */
  229.     request->LeftEdge = ((width - request->Width) >> 1);
  230.     request->TopEdge = ((height - request->Height) >> 1);
  231.     if (!(window->Flags & GIMMEZEROZERO)) {
  232.         request->LeftEdge += borderleft;
  233.         request->TopEdge += bordertop;
  234.     }
  235.     }
  236.  
  237.     if (window && Request(request, window)) return window;
  238.  
  239.     if (window) CloseWindowSafely(window);
  240.     return NULL;
  241. }
  242.  
  243. void EndMyRequest(request, window, original)
  244. struct Requester *request;
  245. struct Window *window, *original;
  246. {
  247.     EndRequest(request, window);
  248.     if (window != original) CloseWindowSafely(window);
  249. }
  250.  
  251. /*
  252.  * Wait on a request posted by MyRequest.
  253.  * Returns when a gadget with GadgetID >= POSGADGETID is released,
  254.  * so Gadgets with an ID < POSGADGETID will be ignored.
  255.  * NEGGADID > POSGADID.
  256.  * Any messages other than GADGETUP will be ignored.
  257.  */
  258.  
  259. int WaitMyRequest(window)
  260. struct Window *window;
  261. {
  262.     int ID = 0;
  263.     struct IntuiMessage *message;
  264.     struct Gadget *Gadget;
  265.     ULONG Class;
  266.     ULONG OldIDCMP = window->IDCMPFlags;
  267.     ULONG SigMask;
  268.  
  269.     if (!window)
  270.     return NEGGADGETID;
  271.  
  272.     ModifyIDCMP(window, GADGETUP);
  273.  
  274. #ifdef AREXX
  275.     SigMask = RexxMask | (1L << MainWindow->UserPort->mp_SigBit);
  276. #else
  277.     SigMask = (1L << MainWindow->UserPort->mp_SigBit);
  278. #endif
  279.  
  280.     while (ID < POSGADGETID) {
  281.     Wait(SigMask);
  282. #ifdef AREXX
  283.     dispRexxPort();
  284. #endif
  285.     while (message = (struct IntuiMessage *) GetMsg(window->UserPort) ) {
  286.         Class = message->Class;
  287.         Gadget = (struct Gadget *)message->IAddress;
  288.         ReplyMsg(message);
  289.         if (Class != GADGETUP) continue;
  290.         ID = Gadget->GadgetID;
  291.         if (ID >= POSGADGETID) break; /* Also gets out of outer loop */
  292.     }
  293.     }
  294.     ModifyIDCMP(window, OldIDCMP);
  295.     return ID;
  296. }
  297.  
  298. void RectDraw(rp, x1, y1, x2, y2)
  299. struct RastPort *rp;
  300. SHORT x1, y1, x2,y2;
  301. {
  302.     Move(rp, (long) x1, (long) y1);
  303.     Draw(rp, (long) x2, (long) y1);
  304.     Draw(rp, (long) x2, (long) y2);
  305.     Draw(rp, (long) x1, (long) y2);
  306.     if (y2 > y1) y1++; else y1--;   /* Don't XOR the first pixel twice */
  307.     Draw(rp, (long) x1, (long) y1);
  308. }
  309.  
  310. void CrossDraw(rp, x, y, left, right, top, bottom)
  311. struct RastPort *rp;
  312. SHORT x, y, top, bottom, left, right;
  313. {
  314.     Move(rp, (long) left, (long) y);
  315.     Draw(rp, (long) right, (long) y);
  316.     Move(rp, (long) x, (long) top);
  317.     Draw(rp, (long) x, (long) bottom);
  318. }
  319.  
  320. void DisableSystemGadgets(gadget)
  321. struct Gadget *gadget;
  322. {
  323.     while (gadget) {
  324.     if (gadget->GadgetType & SYSGADGET) {
  325.         /* Ghost everything except the Title/Dragbar */
  326.         if ((gadget->GadgetType & 0x00F0) != WDRAGGING)
  327.         OffGadget(gadget, MainWindow, NULL);
  328.         gadget->Flags |= GADGDISABLED;
  329.     }
  330.     gadget = gadget->NextGadget;
  331.     }
  332. }
  333.  
  334. void EnableSystemGadgets(gadget)
  335. struct Gadget *gadget;
  336. {
  337.     USHORT Flags = 0;
  338.  
  339.     while (gadget) {
  340.     if (gadget->GadgetType & SYSGADGET) {
  341.         Flags |= gadget->Flags;
  342.         gadget->Flags &= ~GADGDISABLED;
  343.     }
  344.     gadget = gadget->NextGadget;
  345.     }
  346.     /* Unghost everthing if necessary */
  347.     if (Flags & GADGDISABLED)   RefreshWindowFrame(MainWindow);
  348. }
  349.  
  350. void StopFraming()
  351. {
  352.     if (MainWindow) {
  353.     EnableSystemGadgets(MainWindow->FirstGadget);
  354.     ModifyIDCMP(MainWindow, MainWindow->IDCMPFlags & ~INTUITICKS);
  355.     }
  356.     MouseStatus = NOTFRAMING;
  357.     CloseXYwindow();
  358. }
  359.  
  360. void CheckMouse(Message)
  361. register struct IntuiMessage *Message;
  362. {
  363.     register SHORT top = MainWindow->BorderTop,
  364.            bottom = MainWindow->Height - MainWindow->BorderBottom - 1,
  365.            left = MainWindow->BorderLeft,
  366.            right = MainWindow->Width - MainWindow->BorderRight - 1;
  367.     static ULONG OldSecs, OldMicros;
  368.     static SHORT MidX, MidY;
  369.     USHORT MouseX, MouseY;
  370.  
  371.     if (Message->IDCMPWindow == MainWindow) {
  372.     MouseX = Message->MouseX;
  373.     MouseY = Message->MouseY;
  374.     } else {
  375.     MouseX = MainWindow->MouseX;
  376.     MouseY = MainWindow->MouseY;
  377.     }
  378.  
  379.     if (StillDrawing || MouseStatus != FLASHING &&
  380.     (MouseX < left || MouseX > right || MouseY < top || MouseY > bottom))
  381.     return;
  382.  
  383.     MouseX -= left;
  384.     MouseY -= top;
  385.  
  386.     if (Message->Class == MOUSEBUTTONS) {
  387.     if (Message->Code == SELECTDOWN) {
  388.         /* We selected a point */
  389.         switch (MouseStatus) {
  390.         case NOTFRAMING:
  391.         case FLASHING:
  392.         MouseStatus = NOPOINT;
  393.         DisableSystemGadgets(MainWindow->FirstGadget);
  394.         ModifyIDCMP(MainWindow, MainWindow->IDCMPFlags | INTUITICKS);
  395.         OpenXYwindow();
  396.         /* Now we can select our first corner */
  397.         break;
  398.         case NOPOINT:
  399.         FrameX1 = FrameX2 = MouseX;
  400.         FrameY1 = FrameY2 = MouseY;
  401.         MouseStatus = POINT1;
  402.         OldMicros = Message->Micros;
  403.         OldSecs = Message->Seconds;
  404.         /* We have the first point. Now go for the second */
  405.         break;
  406.         case POINT1:
  407.         if (DoubleClick(OldSecs, OldMicros,
  408.                 Message->Seconds, Message->Micros)) {
  409.             /* Did we double-click? Then we have selected a center */
  410.             MouseStatus = CENTERFRAMING;
  411.             MidX = FrameX1;
  412.             MidY = FrameY1;
  413.             break;
  414.         }
  415.         FrameX2 = MouseX;
  416.         FrameY2 = MouseY;
  417.         /* Fall through to CENTERFRAMING */
  418.         case CENTERFRAMING:
  419.         if (FrameX1 == FrameX2 || FrameY1 == FrameY2) break;
  420.         EnableSystemGadgets(MainWindow->FirstGadget);
  421.         MouseStatus = FLASHING;
  422.         /* Point 1 should be upper left */
  423.         if (FrameX2 < FrameX1) {
  424.             /* I DO know I am reusing a variable here. Sorry! */
  425.             left=FrameX2; FrameX2=FrameX1; FrameX1=left;
  426.         }
  427.         if (FrameY2 < FrameY1) {
  428.             left=FrameY2; FrameY2=FrameY1; FrameY1=left;
  429.         }
  430.         break;
  431.         }    /* End switch MouseStatus */
  432.     }   /* End if Code == SELECTDOWN */
  433.     return;
  434.     }    /* End if Class == MOUSEBUTTONS */
  435.  
  436.     /* We are moving the mouse. Show something! */
  437.  
  438.     UpdateXYwindow(MouseX, MouseY);
  439.  
  440.     SetDrMd(MainWindow->RPort, (ULONG) COMPLEMENT);
  441.  
  442.     switch (MouseStatus) {
  443.     /* case NOTFRAMING: */
  444.     /*    return; */
  445.     case NOPOINT:
  446.     FrameX1 = FrameX2 = MouseX;
  447.     FrameY1 = FrameY2 = MouseY;
  448.     WaitTOF();
  449.     CrossDraw(MainWindow->RPort, FrameX1, FrameY1,
  450.             0, MainWindow->GZZWidth-1, 0, MainWindow->GZZHeight-1);
  451.     WaitTOF();
  452.     CrossDraw(MainWindow->RPort, FrameX1, FrameY1,
  453.             0, MainWindow->GZZWidth-1, 0, MainWindow->GZZHeight-1);
  454.     break;
  455.     case CENTERFRAMING:
  456.     FrameX1 = MouseX;
  457.     FrameY1 = MouseY;
  458.     FrameX2 = 2*MidX - FrameX1;
  459.     FrameY2 = 2*MidY - FrameY1;
  460.     skipto flashing;
  461.     case POINT1:
  462.     FrameX2 = MouseX;
  463.     FrameY2 = MouseY;
  464.     /* Deliberate Fall-Through to FLASHING */
  465.     case FLASHING:
  466. flashing:
  467.     WaitTOF();
  468.     RectDraw(MainWindow->RPort, FrameX1, FrameY1, FrameX2, FrameY2);
  469.     WaitTOF();
  470.     RectDraw(MainWindow->RPort, FrameX1, FrameY1, FrameX2, FrameY2);
  471.     }
  472. }
  473.  
  474. void InitPenTable()
  475. {
  476.     register int i;
  477.  
  478.     switch (PenTableMode) {
  479.     case MODULO:
  480.     PenTable[0] = 0;
  481.     for (i=1; i<MAXDEPTH; i++) PenTable[i] = 1 + i % (NumColors - 1);
  482.     break;
  483.     case RANGES:
  484.     PenTable[0] = 0;
  485.     for (i=1; i<MAXDEPTH; i++)
  486.         PenTable[i] = 1 + (i/RangeWidth) % (NumColors - 1);
  487.     case SELECT:
  488.     /* Don't change the table if it is user-defined */
  489.     break;
  490.     }
  491. }
  492.  
  493. void SelectMenu(MenuNum, CheckIt)
  494. LONG MenuNum;
  495. bool CheckIt;
  496. {
  497.     struct MenuItem *Item = ItemAddress(MandelMenu, MenuNum);
  498.  
  499.     ClearMenuStrip(MainWindow);
  500.  
  501.     if (CheckIt)
  502.     Item->Flags |= CHECKED;
  503.     else
  504.     Item->Flags &= ~CHECKED;
  505.  
  506.     SetMenuStrip(MainWindow, MandelMenu);
  507. }
  508.  
  509. void MakeMAND(mand)
  510. struct Mand *mand;
  511. {
  512.     int i;
  513.  
  514.     mand->MandID = MAND;
  515.     mand->Size = sizeof(struct Mand) - 2 * sizeof(LONG);
  516.     mand->MaxDepth = MaxDepth;
  517.     mand->RangeWidth = RangeWidth;
  518.  
  519.     mand->RainDist = RainbowDistance;
  520.     mand->RainRMax = RainbowRMax;
  521.     mand->RainGMax = RainbowGMax;
  522.     mand->RainBMax = RainbowBMax;
  523.  
  524.     for (i=0; i < sizeof(mand->Coords); i++)
  525.     mand->Coords[i] = '\0';
  526.     sprintf(&mand->Coords[0], "%1.10g %1.10g %1.10g %1.10g",
  527.     LeftEdge, RightEdge, TopEdge, BottomEdge);
  528.  
  529.     mand->FunctionNr = FunctionNr;
  530.     mand->PenTableMode = PenTableMode;
  531.     mand->WBWidth = WBWidth;
  532.     mand->WBHeight = WBHeight;
  533.  
  534. }
  535.  
  536. bool InterpretMAND(mand, ilbminfo)
  537. struct Mand *mand;
  538. struct ILBM_info *ilbminfo;
  539. {
  540.     double NewLeftEdge, NewRightEdge, NewTopEdge, NewBottomEdge;
  541.     double Ratio;
  542.  
  543.     /* Perform some checks on correctness of the chunk */
  544.     if (mand->MandID != MAND ||
  545.      mand->Size > sizeof(struct Mand) - 2 * sizeof(LONG) ||
  546.       mand->MaxDepth > MAXDEPTH ||
  547.        mand->RangeWidth > MAXDEPTH)
  548.     return FALSE;
  549.  
  550.     if (sscanf(&mand->Coords[0], "%lf %lf %lf %lf",
  551.     &NewLeftEdge, &NewRightEdge, &NewTopEdge, &NewBottomEdge) < 4)
  552.     return FALSE;
  553.  
  554.     MaxDepth    = mand->MaxDepth;
  555.     RangeWidth    = mand->RangeWidth;
  556.  
  557.     /* Compensate for different sized windows */
  558.  
  559.     Ratio    = (double)MainWindow->GZZWidth / (double)ilbminfo->header.w;
  560.     LeftEdge    = NewLeftEdge;
  561.     if (Ratio != 1.0)
  562.     RightEdge = NewLeftEdge + Ratio * (NewRightEdge - NewLeftEdge);
  563.     else        /* avoid round-off when almost exactly 1.0000 */
  564.     RightEdge = NewRightEdge;
  565.  
  566.     Ratio    = (double)MainWindow->GZZHeight / (double)ilbminfo->header.h;
  567.     TopEdge    = NewTopEdge;
  568.     if (Ratio != 1.0)
  569.     BottomEdge = NewTopEdge - Ratio * (NewTopEdge - NewBottomEdge);
  570.     else        /* avoid round-off when almost exactly 1.0000 */
  571.     BottomEdge = NewBottomEdge;
  572.  
  573.     CalcCSteps();
  574.  
  575.     RainbowDistance = mand->RainDist;
  576.     RainbowRMax = mand->RainRMax;
  577.     RainbowGMax = mand->RainGMax;
  578.     RainbowBMax = mand->RainBMax;
  579.  
  580.     if (mand->Size > OFFSETOF(FunctionNr, Mand) - 2*sizeof(long)) {
  581.     SetDrawingFunction(mand->FunctionNr);
  582.     PenTableMode = mand->PenTableMode;
  583.     WBWidth = mand->WBWidth;
  584.     WBHeight = mand->WBHeight;
  585.     InitPenTable();
  586.     }
  587.  
  588.     UpdateCheckmarks();
  589.  
  590.     return TRUE;
  591. }
  592.