home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / tools / workbench / lupe1.9 / source / lupe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-22  |  62.2 KB  |  2,424 lines

  1.  
  2. /**** --- BEGIN HEADER --- ****************************************************/
  3. /*                                                                            */
  4. /* Name          : lupe.c                                                     */
  5. /* Version       : 1.9                                                        */
  6. /* Revision      :                                                            */
  7. /* Creation Date : 18-Jul-95                                                  */
  8. /* Last Changes  : 02-10-97                                                   */
  9. /* Author(s)     : Frank Toepper                                              */
  10. /* Remarks       : needs OS3.0+                                               */
  11. /*                                                                            */
  12. /* Copyright (C) 1995-97 Frank Toepper                                        */
  13. /*                                                                            */
  14. /* Description   : a magnifying glass program                                 */
  15. /*                                                                            */
  16. /* History:                                                                   */
  17. /* --------                                                                   */
  18. /*                                                                            */
  19. /* Date     | Author     | Changes                                            */
  20. /* ---------+------------+--------------------------------------------------- */
  21. /* 06-06-97 | FT         | begin header maintenance                           */
  22. /* 12-06-97 | FT         | grid was generated in 1:1-mode                     */
  23. /*          |            | on uniconify the window will be opened on the      */
  24. /* 17-08-97 | FT         | frontmost screen                                   */
  25. /* 18-08-97 | FT         | default show/hide-hotkey changed to "lalt l"       */
  26. /* 02-10-97 | FT         | show/hide-Msg will be disposed now                 */
  27. /* 15-10-97 | FT         | cleanup with minor changes                         */
  28. /*                                                                            */
  29. /**** --- END HEADER --- ******************************************************/
  30.  
  31.  
  32. #include <string.h>
  33. #include <iostream.h>
  34. #include <ctype.h>
  35. #include <intuition/intuition.h>
  36. #include <intuition/imageclass.h>
  37. #include <intuition/icclass.h>
  38. #include <intuition/gadgetclass.h>
  39. #include <intuition/intuitionbase.h>
  40. #include <exec/exec.h>
  41. #include <dos/dos.h>
  42. #include <graphics/scale.h>
  43. #include <devices/inputevent.h>
  44. #include <libraries/commodities.h>
  45. #include <libraries/gadtools.h>
  46. #include <datatypes/pictureclass.h>
  47. #include <graphics/displayinfo.h>
  48. #include <graphics/gfxmacros.h>
  49. #include <graphics/gfxbase.h>
  50. #include <cybergraphics/cybergraphics.h>
  51. #include <clib/dos_protos.h>
  52. #include <pragma/dos_lib.h>
  53. #include <clib/intuition_protos.h>
  54. #include <pragma/intuition_lib.h>
  55. #include <clib/graphics_protos.h>
  56. #include <pragma/graphics_lib.h>
  57. #include <clib/exec_protos.h>
  58. #include <pragma/exec_lib.h>
  59. #include <clib/commodities_protos.h>
  60. #include <pragma/commodities_lib.h>
  61. #include <clib/gadtools_protos.h>
  62. #include <pragma/gadtools_lib.h>
  63. #include <clib/icon_protos.h>
  64. #include <pragma/icon_lib.h>
  65. #include <clib/cybergraphics_protos.h>
  66. #include <pragma/cybergraphics_lib.h>
  67. #include <clib/wb_protos.h>
  68. #include <pragma/wb_lib.h>
  69. #include <libraries/asl.h>
  70. #include <clib/asl_protos.h>
  71. #include <pragma/asl_lib.h>
  72. #include <clib/alib_protos.h>
  73. #include <pragma/utility_lib.h>
  74. #include <clib/utility_protos.h>
  75. #include <pragma/layers_lib.h>
  76. #include <clib/layers_protos.h>
  77. #include <wbstartup.h>
  78.  
  79. #pragma header
  80.  
  81. #include "lupe_cat.h"
  82.  
  83. #define VERSION "Lupe V1.9"
  84.  
  85. #define CYBERARRAY_BPP 3
  86.  
  87. #define MINWIDTH 56
  88. #define MINHEIGHT 30
  89.  
  90. enum { SAMESCREEN, NEWSCREEN };
  91.  
  92. UWORD innerwidth = 150, innerheight = 100, sourcewidth, sourceheight;
  93. UWORD scalefac = 5, maxscalefac = 15, minwidth;
  94. UWORD leftoff, topoff, bottomoff, rightoff;
  95. UWORD sizeiw, sizeih, winx, winy, winleft = 0, wintop = 11, originX = 0, originY = 0;
  96. UWORD textoff, coordsstringlen, fontX, fontY, scrdepth;
  97. WORD fixedX = 0, fixedY = 0;
  98. ULONG cxsigflag, waitmask = 0, pens[6];
  99. LONG oldx, oldy;
  100. APTR VisualInfo = NULL;
  101. BPTR fh;
  102. struct MsgPort *broker_mp, *userport, *app_mp = NULL;
  103. struct Task *thistask;
  104. struct Window *mywin;
  105. struct Screen *scr = NULL, *tmpscr;
  106. struct Menu *menu = NULL;
  107. struct MenuItem *item;
  108. struct BitMap *srcbm = NULL, *destbm = NULL, *scrbm, *maskbm = NULL;
  109. struct TextFont *screenfont = NULL, *topazfont;
  110. struct InputXpression setoriginix, resetoriginix, showhideix;
  111. struct RastPort *scrrp, destrp, *winrp, maskrp;
  112. struct Library *CxBase, *GadToolsBase, *CyberGfxBase, *IconBase;
  113. struct Library *WorkbenchBase, *AslBase, *LocaleBase, *UtilityBase, *LayersBase;
  114. struct GfxBase *GfxBase;
  115. struct AppIcon *appicon = NULL;
  116. struct AppMessage *appmsg;
  117. struct DiskObject *icon = NULL;
  118. UBYTE timesig, showhidesig;
  119. BOOL hires, newlook, jump = FALSE, fast = FALSE, pubscreenlocked = FALSE, enable = TRUE;
  120. BOOL cybergfxscreen, coords = FALSE, crosshair = FALSE, origin = TRUE, fixed = FALSE;
  121. BOOL jumpdirect, showhide = TRUE, hide = FALSE, hideonclose = FALSE, grid = FALSE;
  122. BOOL showrgb = FALSE, jumptoactivescreen = FALSE;
  123. CxObj *broker, *customcxobj;
  124. Object *propgadget;
  125. char pubscreenname[MAXPUBSCREENNAME];
  126. char setoriginkey[50] = "lalt o", resetoriginkey[50] = "lalt r", showhidekey[50] = "lalt l";
  127. char title[10], dispstring[12], language[20] = "";
  128. char programname[110], iffpath[256] = "ram:Lupe.iff", iffname[110];
  129. char *Template = "CX_PRIORITY=P/N/K, FAST=F/S/K, MAXSCALEFACTOR=M/N/K, SCALEFACTOR=S/N/K, "
  130.                  "WINLEFT=L/N/K, WINTOP=T/N/K, WINWIDTH=W/N/K, WINHEIGHT=H/N/K, "
  131.                  "COORDINATES=C/S/K, CROSSHAIR=R/S/K, SETORIGINKEY=O/K, RESETORIGINKEY=K/K, "
  132.                  "FIXED=D/S/K, SHOWHIDEKEY=SH/K, ICONIFY=I/S/K, ICONIFYONCLOSE=IOC/S/K, "
  133.                  "GRID=G/S/K, SHOWRGB=RGB/S/K, IFFFILE=IF/K, JUMPTOACTIVESCREEN=JAS/S/K, "
  134.                  "LANGUAGE=U";
  135.  
  136. struct BitScaleArgs bsa = {
  137.    // Src coords
  138.    0, 0,
  139.    innerwidth / scalefac,
  140.    innerheight / scalefac,
  141.    // Src factors
  142.    1, 1,
  143.    0, 0,
  144.    innerwidth,
  145.    innerheight,
  146.    // Dest factors
  147.    scalefac, scalefac,
  148.    // Bitmaps
  149.    NULL, NULL,
  150.    0,
  151.    0, 0,
  152.    0, 0
  153. };
  154.  
  155. struct TextAttr topaz_attr = {
  156.    "topaz.font",
  157.    8,
  158.    0,
  159.    FPF_ROMFONT
  160. };
  161.  
  162. struct NewBroker newbroker = {
  163.    NB_VERSION,
  164.    "Lupe",
  165.    VERSION " © 1995-97 Frank Toepper",
  166.    0,
  167.    3,
  168.    COF_SHOW_HIDE,
  169.    0,
  170.    NULL,
  171.    0
  172. };
  173.  
  174. extern struct IntuitionBase *IntuitionBase;
  175.  
  176. // function declarations for menu
  177. BOOL jumpFunc ();
  178. BOOL jumptoactiveFunc ();
  179. BOOL saveFunc ();
  180. BOOL fastFunc ();
  181. BOOL AboutFunc ();
  182. BOOL enableFunc ();
  183. BOOL coordsFunc ();
  184. BOOL crosshairFunc ();
  185. BOOL gridFunc ();
  186. BOOL showrgbFunc ();
  187. BOOL fixedFunc ();
  188. BOOL QuitFunc ();
  189. BOOL hideFunc ();
  190. BOOL hideoncloseFunc ();
  191.  
  192. //----------------------------------------------
  193.  
  194. void Putchar (register __d0 char zeichen, register __a3 char *putchdata)
  195. {
  196.    *putchdata++ = zeichen;
  197. }
  198.  
  199. void error (char *formatstring, ...)
  200. {
  201.  APTR args = &formatstring + 1;
  202.  struct EasyStruct easystruct = {
  203.     sizeof (struct EasyStruct),
  204.     0,
  205.     GetString (TXT_ERROR),
  206.     formatstring,
  207.     GetString (TXT_OK)
  208.  };
  209.  
  210.    if (Cli ())
  211.    {
  212.       VPrintf (formatstring, (LONG *) args);
  213.       FPutC (Output (), '\n');
  214.       Flush (Output ());
  215.    }
  216.    else
  217.    {
  218.       EasyRequestArgs (NULL, &easystruct, NULL, args);
  219.    }
  220. }
  221.  
  222. //- setup screen -------------------------------
  223.  
  224. BOOL lockaspublicscreen (struct Screen *screen)
  225. {
  226.  struct List *pubscreenlist;
  227.  struct PubScreenNode *pubscreennode;
  228.  
  229.    pubscreenlist = LockPubScreenList ();
  230.    if (pubscreenlist)
  231.    {
  232.       pubscreennode = (struct PubScreenNode *) pubscreenlist->lh_Head;
  233.       while (pubscreennode)
  234.       {
  235.          if (pubscreennode->psn_Screen == screen)
  236.          {
  237.             if (LockPubScreen (pubscreennode->psn_Node.ln_Name))
  238.             {
  239.                UnlockPubScreenList ();
  240.                return TRUE;
  241.             }
  242.          }
  243.          pubscreennode = (struct PubScreenNode *) pubscreennode->psn_Node.ln_Succ;
  244.       }
  245.       UnlockPubScreenList ();
  246.    }
  247.    return FALSE;
  248. }
  249.  
  250. void CloseDownScreen ()
  251. {
  252.    if (VisualInfo)
  253.    {
  254.       FreeVisualInfo (VisualInfo);
  255.       VisualInfo = NULL;
  256.    }
  257.    if (scr && pubscreenlocked)
  258.    {
  259.       UnlockPubScreen (NULL, scr);
  260.    }
  261.    pubscreenlocked = FALSE;
  262. }
  263.  
  264. BOOL jumptoscreen (struct Screen *selectedscreen)
  265. {
  266.    // to adjust screen order later
  267.    jumpdirect = FALSE;
  268.    
  269.    if (selectedscreen)
  270.    {
  271.       jumpdirect = TRUE;
  272.       CloseDownScreen ();
  273.       if (lockaspublicscreen (selectedscreen))
  274.       {
  275.          pubscreenlocked = TRUE;
  276.       }
  277.       scr = selectedscreen;
  278.       return TRUE;
  279.    }
  280.    return FALSE;
  281. }
  282.  
  283. int setupscreen (struct Screen *selectedscreen)
  284. {
  285.  ULONG id;
  286.  
  287.    // screen selected from screens-menu?
  288.    if (!jumptoscreen (selectedscreen))
  289.    {
  290.       // no, then 'jump'?
  291.       if (scr)
  292.       {
  293.          tmpscr = scr->NextScreen;
  294.          if (tmpscr)
  295.          {
  296.             CloseDownScreen ();
  297.             if (lockaspublicscreen (tmpscr))
  298.             {
  299.                pubscreenlocked = TRUE;
  300.             }
  301.          }
  302.          else
  303.          {
  304.             error (GetString (TXT_ERROR_NOOTHERSCREEN));
  305.             return SAMESCREEN;
  306.          }
  307.          scr = tmpscr;
  308.       }
  309.       // no? -> startup
  310.       else if ((scr = LockPubScreen (NULL)) != 0)
  311.       {
  312.          pubscreenlocked = TRUE;
  313.       }
  314.       else
  315.       {
  316.          error (GetString (TXT_ERROR_LOCKPUBSCREEN));
  317.          throw 1;
  318.       }
  319.    }
  320.    VisualInfo = GetVisualInfoA (scr, NULL);
  321.    if (!VisualInfo)
  322.    {
  323.       error (GetString (TXT_ERROR_VISUALINFO));
  324.       throw 2;
  325.    }
  326.    cybergfxscreen = FALSE;
  327.    if (CyberGfxBase)
  328.       if ((id = GetVPModeID (&scr->ViewPort)) != INVALID_ID)
  329.          if (IsCyberModeID (id))
  330.             if (GetCyberIDAttr (CYBRIDATTR_BPPIX, id) > 1)
  331.                cybergfxscreen = TRUE;
  332.    return NEWSCREEN;
  333. }
  334.  
  335. //- window -------------------------------------
  336.  
  337. void getoffsets ()
  338. {
  339.  struct DrawInfo *drawinfo;
  340.  APTR sizeobject;
  341.  ULONG attr;
  342.  
  343.    if (screenfont)
  344.    {
  345.       CloseFont (screenfont);
  346.       screenfont = NULL;
  347.    }
  348.    hires = (scr->Flags & SCREENHIRES) != 0;
  349.    hires ? (rightoff = 18) : (rightoff = 13);
  350.    SetAPen (&maskrp, 1);
  351.    drawinfo = GetScreenDrawInfo (scr);
  352.    if (drawinfo)
  353.    {
  354.       // dimension of the border
  355.       sizeobject = NewObject (NULL, SYSICLASS,
  356.        SYSIA_Which, SIZEIMAGE, SYSIA_DrawInfo, drawinfo,
  357.        SYSIA_Size, hires ? SYSISIZE_MEDRES : SYSISIZE_LOWRES, TAG_END);
  358.       if (sizeobject)
  359.       {
  360.          if (GetAttr (IA_Width, sizeobject, &attr))
  361.          {
  362.             sizeiw = attr;
  363.             rightoff =  (UWORD) attr;
  364.          }
  365.          if (GetAttr (IA_Height, sizeobject, &attr))
  366.          {
  367.             sizeih = attr;
  368.          }
  369.          newlook = (drawinfo->dri_Flags & DRIF_NEWLOOK) && (drawinfo->dri_Depth != 1);
  370.          SetAPen (&maskrp, drawinfo->dri_Pens[SHADOWPEN]);
  371.          DisposeObject (sizeobject);
  372.       }
  373.       pens[0] = drawinfo->dri_Pens[FILLTEXTPEN];
  374.       pens[1] = drawinfo->dri_Pens[FILLPEN];
  375.       pens[2] = drawinfo->dri_Pens[TEXTPEN];
  376.       pens[3] = drawinfo->dri_Pens[BACKGROUNDPEN];
  377.       pens[4] = drawinfo->dri_Pens[SHINEPEN];
  378.       pens[5] = drawinfo->dri_Pens[SHADOWPEN];
  379.       FreeScreenDrawInfo (scr, drawinfo);
  380.    }
  381.    else
  382.    {
  383.       // default pens
  384.       pens[0] = 2;
  385.       pens[1] = 3;
  386.       pens[2] = 1;
  387.       pens[3] = 0;
  388.       pens[4] = 2;
  389.       pens[5] = 1;
  390.    }  // if (drawinfo)
  391.    scrrp = &scr->RastPort;
  392.    topoff = scrrp->TxHeight + (UWORD) scr->WBorTop + 1;
  393.    leftoff = scr->WBorLeft;
  394.    scrbm = scrrp->BitMap;
  395.    scrdepth = GetBitMapAttr (scrbm, BMA_DEPTH);
  396.    fontX = topazfont->tf_XSize;
  397.    fontY = topazfont->tf_YSize;
  398.    minwidth = MINWIDTH;
  399.    coordsstringlen = 1;
  400.    if (scr->Width > 999)
  401.    {
  402.       coordsstringlen += 5;
  403.    }
  404.    else
  405.    {
  406.       coordsstringlen += 4;
  407.    }
  408.    if (scr->Height > 999)
  409.    {
  410.       coordsstringlen += 5;
  411.    }
  412.    else
  413.    {
  414.       coordsstringlen += 4;
  415.    }
  416.    if (coords || showrgb)
  417.    {
  418.       bottomoff = sizeih;
  419.       // center the text in the bottomborder
  420.       textoff = (bottomoff + fontY >> 1) - topazfont->tf_Baseline;
  421.       minwidth = 0;
  422.       if (coords)
  423.       {
  424.          minwidth = coordsstringlen * (fontX);
  425.       }
  426.       if (showrgb)
  427.       {
  428.          minwidth += 13 * (fontX);
  429.       }
  430.       // SysIHack or height of screenfont <= 8?
  431.       if ((bottomoff - 2) >= scr->Font->ta_YSize)
  432.       {
  433.          screenfont = OpenFont (scr->Font);
  434.          if (screenfont)
  435.          {
  436.             if (!(screenfont->tf_Flags & FPF_PROPORTIONAL))
  437.             {
  438.                fontX = screenfont->tf_XSize;
  439.                fontY = screenfont->tf_YSize;
  440.                minwidth = 0;
  441.                if (coords)
  442.                {
  443.                   minwidth = coordsstringlen * (fontX);
  444.                }
  445.                if (showrgb)
  446.                {
  447.                   minwidth += 13 * (fontX);
  448.                }
  449.                // center the text in the bottomborder
  450.                textoff = (bottomoff + fontY >> 1) - screenfont->tf_Baseline;
  451.             }
  452.             else
  453.             {
  454.                CloseFont (screenfont);
  455.                screenfont = NULL;               
  456.             }
  457.          }
  458.       }
  459.    }  // if (coords
  460.    else
  461.    {
  462.       bottomoff = scr->WBorBottom;
  463.    }
  464. }
  465.  
  466. void setwintitle ()
  467. {
  468.  LONG args[] = { (LONG) "Lupe", scalefac };
  469.  
  470.    RawDoFmt ("%s %ld:1", args, (void (*)()) Putchar, title);
  471.    SetWindowTitles (mywin, title, (STRPTR) ~0);
  472. }
  473.  
  474. void setmenu ()
  475. {
  476.  struct MenuItem *mitem;
  477.  
  478.    if (mywin)
  479.    {
  480.       ClearMenuStrip (mywin);
  481.  
  482.       mitem = ItemAddress (menu, FULLMENUNUM (0, 2, NOSUB));
  483.       if (jumptoactivescreen) mitem->Flags |= CHECKED;
  484.       else mitem->Flags &= ~CHECKED;
  485.  
  486.       mitem = ItemAddress (menu, FULLMENUNUM (0, 6, NOSUB));
  487.       if (enable) mitem->Flags |= CHECKED;
  488.       else mitem->Flags &= ~CHECKED;
  489.  
  490.       mitem = mitem->NextItem;
  491.       if (fixed) mitem->Flags |= CHECKED;
  492.       else mitem->Flags &= ~CHECKED;
  493.  
  494.       mitem = mitem->NextItem;
  495.       if (fast) mitem->Flags |= CHECKED;
  496.       else mitem->Flags &= ~CHECKED;
  497.  
  498.       mitem = mitem->NextItem;
  499.       if (coords) mitem->Flags |= CHECKED;
  500.       else mitem->Flags &= ~CHECKED;
  501.  
  502.       mitem = mitem->NextItem;
  503.       if (crosshair) mitem->Flags |= CHECKED;
  504.       else mitem->Flags &= ~CHECKED;
  505.  
  506.       mitem = mitem->NextItem;
  507.       if (grid) mitem->Flags |= CHECKED;
  508.       else mitem->Flags &= ~CHECKED;
  509.  
  510.       mitem = mitem->NextItem;
  511.       if (showrgb) mitem->Flags |= CHECKED;
  512.       else mitem->Flags &= ~CHECKED;
  513.  
  514.       mitem = ItemAddress (menu, FULLMENUNUM (0, 16, NOSUB));
  515.       if (hideonclose) mitem->Flags |= CHECKED;
  516.       else mitem->Flags &= ~CHECKED;
  517.  
  518.       ResetMenuStrip (mywin, menu);
  519.    }
  520. }
  521.  
  522. void setupgrid ()
  523. {
  524.  UWORD i, j;
  525.  
  526.    if (maskbm)
  527.    {
  528.       FreeBitMap (maskbm);
  529.       maskbm = NULL;
  530.    }
  531.    if (grid && (scalefac > 1))
  532.    {
  533.       maskbm = AllocBitMap (innerwidth, innerheight, 1, BMF_CLEAR, destbm);
  534.       if (!maskbm)
  535.       {
  536.          error (GetString (TXT_ERROR_GRIDMASK));
  537.          grid = FALSE;
  538.          setmenu ();
  539.       }
  540.       else
  541.       {
  542.          maskrp.BitMap = maskbm;
  543.          for (i = scalefac - 1; i < innerwidth; i += scalefac)
  544.          {
  545.             RectFill (&maskrp, i, 0, i, innerheight - 1);
  546.             for (j = scalefac - 1; j < innerheight; j += scalefac)
  547.             {
  548.                WritePixel (&maskrp, i, j);
  549.             }
  550.          }
  551.          for (i = scalefac - 1; i < innerheight; i += scalefac)
  552.          {
  553.             RectFill (&maskrp, 0, i, innerwidth - 1, i);
  554.          }
  555.       }
  556.    }
  557. }
  558.  
  559. void allocbm ()
  560. {
  561.    if (srcbm)
  562.    {
  563.       FreeBitMap (srcbm);
  564.       srcbm = NULL;
  565.    }
  566.    if (destbm)
  567.    {
  568.       FreeBitMap (destbm);
  569.       destbm = NULL;
  570.    }
  571.    winx = mywin->Width;
  572.    winy = mywin->Height;
  573.    innerwidth = winx - (leftoff + rightoff);
  574.    innerheight = winy - (topoff + bottomoff);
  575.    sourcewidth = innerwidth / scalefac;
  576.    sourceheight = innerheight / scalefac;
  577.    if (scalefac > 1)
  578.    {
  579.       if (!(srcbm = AllocBitMap (sourcewidth, sourceheight, cybergfxscreen ? 24 : scrdepth, cybergfxscreen ? (BMF_CLEAR | BMF_MINPLANES | PIXFMT_RGB24) : BMF_CLEAR, scrbm)))
  580.       {
  581.          error (GetString (TXT_ERROR_SOURCEBMP));
  582.          throw 1;
  583.       }
  584.       if (!(destbm = AllocBitMap (innerwidth, innerheight, cybergfxscreen ? 24 : scrdepth, cybergfxscreen ? (BMF_CLEAR | BMF_MINPLANES | PIXFMT_RGB24) : BMF_CLEAR, srcbm)))
  585.       {
  586.          error (GetString (TXT_ERROR_DESTBMP));
  587.          throw 2;
  588.       }
  589.       bsa.bsa_SrcWidth = sourcewidth;
  590.       bsa.bsa_SrcHeight = sourceheight;
  591.       bsa.bsa_DestWidth = innerwidth;
  592.       bsa.bsa_DestHeight = innerheight;
  593.       bsa.bsa_SrcBitMap = srcbm;
  594.       bsa.bsa_DestBitMap = destbm;
  595.       bsa.bsa_XDestFactor = bsa.bsa_YDestFactor = scalefac;
  596.       setupgrid ();
  597.       destrp.BitMap = destbm;
  598.    }
  599. }
  600.  
  601. void makescreenmenu ()
  602. {
  603.  struct NewMenu tmpmenu[] = {
  604.   { NM_SUB, 0, 0, 0, 0, 0 },
  605.   { NM_END, 0, 0, 0, 0, 0 }
  606.  };
  607.  ULONG lock;
  608.  struct List *pubscreenlist;
  609.  struct PubScreenNode *pubscreennode;
  610.  struct MenuItem **itempointer = &menu->FirstItem->NextItem->SubItem;
  611.  
  612.    lock = LockIBase (0);
  613.    tmpscr = IntuitionBase->FirstScreen;
  614.    if (tmpscr->NextScreen)
  615.    {
  616.       while ((tmpscr = tmpscr->NextScreen) != 0)
  617.       {
  618.          (*tmpmenu).nm_Label = tmpscr->DefaultTitle;
  619.          pubscreenlist = LockPubScreenList ();
  620.          if (pubscreenlist)
  621.          {
  622.             pubscreennode = (struct PubScreenNode *) pubscreenlist->lh_Head;
  623.             while (pubscreennode)
  624.             {
  625.                if (pubscreennode->psn_Screen == tmpscr)
  626.                {
  627.                   if (pubscreennode->psn_Node.ln_Name)
  628.                   {
  629.                      tmpmenu->nm_Label = pubscreennode->psn_Node.ln_Name;
  630.                   }
  631.                   break;
  632.                }
  633.                pubscreennode = (struct PubScreenNode *) pubscreennode->psn_Node.ln_Succ;
  634.             }
  635.             UnlockPubScreenList ();
  636.          }
  637.          if (!tmpmenu->nm_Label)
  638.          {
  639.             tmpmenu->nm_Label = GetString (TXT_UNNAMED);
  640.          }
  641.          tmpmenu->nm_UserData = tmpscr;
  642.          // each item single created
  643.          *itempointer = (struct MenuItem *) CreateMenusA (tmpmenu, NULL);
  644.          if (*itempointer)
  645.          {
  646.             itempointer = &(*itempointer)->NextItem;
  647.          }
  648.          else
  649.          {
  650.             error (GetString (TXT_ERROR_SCREENMENUITEM));
  651.          }
  652.       }
  653.    }
  654.    else
  655.    {
  656.       tmpmenu->nm_Label = GetString (TXT_NOOTHERSCREEN);
  657.       *itempointer = (struct MenuItem *) CreateMenusA (tmpmenu, NULL);
  658.       if (*itempointer)
  659.       {
  660.          (*itempointer)->Flags |= HIGHNONE;
  661.          itempointer = &(*itempointer)->NextItem;
  662.       }
  663.       else
  664.       {
  665.          error (GetString (TXT_ERROR_SCREENMENU));
  666.       }
  667.    }
  668.    UnlockIBase (lock);
  669.    if (!LayoutMenus (menu, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_DONE))
  670.    {
  671.       error (GetString (TXT_ERROR_LAYOUTMENU));
  672.       throw 1;
  673.    }
  674. }
  675.  
  676. void freescreenmenu (struct MenuItem *menuitem)
  677. {
  678.    if (menuitem)
  679.    {
  680.       freescreenmenu (menuitem->NextItem);
  681.       FreeMenus ((struct Menu *) menuitem);
  682.    }
  683. }
  684.  
  685. void openwin ()
  686.  struct NewMenu standardmenu[] = {
  687.    { NM_TITLE, GetString (TXT_PROJECT), 0, 0, 0, 0 },
  688.    {  NM_ITEM, GetString (TXT_JUMP), GetString (KEY_JUMP), 0, 0, jumpFunc },
  689.    {  NM_ITEM, GetString (TXT_JUMPTOSCREEN), 0, 0, 0, 0 },
  690.    {  NM_ITEM, GetString (TXT_JUMPTOACTIVESCREEN), GetString (KEY_JUMPTOACTIVESCREEN), CHECKIT | MENUTOGGLE, 0, jumptoactiveFunc },
  691.    {  NM_ITEM, NM_BARLABEL, 0, 0, 0, 0 },
  692.    {  NM_ITEM, GetString (TXT_SAVEIFF), GetString (KEY_SAVEIFF), 0, 0, saveFunc },
  693.    {  NM_ITEM, NM_BARLABEL, 0, 0, 0, 0 },
  694.    {  NM_ITEM, GetString (TXT_ENABLE), GetString (KEY_ENABLE), CHECKIT | MENUTOGGLE, 0, enableFunc },
  695.    {  NM_ITEM, GetString (TXT_FIXED), GetString (KEY_FIXED), CHECKIT | MENUTOGGLE, 0, fixedFunc },
  696.    {  NM_ITEM, GetString (TXT_FAST), GetString (KEY_FAST), CHECKIT | MENUTOGGLE, 0, fastFunc },
  697.    {  NM_ITEM, GetString (TXT_COORDINATES), GetString (KEY_COORDINATES), CHECKIT | MENUTOGGLE, 0, coordsFunc },
  698.    {  NM_ITEM, GetString (TXT_CROSSHAIR), GetString (KEY_CROSSHAIR), CHECKIT | MENUTOGGLE, 0, crosshairFunc },
  699.    {  NM_ITEM, GetString (TXT_GRID), GetString (KEY_GRID), CHECKIT | MENUTOGGLE, 0, gridFunc },
  700.    {  NM_ITEM, GetString (TXT_SHOWRGB), GetString (KEY_SHOWRGB), CHECKIT | MENUTOGGLE, 0, showrgbFunc },
  701.    {  NM_ITEM, NM_BARLABEL, 0, 0, 0, 0 },
  702.    {  NM_ITEM, GetString (TXT_ABOUT), GetString (KEY_ABOUT), 0, 0, AboutFunc },
  703.    {  NM_ITEM, NM_BARLABEL, 0, 0, 0, 0 },
  704.    {  NM_ITEM, GetString (TXT_ICONIFYONCLOSE), GetString (KEY_ICONIFYONCLOSE), CHECKIT | MENUTOGGLE, 0, hideoncloseFunc },
  705.    {  NM_ITEM, GetString (TXT_ICONIFY), GetString (KEY_ICONIFY), 0, 0, hideFunc },
  706.    {  NM_ITEM, GetString (TXT_QUIT), GetString (KEY_QUIT), 0, 0, QuitFunc },
  707.    {  NM_END, 0, 0, 0, 0, 0 }
  708.  };
  709.  ULONG lock;
  710.  WORD bw, rh;
  711.  struct Rectangle zoom = {
  712.     minwidth + leftoff + rightoff,
  713.     MINHEIGHT + topoff + bottomoff + sizeih,
  714.     9999, 9999
  715.  };
  716.  
  717.    if (!mywin)
  718.    {
  719.       if (hires)
  720.       {
  721.          bw = rh = 2;
  722.       }
  723.       else
  724.       {
  725.          bw = rh = 1;
  726.       }
  727.       // first bring the screen to front
  728.       //  -> screen order in menu correct
  729.       lock = LockIBase (0);
  730.       tmpscr = IntuitionBase->FirstScreen;
  731.       UnlockIBase (lock);
  732.       if (tmpscr != scr)
  733.       {
  734.          if (jumpdirect)
  735.          {
  736.             ScreenToFront (scr);
  737.          }
  738.          else
  739.          {
  740.             ScreenToBack (tmpscr);
  741.          }
  742.       }
  743.       menu = CreateMenusA (standardmenu, NULL);
  744.       if (!menu)
  745.       {
  746.          error (GetString (TXT_ERROR_MENU));
  747.          throw (1);
  748.       }
  749.       makescreenmenu ();
  750.       propgadget = (Object *) NewObject (NULL, PROPGCLASS,
  751.         PGA_Freedom,     FREEVERT,
  752.         ICA_TARGET,      ICTARGET_IDCMP,
  753.         PGA_NewLook,     TRUE,
  754.         PGA_Borderless,  newlook,
  755.         PGA_Total,       maxscalefac,
  756.         PGA_Visible,     1,
  757.         PGA_Top,         scalefac - 1,
  758.         GA_RelRight,     bw - sizeiw + 3,
  759.         GA_Top,          topoff + rh,
  760.         GA_Width,        sizeiw - bw - bw - 4,
  761.         GA_RelHeight,    -topoff - sizeih - rh - rh,
  762.         GA_RightBorder,  TRUE,
  763.         TAG_DONE);
  764.       if (!propgadget)
  765.       {
  766.          error (GetString (TXT_ERROR_PROPGADGET));
  767.          throw (2);
  768.       }
  769.       if (innerwidth < minwidth)
  770.       {
  771.          innerwidth = minwidth;
  772.       }
  773.       mywin = OpenWindowTags (NULL,
  774.         WA_Flags,          WFLG_ACTIVATE | WFLG_CLOSEGADGET | WFLG_DEPTHGADGET
  775.                             | WFLG_DRAGBAR | WFLG_SIZEGADGET | WFLG_SIMPLE_REFRESH
  776.                             | WFLG_NEWLOOKMENUS | WFLG_REPORTMOUSE | WFLG_SIZEBRIGHT
  777.                             | ((coords || showrgb) ? WFLG_SIZEBBOTTOM : 0),
  778.         WA_AutoAdjust,     1,
  779.         WA_MaxHeight,      9999,
  780.         WA_MaxWidth,       9999,
  781.         WA_MinHeight,      MINHEIGHT + topoff + bottomoff,
  782.         WA_MinWidth,       minwidth + leftoff + rightoff,
  783.         WA_IDCMP,          IDCMP_CLOSEWINDOW | IDCMP_IDCMPUPDATE | IDCMP_NEWSIZE
  784.                             | IDCMP_MENUPICK | IDCMP_ACTIVEWINDOW
  785.                             | IDCMP_INACTIVEWINDOW | IDCMP_MOUSEMOVE | IDCMP_VANILLAKEY
  786.                             | IDCMP_RAWKEY | IDCMP_REFRESHWINDOW,
  787.         WA_InnerHeight,    innerheight,
  788.         WA_InnerWidth,     innerwidth,
  789.         WA_Left,           winleft,
  790.         WA_Gadgets,        propgadget,
  791.         WA_Top,            wintop,
  792.         pubscreenlocked ? WA_PubScreen : WA_CustomScreen, scr,
  793.         WA_Zoom,           &zoom,
  794.         TAG_DONE);
  795.       if (!mywin)
  796.       {
  797.          error (GetString (TXT_ERROR_WINDOW));
  798.          throw (3);
  799.       }
  800.       // shit patches
  801.       leftoff = mywin->BorderLeft;
  802.       bottomoff = mywin->BorderBottom;
  803.       SetMenuStrip (mywin, menu);
  804.       setmenu ();
  805.       setwintitle ();
  806.       userport = mywin->UserPort;
  807.       winrp = mywin->RPort;
  808.       if (screenfont)
  809.       {
  810.          SetFont (winrp, screenfont);
  811.       }
  812.       else
  813.       {
  814.          SetFont (winrp, topazfont);
  815.       }
  816.       SetAPen (winrp, pens[0]);
  817.       SetBPen (winrp, pens[1]);
  818.       waitmask |= 1 << userport->mp_SigBit;
  819.    }
  820. }
  821.  
  822. void closewin ()
  823. {
  824.    if (mywin)
  825.    {
  826.       if (menu)
  827.       {
  828.          ClearMenuStrip (mywin);
  829.       }
  830.       wintop = mywin->TopEdge;
  831.       winleft = mywin->LeftEdge;
  832.       waitmask &= ~(1 << userport->mp_SigBit);
  833.       CloseWindow (mywin);
  834.       mywin = NULL;
  835.       userport = NULL;
  836.       jump = TRUE;
  837.    }
  838.    if (menu)
  839.    {
  840.       freescreenmenu (ItemAddress (menu, FULLMENUNUM (0, 1, 0)));
  841.       FreeMenus (menu);
  842.       menu = NULL;
  843.    }
  844.    if (propgadget)
  845.    {
  846.       DisposeObject (propgadget);
  847.       propgadget = NULL;
  848.    }
  849.    if (srcbm)
  850.    {
  851.       FreeBitMap (srcbm);
  852.       srcbm = NULL;
  853.    }
  854.    if (destbm)
  855.    {
  856.       FreeBitMap (destbm);
  857.       destbm = NULL;
  858.    }
  859.    if (maskbm)
  860.    {
  861.       FreeBitMap (maskbm);
  862.       maskbm = NULL;
  863.    }
  864. }
  865.  
  866. BOOL screen_is_still_open ()
  867. {
  868.    tmpscr = IntuitionBase->FirstScreen;
  869.    while (tmpscr)
  870.    {
  871.       if (tmpscr == scr)
  872.       {
  873.          return TRUE;
  874.       }
  875.       tmpscr = tmpscr->NextScreen;
  876.    }
  877.    return FALSE;
  878. }
  879.  
  880. void freeappicon ()
  881. {
  882.    if (appicon)
  883.    {
  884.       RemoveAppIcon (appicon);
  885.       appicon = NULL;
  886.    }
  887.    if (app_mp)
  888.    {
  889.       waitmask &= ~(1 << app_mp->mp_SigBit);
  890.       DeleteMsgPort (app_mp);
  891.       app_mp = NULL;
  892.    }
  893.    if (icon)
  894.    {
  895.       FreeDiskObject (icon);
  896.       icon = NULL;
  897.    }
  898. }
  899.  
  900. void showwindow ()
  901. {
  902.  ULONG lock;
  903.  
  904.    if (!mywin)
  905.    {
  906.       if (jumptoactivescreen)
  907.       {
  908.          lock = LockIBase (0);
  909.          scr = IntuitionBase->ActiveScreen;
  910.          UnlockIBase (lock);
  911.          
  912.       }
  913.       else if (!screen_is_still_open ())
  914.       {
  915.          scr = NULL;
  916.       }
  917.       setupscreen (scr);
  918.       getoffsets ();
  919.       openwin ();
  920.       allocbm ();
  921.       freeappicon ();
  922.    }
  923. }
  924.  
  925. void hidewindow ()
  926. {
  927.    closewin ();
  928.    CloseDownScreen ();
  929.  
  930.    freeappicon ();
  931.  
  932.    if (Cli ())
  933.    {
  934.       GetProgramName (programname, 108);
  935.    }
  936.    else
  937.    {
  938.       strncpy (programname, thistask->tc_Node.ln_Name, 108);
  939.    }
  940.    icon = GetDiskObject ("ENV:sys/def_Lupe");
  941.    if (!icon)
  942.    {
  943.       icon = GetDiskObject (programname);
  944.       if (!icon)
  945.       {
  946.          icon = GetDefDiskObject (WBTOOL);
  947.       }
  948.    }
  949.    if (icon)
  950.    {
  951.       app_mp = CreateMsgPort ();
  952.       if (app_mp)
  953.       {
  954.          appicon = AddAppIcon (1, 0, "Lupe", app_mp, NULL, icon, NULL);
  955.          if (appicon)
  956.          {
  957.             waitmask |= 1 << app_mp->mp_SigBit;
  958.          }
  959.       }
  960.    }
  961. }
  962.  
  963. //- refresh ------------------------------------
  964.  
  965. void printcoords (LONG x, LONG y)
  966. {
  967.    if (coords)
  968.    {
  969.     LONG args[] = {x - originX, y - originY};
  970.  
  971.       memset (dispstring, ' ', coordsstringlen);
  972.       RawDoFmt ("%ld,%ld", args, (void (*)()) Putchar, dispstring);
  973.       dispstring[strlen (dispstring)] = ' ';
  974.       mywin->Flags &= ~SIZEGADGET;
  975.       if ((winx == mywin->Width) && (winy == mywin->Height))
  976.       {
  977.          Move (winrp, leftoff, mywin->Height - textoff);
  978.          Text (winrp, dispstring, coordsstringlen);
  979.       }
  980.       mywin->Flags |= SIZEGADGET;
  981.    }
  982. }
  983.  
  984. void printrgb (LONG x, LONG y)
  985. {
  986.  ULONG colorreg, colors[3], apen, textlen, cybercolor;
  987.  
  988.    if (showrgb)
  989.    {
  990.       colorreg = ReadPixel (scrrp, x, y);
  991.       if (cybergfxscreen)
  992.       {
  993.          cybercolor = ReadRGBPixel (scrrp, x, y);
  994.          colors[0] = (cybercolor >> 16) & 0xff;
  995.          colors[1] = (cybercolor >> 8) & 0xff;
  996.          colors[2] = cybercolor & 0xff;
  997.       }
  998.       else
  999.       {
  1000.          GetRGB32 (scr->ViewPort.ColorMap, colorreg, 1, colors);
  1001.          colors[0] &= 0xff;
  1002.          colors[1] &= 0xff;
  1003.          colors[2] &= 0xff;
  1004.       }
  1005.       RawDoFmt ("%3ld,%3ld,%3ld", colors, (void (*)()) Putchar, dispstring);
  1006.       textlen = TextLength (winrp, dispstring, 11);
  1007.       apen = GetAPen (winrp);
  1008.       mywin->Flags &= ~SIZEGADGET;
  1009.       if ((winx == mywin->Width) && (winy == mywin->Height))
  1010.       {        
  1011.          Move (winrp, innerwidth - textlen, mywin->Height - textoff);
  1012.          Text (winrp, dispstring, 11);
  1013.          SetAPen (winrp, pens[5]);
  1014.          Move (winrp, innerwidth - textlen - fontX - 1, mywin->Height - (bottomoff - fontY >> 1) - 2);
  1015.          Draw (winrp, innerwidth - textlen - fontX - 1, mywin->Height - (bottomoff - fontY >> 1) - fontY);
  1016.          Draw (winrp, innerwidth - textlen - 2, mywin->Height - (bottomoff - fontY >> 1) - fontY);
  1017.          SetAPen (winrp, pens[4]);
  1018.          Move (winrp, innerwidth - textlen - 1, mywin->Height - (bottomoff - fontY >> 1) - fontY + 1);
  1019.          Draw (winrp, innerwidth - textlen - 1, mywin->Height - (bottomoff - fontY >> 1) - 1);
  1020.          Draw (winrp, innerwidth - textlen - fontX, mywin->Height - (bottomoff - fontY >> 1) - 1);
  1021.          if (cybergfxscreen)
  1022.          {
  1023.             FillPixelArray (winrp, innerwidth - textlen - fontX, mywin->Height - (bottomoff - fontY >> 1) - fontY + 1,
  1024.               fontX - 1, fontY - 2, cybercolor);
  1025.          }
  1026.          else
  1027.          {
  1028.             SetAPen (winrp, colorreg);
  1029.             RectFill (winrp, innerwidth - textlen - fontX, mywin->Height - (bottomoff - fontY >> 1) - fontY + 1,
  1030.               innerwidth - textlen - 2, mywin->Height - (bottomoff - fontY >> 1) - 2);
  1031.          }
  1032.       }
  1033.       mywin->Flags |= SIZEGADGET;
  1034.       SetAPen (winrp, apen);
  1035.    }  // if (showrgb)
  1036. }
  1037.  
  1038. // displace the coords and set the offsets for crosshair
  1039. LONG adjustX (LONG &x)
  1040. {
  1041.  LONG xoff = 0;
  1042.  
  1043.    x -= sourcewidth >> 1;
  1044.    if (x < 0)
  1045.    {
  1046.       xoff = x;
  1047.       x = 0;
  1048.    }
  1049.    else if (x > (scr->Width - sourcewidth))
  1050.    {
  1051.       xoff = -(scr->Width - sourcewidth - x);
  1052.       x = scr->Width - sourcewidth;
  1053.    }
  1054.    return xoff;
  1055. }
  1056.  
  1057. LONG adjustY (LONG &y)
  1058. {
  1059.  LONG yoff = 0;
  1060.  
  1061.    y -= sourceheight >> 1;
  1062.    if (y < 0)
  1063.    {
  1064.       yoff = y;
  1065.       y = 0;
  1066.    }
  1067.    else if (y > (scr->Height - sourceheight))
  1068.    {
  1069.       yoff = -(scr->Height - sourceheight - y);
  1070.       y = scr->Height - sourceheight;
  1071.    }
  1072.    return yoff;
  1073. }
  1074.  
  1075. void refresh ()
  1076. {
  1077.  LONG x, y, xoff, yoff;
  1078.  
  1079.    if (mywin)
  1080.    {
  1081.       // set the coordinates
  1082.       if (enable)
  1083.       {
  1084.          if (fixed)
  1085.          {
  1086.             x = fixedX;
  1087.             y = fixedY;
  1088.          }
  1089.          else
  1090.          {
  1091.             x = scr->MouseX;
  1092.             y = scr->MouseY;
  1093.          }
  1094.          oldx = x;
  1095.          oldy = y;
  1096.       }
  1097.       else
  1098.       {
  1099.          x = oldx;
  1100.          y = oldy;
  1101.       }
  1102.       
  1103.       printcoords (x, y);
  1104.       printrgb (x, y);
  1105.  
  1106.       // displaces the coords and sets the offsets for crosshair
  1107.       xoff = adjustX (x);
  1108.       yoff = adjustY (y);
  1109.  
  1110.       // adjusts the offsets to scalefac
  1111.       if (crosshair)
  1112.       {
  1113.          xoff = scalefac * ((sourcewidth >> 1) + xoff) + (scalefac - 1 >> 1);
  1114.          yoff = scalefac * ((sourceheight >> 1) + yoff) + (scalefac - 1 >> 1);
  1115.       }
  1116.  
  1117.       if (scalefac > 1)
  1118.       {
  1119.          // blit and scale
  1120.          BltBitMap (scrbm, x, y, srcbm, 0, 0, sourcewidth, sourceheight, ABNC | ABC, ~0, NULL);
  1121.          BitMapScale (&bsa);
  1122.          // draw the grid
  1123.          if (grid)
  1124.          {
  1125.             SetDrMd (&destrp, JAM1);
  1126.             BltTemplate (maskbm->Planes[0], 0, maskbm->BytesPerRow, &destrp, 0, 0, sourcewidth * scalefac, sourceheight * scalefac);
  1127.          }
  1128.          // draw the crosshair
  1129.          if (crosshair)
  1130.          {
  1131.             SetDrMd (&destrp, COMPLEMENT);
  1132.             RectFill (&destrp, xoff, 0, xoff, sourceheight * scalefac - 1);
  1133.             RectFill (&destrp, 0, yoff, sourcewidth * scalefac - 1, yoff);
  1134.          }
  1135.          mywin->Flags &= ~SIZEGADGET;
  1136.          if ((winx == mywin->Width) && (winy == mywin->Height))
  1137.          {
  1138.             BltBitMapRastPort (destbm, 0, 0, winrp, leftoff, topoff, innerwidth, innerheight, ABNC | ABC);
  1139.          }
  1140.          mywin->Flags |= SIZEGADGET;
  1141.       }
  1142.       else  // 1:1
  1143.       {
  1144.          mywin->Flags &= ~SIZEGADGET;
  1145.          if ((winx == mywin->Width) && (winy == mywin->Height))
  1146.          {
  1147.             BltBitMapRastPort (scrbm, x, y, winrp, leftoff, topoff, innerwidth, innerheight, ABNC | ABC);
  1148.             // draw the crosshair in 1:1
  1149.             if (crosshair)
  1150.             {
  1151.                SetDrMd (winrp, COMPLEMENT);
  1152.                RectFill (winrp, leftoff + xoff, topoff, leftoff + xoff, topoff + innerheight - 1);
  1153.                RectFill (winrp, leftoff, topoff + yoff, leftoff + innerwidth - 1, topoff + yoff);
  1154.                SetDrMd (winrp, JAM2);
  1155.             }
  1156.          }
  1157.          mywin->Flags |= SIZEGADGET;
  1158.       }
  1159.       if (!fast)
  1160.       {
  1161.          SetSignal (0, 1 << timesig);
  1162.       }
  1163.    }
  1164. }
  1165.  
  1166. void reopenwin ()
  1167. {
  1168.    closewin ();
  1169.    getoffsets ();
  1170.    openwin ();
  1171.    allocbm ();
  1172. }
  1173.  
  1174. void setpropgad ()
  1175. {
  1176.    allocbm ();
  1177.    SetAttrs (propgadget, PGA_Top, scalefac - 1);
  1178.    RefreshGList ((struct Gadget *) propgadget, mywin, NULL, 1);
  1179.    setwintitle ();
  1180. }
  1181.  
  1182. //- Commodity ----------------------------------
  1183.  
  1184. void CxFunction (CxMsg *cxm, CxObj *co)
  1185. {
  1186.  struct InputEvent *ie = (struct InputEvent *) CxMsgData (cxm);
  1187.  
  1188.    if (origin)
  1189.    {
  1190.       if (MatchIX (ie, &setoriginix))
  1191.       {
  1192.          originX = scr->MouseX;
  1193.          originY = scr->MouseY;
  1194.          DisposeCxMsg (cxm);
  1195.          return;
  1196.       }
  1197.       if (MatchIX (ie, &resetoriginix))
  1198.       {
  1199.          originX = originY = 0;
  1200.          DisposeCxMsg (cxm);
  1201.          return;
  1202.       }
  1203.    }
  1204.    if (showhide)
  1205.    {
  1206.       if (MatchIX (ie, &showhideix))
  1207.       {
  1208.          Signal (thistask, 1 << showhidesig);
  1209.          DisposeCxMsg (cxm);
  1210.       }
  1211.    }
  1212.    if ((ie->ie_Class == IECLASS_TIMER) || fast)
  1213.    {
  1214.       Signal (thistask, 1 << timesig);
  1215.    }
  1216. }
  1217.  
  1218. void initbroker ()
  1219. {
  1220.  LONG errorcode;
  1221.  
  1222.    broker_mp = CreateMsgPort ();
  1223.    if (!broker_mp)
  1224.    {
  1225.       error (GetString (TXT_ERROR_COMMODITYMP));
  1226.       throw (1);
  1227.    }
  1228.    newbroker.nb_Port = broker_mp;
  1229.    newbroker.nb_Descr = GetString (TXT_DESCRIPTION),
  1230.    cxsigflag = 1 << broker_mp->mp_SigBit;
  1231.    broker = CxBroker (&newbroker, &errorcode);
  1232.    if (!broker)
  1233.    {
  1234.       if (errorcode == CBERR_SYSERR)
  1235.       {
  1236.          error (GetString (TXT_ERROR_COMMODITYBROKER));
  1237.       }
  1238.       throw (2);
  1239.    }
  1240.    customcxobj = CxCustom (CxFunction, 0);
  1241.    if (!customcxobj)
  1242.    {
  1243.       error (GetString (TXT_ERROR_COMMODITYCUSTOM));
  1244.       throw (3);
  1245.    }
  1246.    AttachCxObj (broker, customcxobj);
  1247.    if (CxObjError (customcxobj))
  1248.    {
  1249.       error (GetString (TXT_ERROR_COMMODITYBROKER));
  1250.       throw (4);
  1251.    }
  1252.    if (ParseIX (setoriginkey, &setoriginix) || ParseIX (resetoriginkey, &resetoriginix))
  1253.    {
  1254.       origin = FALSE;
  1255.       error (GetString (TXT_ERROR_HOTKEY), "'Set Origin'");
  1256.    }
  1257.    if (ParseIX (showhidekey, &showhideix))
  1258.    {
  1259.       showhide = FALSE;
  1260.       error (GetString (TXT_ERROR_HOTKEY), "'Show/Hide Window'");
  1261.    }
  1262.    ActivateCxObj (broker, 1);
  1263. }
  1264.  
  1265. //- messages -----------------------------------
  1266.  
  1267. BOOL menupick (UWORD code)
  1268. {
  1269.  static BOOL (*func)();
  1270.  
  1271.    while ((code != MENUNULL) && !jump)
  1272.    {
  1273.       item = ItemAddress (menu, code);
  1274.       if (SUBNUM (code) != NOSUB)
  1275.       {
  1276.          if (GTMENUITEM_USERDATA (item))  // 'no other screen'-submenu == 0
  1277.          {
  1278.             setupscreen ((struct Screen *) GTMENUITEM_USERDATA (item));
  1279.             reopenwin ();
  1280.          }
  1281.       }
  1282.       else
  1283.       {
  1284.          func = (BOOL (*)()) GTMENUITEM_USERDATA (item);
  1285.          if (func () == FALSE)
  1286.          {
  1287.             return FALSE;
  1288.          }
  1289.       }
  1290.       if (!jump) code = item->NextSelect;
  1291.    }
  1292.    return TRUE;
  1293. }
  1294.  
  1295. BOOL vanillakey (UWORD code)
  1296. {
  1297.  BOOL returnvalue = TRUE;
  1298.  
  1299.    code = ToUpper (code);
  1300.  
  1301.    if (code == ToUpper (*GetString (KEY_JUMP)))
  1302.    {
  1303.       returnvalue = jumpFunc ();    
  1304.    }
  1305.    else if (code == ToUpper (*GetString (KEY_JUMPTOACTIVESCREEN)))
  1306.    {
  1307.       jumptoactivescreen = !jumptoactivescreen;
  1308.       setmenu ();    
  1309.    }
  1310.    else if (code == ToUpper (*GetString (KEY_SAVEIFF)))
  1311.    {
  1312.       returnvalue = saveFunc ();
  1313.    }
  1314.    else if (code == ToUpper (*GetString (KEY_ENABLE)))
  1315.    {
  1316.       enable = !enable;
  1317.       ActivateCxObj (broker, enable);
  1318.       setmenu ();
  1319.    }
  1320.    else if (code == ToUpper (*GetString (KEY_FIXED)))
  1321.    {
  1322.       fixed = !fixed;
  1323.       fixedX = scr->MouseX;
  1324.       fixedY = scr->MouseY;
  1325.       setmenu ();
  1326.    }
  1327.    else if (code == ToUpper (*GetString (KEY_FAST)))
  1328.    {
  1329.       fast = !fast;
  1330.       setmenu ();
  1331.    }
  1332.    else if (code == ToUpper (*GetString (KEY_COORDINATES)))
  1333.    {
  1334.       coords = !coords;
  1335.       reopenwin ();
  1336.    }
  1337.    else if (code == ToUpper (*GetString (KEY_CROSSHAIR)))
  1338.    {
  1339.       crosshair = !crosshair;
  1340.       setmenu ();
  1341.    }
  1342.    else if (code == ToUpper (*GetString (KEY_GRID)))
  1343.    {
  1344.       grid = !grid;
  1345.       setupgrid ();
  1346.       setmenu ();
  1347.    }
  1348.    else if (code == ToUpper (*GetString (KEY_SHOWRGB)))
  1349.    {
  1350.       showrgb = !showrgb;
  1351.       reopenwin ();
  1352.    }
  1353.    else if (code == ToUpper (*GetString (KEY_ABOUT)))
  1354.    {
  1355.       returnvalue = AboutFunc ();
  1356.    }
  1357.    else if (code == ToUpper (*GetString (KEY_ICONIFYONCLOSE)))
  1358.    {
  1359.       hideonclose = !hideonclose;
  1360.       setmenu ();
  1361.    }
  1362.    else if (code == ToUpper (*GetString (KEY_ICONIFY)))
  1363.    {
  1364.       returnvalue = hideFunc ();
  1365.    }
  1366.    else if (code == ToUpper (*GetString (KEY_QUIT)))
  1367.    {
  1368.       returnvalue = FALSE;
  1369.    }
  1370.    else switch (code)
  1371.    {
  1372.     case 27:  // ESC
  1373.       if (hideonclose)
  1374.       {
  1375.          hidewindow ();
  1376.          jump = TRUE;
  1377.       }
  1378.       else
  1379.       {
  1380.          returnvalue = FALSE;
  1381.       }
  1382.       break;
  1383.     case '+':
  1384.       if (scalefac < maxscalefac)
  1385.       {
  1386.          scalefac++;
  1387.          setpropgad ();
  1388.       }
  1389.       break;
  1390.     case '-':
  1391.       if (scalefac > 1)
  1392.       {
  1393.          scalefac--;
  1394.          setpropgad ();
  1395.       }
  1396.       break;
  1397.    }
  1398.    return returnvalue;
  1399. }
  1400.  
  1401. void rawkey (UWORD code, UWORD qualifier)
  1402. {
  1403.    switch (code)
  1404.    {
  1405.     // up
  1406.     case 76:
  1407.       if (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1408.       {
  1409.          fixedY -= sourceheight - 1;
  1410.          if (fixedY < 0)
  1411.          {
  1412.             fixedY = 0;
  1413.          }
  1414.       }
  1415.       else if (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1416.       {
  1417.          fixedY = 0;
  1418.       }
  1419.       else if (fixedY)
  1420.       {
  1421.          fixedY--;
  1422.       }
  1423.       break;
  1424.     // down
  1425.     case 77:
  1426.       if (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1427.       {
  1428.          fixedY += sourceheight - 1;
  1429.          if (fixedY > (scr->Height - 1))
  1430.          {
  1431.             fixedY = scr->Height - 1;
  1432.          }
  1433.       }
  1434.       else if (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1435.       {
  1436.          fixedY = scr->Height - 1;
  1437.       }
  1438.       else if (fixedY < (scr->Height - 1))
  1439.       {
  1440.          fixedY++;
  1441.       }
  1442.       break;
  1443.     // right
  1444.     case 78:
  1445.       if (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1446.       {
  1447.          fixedX += sourcewidth - 1;
  1448.          if (fixedX > (scr->Width - 1))
  1449.          {
  1450.             fixedX = scr->Width - 1;
  1451.          }
  1452.       }
  1453.       else if (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1454.       {
  1455.          fixedX = scr->Width - 1;
  1456.       }
  1457.       else if (fixedX < (scr->Width - 1))
  1458.       {
  1459.          fixedX++;
  1460.       }
  1461.       break;
  1462.     // left
  1463.     case 79:
  1464.       if (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1465.       {
  1466.          fixedX -= sourcewidth - 1;
  1467.          if (fixedX < 0)
  1468.          {
  1469.             fixedX = 0;
  1470.          }
  1471.       }
  1472.       else if (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1473.       {
  1474.          fixedX = 0;
  1475.       }
  1476.       else if (fixedX)
  1477.       {
  1478.          fixedX--;
  1479.       }
  1480.       break;
  1481.    }
  1482. }
  1483.  
  1484. void processmsg ()
  1485. {
  1486.  struct IntuiMessage *intuimsg = NULL, m;
  1487.  CxMsg *msg;
  1488.  BOOL cont = TRUE, app_clicked = FALSE;
  1489.  LONG sigmask, msgid, msgtype;;
  1490.  ULONG lock;
  1491.  
  1492.    waitmask |= (1 << timesig) | (1 << showhidesig) | cxsigflag | SIGBREAKF_CTRL_C;
  1493.    while (cont)
  1494.    {
  1495.       sigmask = Wait (waitmask);
  1496.       if (sigmask & cxsigflag)
  1497.       {
  1498.          while ((msg = (CxMsg *) GetMsg (broker_mp)) != 0)
  1499.          {
  1500.             msgid = CxMsgID (msg);
  1501.             msgtype = CxMsgType (msg);
  1502.             ReplyMsg ((struct Message *) msg);
  1503.             switch (msgtype)
  1504.             {
  1505.              case CXM_COMMAND:
  1506.                switch (msgid)
  1507.                {
  1508.                 case CXCMD_APPEAR:
  1509.                   showwindow ();
  1510.                   break;
  1511.                 case CXCMD_DISAPPEAR:
  1512.                   hidewindow ();
  1513.                   break;
  1514.                 case CXCMD_DISABLE:
  1515.                   ActivateCxObj (broker, 0);
  1516.                   enable = FALSE;
  1517.                   setmenu ();
  1518.                   break;
  1519.                 case CXCMD_ENABLE:
  1520.                   ActivateCxObj (broker, 1);
  1521.                   enable = TRUE;
  1522.                   setmenu ();
  1523.                   break;
  1524.                 case CXCMD_UNIQUE:
  1525.                   showwindow ();
  1526.                   break;
  1527.                 case CXCMD_KILL:
  1528.                   cont = FALSE;
  1529.                   break;
  1530.                }
  1531.             }
  1532.          }  // while ((msg
  1533.       }
  1534.       if (userport)
  1535.       {
  1536.          if (sigmask & (1 << userport->mp_SigBit))
  1537.          {
  1538.             jump = FALSE;
  1539.             while ((intuimsg = (struct IntuiMessage *) GetMsg (userport)) != 0)
  1540.             {
  1541.                CopyMem ((char *) intuimsg, (char *) &m, (long) sizeof (struct IntuiMessage));
  1542.                ReplyMsg ((struct Message *) intuimsg);
  1543.                switch (m.Class)
  1544.                {
  1545.                 case IDCMP_CLOSEWINDOW:
  1546.                   if (hideonclose)
  1547.                   {
  1548.                      hidewindow ();
  1549.                   }
  1550.                   else
  1551.                   {
  1552.                      cont = FALSE;
  1553.                   }
  1554.                   break;
  1555.                 case IDCMP_NEWSIZE:
  1556.                   allocbm ();
  1557.                   break;
  1558.                 case IDCMP_IDCMPUPDATE:
  1559.                   ULONG h;
  1560.                   GetAttr (PGA_Top, propgadget, &h);
  1561.                   if (++h != scalefac)
  1562.                   {
  1563.                      scalefac = h;
  1564.                      allocbm ();
  1565.                      setwintitle ();
  1566.                      setmenu ();
  1567.                   }
  1568.                   break;
  1569.                 case IDCMP_MENUPICK:
  1570.                   cont = menupick (m.Code);
  1571.                   break;
  1572.                 case IDCMP_ACTIVEWINDOW:
  1573.                   SetAPen (winrp, pens[0]);
  1574.                   SetBPen (winrp, pens[1]);
  1575.                   printcoords (oldx, oldy);
  1576.                   printrgb (oldx, oldy);
  1577.                   ClearMenuStrip (mywin);
  1578.                   freescreenmenu (ItemAddress (menu, FULLMENUNUM (0, 1, 0)));
  1579.                   makescreenmenu ();
  1580.                   SetMenuStrip (mywin, menu);
  1581.                   break;
  1582.                 case IDCMP_INACTIVEWINDOW:
  1583.                   SetAPen (winrp, pens[2]);
  1584.                   SetBPen (winrp, pens[3]);
  1585.                   printcoords (oldx, oldy);
  1586.                   printrgb (oldx, oldy);
  1587.                   break;
  1588.                 case IDCMP_MOUSEMOVE:
  1589.                   if (fixed)
  1590.                   {
  1591.                      if (m.Qualifier & IEQUALIFIER_LEFTBUTTON)
  1592.                      {
  1593.                         fixedX = scr->MouseX;
  1594.                         fixedY = scr->MouseY;
  1595.                      }
  1596.                   }
  1597.                   break;
  1598.                 case IDCMP_VANILLAKEY:
  1599.                   cont = vanillakey (m.Code);
  1600.                   break;
  1601.                 case IDCMP_RAWKEY:
  1602.                   rawkey (m.Code, m.Qualifier);
  1603.                   break;
  1604.                 case IDCMP_REFRESHWINDOW:
  1605.                   refresh ();
  1606.                   break;
  1607.                }
  1608.                if (jump)
  1609.                {
  1610.                   break;
  1611.                }
  1612.             }  // while (intuimsg
  1613.          }
  1614.       }  // if (userport)
  1615.       // appicon
  1616.       if (app_mp)
  1617.       {
  1618.          if (sigmask & (1 << app_mp->mp_SigBit))
  1619.          {
  1620.             app_clicked = FALSE;
  1621.             while ((appmsg = (struct AppMessage *) GetMsg (app_mp)) != 0)
  1622.             {
  1623.                ReplyMsg ((struct Message *) appmsg);
  1624.                app_clicked = TRUE;
  1625.             }
  1626.             if (app_clicked)
  1627.             {
  1628.                showwindow ();
  1629.             }
  1630.          }
  1631.       }
  1632.       if ((sigmask & (1 << showhidesig)) && cont)
  1633.       {
  1634.          if (mywin)
  1635.          {
  1636.             hidewindow ();
  1637.          }
  1638.          else
  1639.          {
  1640.             showwindow ();
  1641.          }
  1642.       }
  1643.       if ((sigmask & (1 << timesig)) && cont)
  1644.       {
  1645.          if (mywin)
  1646.          {
  1647.             // refresh only if we living on the active screen
  1648.             lock = LockIBase (0);
  1649.             tmpscr = IntuitionBase->ActiveScreen;
  1650.             UnlockIBase (lock);
  1651.             if (scr == tmpscr)
  1652.             {
  1653.                refresh ();
  1654.             }
  1655.             else if (jumptoactivescreen)
  1656.             {
  1657.                setupscreen (tmpscr);
  1658.                reopenwin ();
  1659.             }
  1660.          }
  1661.       }
  1662.       if (sigmask & SIGBREAKF_CTRL_C)
  1663.       {
  1664.          cont = FALSE;
  1665.       }
  1666.    }  // while (cont)
  1667. }
  1668.  
  1669. //- iff save -----------------------------------
  1670.  
  1671. BOOL openfilereq ()
  1672. {
  1673.  APTR request;
  1674.  
  1675.    request = AllocAslRequestTags (ASL_FileRequest,
  1676.     ASLFR_InitialHeight, scr->Height / 2,
  1677.     ASLFR_Screen, scr,
  1678.     ASLFR_SleepWindow, TRUE,
  1679.     ASLFR_Window, mywin,
  1680.     ASLFR_TitleText, GetString (TXT_SAVEIFF),
  1681.     ASLFR_InitialDrawer, iffpath,
  1682.     ASLFR_InitialFile, iffname,
  1683.     ASLFR_DoSaveMode, TRUE,
  1684.     ASLFR_RejectIcons, TRUE,
  1685.     ASLFR_Screen, OpenWorkBench (),
  1686.     TAG_DONE);
  1687.    if (request)
  1688.    {
  1689.       if (AslRequest (request, NULL))
  1690.       {
  1691.          strncpy (iffpath, ((struct FileRequester *) request)->fr_Drawer, 255);
  1692.          strncpy (iffname, ((struct FileRequester *) request)->fr_File, 108);
  1693.          FreeAslRequest (request);
  1694.          return TRUE;
  1695.       }
  1696.       FreeAslRequest (request);
  1697.    }
  1698.    return FALSE;
  1699. }
  1700.  
  1701. void write (register __d4 APTR buffer, register __d5 LONG size)
  1702. {
  1703.    if (Write (fh, buffer, size) != size)
  1704.    {
  1705.       throw (1);
  1706.    }
  1707. }
  1708.  
  1709. ULONG compressline (register __a3 UBYTE *src, register __a4 UBYTE *dest, ULONG size)
  1710. {
  1711.  register UBYTE x, y, *tmp, *deststart;
  1712.    
  1713.    deststart = dest;
  1714.    while (size > 1)
  1715.    {
  1716.       x = 0;
  1717.       y = *src++;
  1718.       if (y == *src)
  1719.       {
  1720.          size--;
  1721.          while (size && (x < 127) && (*src == y))
  1722.          {
  1723.             size--;
  1724.             x++;
  1725.             src++;
  1726.          }
  1727.          *dest++ = -x;
  1728.          *dest++ = y;
  1729.       }
  1730.       else
  1731.       {
  1732.          tmp = dest++;
  1733.          while (size && (x < 128) && (*src != y))
  1734.          {
  1735.             size--;
  1736.             x++;
  1737.             *dest++ = y;
  1738.             y = *src++;
  1739.          }
  1740.          *tmp = x - 1;
  1741.          src--;
  1742.       }
  1743.    }
  1744.    if (size)
  1745.    {
  1746.       *dest++ = 0;
  1747.       *dest++ = *src;
  1748.    }
  1749.    return dest - deststart;
  1750. }
  1751.  
  1752. void savetruecolor ()
  1753. {
  1754.  UWORD bpr = ((innerwidth >> 3) + 2) & 0xfffe, byteoff, i, j;
  1755.  UBYTE *mem, *mem2, *offset, r, g, b;
  1756.  ULONG packlen;
  1757.  register UWORD x, y;
  1758.  struct BitMap *bm = NULL;
  1759.  BOOL ownbitmap = FALSE;
  1760.  
  1761.    if (GetBitMapAttr (destbm, BMA_FLAGS) & PIXFMT_RGB24)
  1762.    {
  1763.       bm = destbm;
  1764.    }
  1765.    else
  1766.    {
  1767.       bm = AllocBitMap (innerwidth, innerheight, 24, BMF_CLEAR | BMF_MINPLANES | PIXFMT_RGB24, 0);
  1768.       if (!bm)
  1769.       {
  1770.          error (GetString (TXT_ERROR_ALLOCBITMAPSAVE));
  1771.          throw (1);
  1772.       }
  1773.       ownbitmap = TRUE;
  1774.       BltBitMap (destbm, 0, 0, bm, 0, 0, innerwidth, innerheight, ABNC | ABC, ~0, NULL);
  1775.    }
  1776.    mem = (UBYTE *) AllocVec (bpr * 24, 0);
  1777.    if (!mem)
  1778.    {
  1779.       throw (2);
  1780.    }
  1781.    mem2 = (UBYTE *) AllocVec (bpr << 1, 0);
  1782.    if (!mem2)
  1783.    {
  1784.       throw (3);
  1785.    }
  1786.    for (i = 0; i < destbm->Rows; i++)
  1787.    {
  1788.       memset (mem, 0, bpr * 24);
  1789.       offset = bm->Planes[0] + i * bpr * 24;
  1790.       for (j = 0, y = 7; j < (bpr * 24); j++, y--)
  1791.       {
  1792.          r = *(offset + j++);
  1793.          g = *(offset + j++);
  1794.          b = *(offset + j);
  1795.          if (y > 7) y = 7;
  1796.          byteoff = j / 24;
  1797.          for (x = 0; x < 8; x++)
  1798.          {
  1799.             mem[x*bpr+byteoff] |= ((r >> x) & 1u) << y;
  1800.             mem[(x+8)*bpr+byteoff] |= ((g >> x) & 1u) << y;
  1801.             mem[(x+16)*bpr+byteoff] |= ((b >> x) & 1u) << y;
  1802.          }
  1803.       }
  1804.       for (j = 0; j < (bpr * 24); j += bpr)
  1805.       {
  1806.          packlen = compressline (&mem[j], mem2, bpr);
  1807.          write (mem2, packlen);
  1808.       }
  1809.       RectFill (winrp, leftoff, i + topoff, innerwidth + leftoff - 1, i + topoff);
  1810.    }
  1811.    FreeVec (mem);
  1812.    FreeVec (mem2);
  1813.    if (ownbitmap && bm)
  1814.    {
  1815.       FreeBitMap (bm);
  1816.    }
  1817. }
  1818.  
  1819. void saveiff ()
  1820. {
  1821.  ULONG len, bodylen, packlen, vpmodeid, colors[3];;
  1822.  UWORD i, j, depth;
  1823.  UBYTE cmap[3], *mem;
  1824.  struct BitMapHeader bh;
  1825.  struct DisplayInfo di;
  1826.  char header[] = "FORM....ILBMANNO";
  1827.  char anno[] = "Written by " VERSION "\0";
  1828.  
  1829.    try
  1830.    {
  1831.       // save header
  1832.       depth = GetBitMapAttr (destbm, BMA_DEPTH);
  1833.       write (header, strlen (header));
  1834.       len = (strlen (anno) + 2) & 0xfe;
  1835.       write (&len, 4);
  1836.       write (anno, len);
  1837.       write ("BMHD", 4);
  1838.       len = sizeof (struct BitMapHeader);
  1839.       write (&len, 4);
  1840.       bh.bmh_Width = innerwidth;
  1841.       bh.bmh_Height = innerheight;
  1842.       bh.bmh_Left = bh.bmh_Top = 0;
  1843.       bh.bmh_Depth = cybergfxscreen ? 24 : depth;
  1844.       bh.bmh_Masking = 0;
  1845.       bh.bmh_Compression = 1;
  1846.       bh.bmh_Pad = 0;
  1847.       bh.bmh_Transparent = 0;
  1848.       vpmodeid = GetVPModeID (&scr->ViewPort);
  1849.       if (GetDisplayInfoData (NULL, (UBYTE *) &di, sizeof (struct DisplayInfo), DTAG_DISP, vpmodeid))
  1850.       {
  1851.          bh.bmh_XAspect = di.Resolution.x;
  1852.          bh.bmh_YAspect = di.Resolution.y;
  1853.       }
  1854.       else
  1855.       {
  1856.          bh.bmh_XAspect = bh.bmh_YAspect = 0;
  1857.       }
  1858.       bh.bmh_PageWidth = innerwidth;
  1859.       bh.bmh_PageHeight = innerheight;
  1860.       write (&bh, len);
  1861.       write ("CAMG", 4);
  1862.       len = 4;
  1863.       write (&len, 4);
  1864.       write (&vpmodeid, 4);
  1865.       // no "CMAP" in true color
  1866.       if (!cybergfxscreen)
  1867.       {
  1868.          write ("CMAP", 4);
  1869.          len = 3 * (1 << depth);
  1870.          write (&len, 4);
  1871.          for (i = 0; i < (1 << depth); i++)
  1872.          {
  1873.             GetRGB32 (scr->ViewPort.ColorMap, i, 1, colors);
  1874.             cmap[0] = colors[0] & 0xff;
  1875.             cmap[1] = colors[1] & 0xff;
  1876.             cmap[2] = colors[2] & 0xff;
  1877.             write (cmap, 3);
  1878.          }
  1879.       }
  1880.       write ("BODY....", 8);
  1881.       bodylen = Seek (fh, 0, OFFSET_CURRENT) - 4;
  1882.       
  1883.       if (cybergfxscreen)
  1884.       {
  1885.          savetruecolor ();
  1886.       }
  1887.       else
  1888.       {
  1889.          mem = (UBYTE *) AllocVec (destbm->BytesPerRow << 1, 0);
  1890.          if (mem)
  1891.          {
  1892.             if (GetBitMapAttr (destbm, BMA_FLAGS) & BMF_INTERLEAVED)
  1893.             {
  1894.                // interleaved
  1895.                for (i = 0, len = 0; i < (destbm->Rows * depth); i++, len += destbm->BytesPerRow / depth)
  1896.                {
  1897.                   packlen = compressline (destbm->Planes[0] + len, mem, destbm->BytesPerRow / depth);
  1898.                   write (mem, packlen);
  1899.                   if (!(i % depth))
  1900.                   {
  1901.                      RectFill (winrp, leftoff, i / depth + topoff, innerwidth + leftoff - 1, i / depth + topoff);
  1902.                   }
  1903.                }
  1904.             }
  1905.             else
  1906.             {
  1907.                len = 0;
  1908.                for (i = 0; i < destbm->Rows; i++)
  1909.                {
  1910.                   for (j = 0; j < depth; j++)
  1911.                   {
  1912.                      packlen = compressline (destbm->Planes[j] + len, mem, destbm->BytesPerRow);
  1913.                      write (mem, packlen);
  1914.                   }
  1915.                   len += destbm->BytesPerRow;
  1916.                   RectFill (winrp, leftoff, i + topoff, innerwidth + leftoff - 1, i + topoff);
  1917.                }
  1918.             }
  1919.             FreeVec (mem);
  1920.          }
  1921.          else
  1922.          {
  1923.             throw (3);
  1924.          }
  1925.       }  // if (cybergfxscreen)
  1926.       if (Seek (fh, 0, OFFSET_CURRENT) & 1)
  1927.       {
  1928.          *cmap = 0x80;
  1929.          write (cmap, 1);
  1930.       }
  1931.       len = Seek (fh, 4, OFFSET_BEGINNING) - 8;
  1932.       write (&len, 4);
  1933.       Seek (fh, bodylen, OFFSET_BEGINNING);
  1934.       len = len - bodylen + 4;
  1935.       write (&len, 4);
  1936.    }
  1937.    catch (int) { }
  1938. }
  1939.  
  1940. //- menu ---------------------------------------
  1941.  
  1942. BOOL fixedFunc ()
  1943. {
  1944.    if (!fixed && (item->Flags & CHECKED))
  1945.    {
  1946.       fixed = TRUE;
  1947.       fixedX = scr->MouseX;
  1948.       fixedY = scr->MouseY;
  1949.    }
  1950.    else if (fixed && !(item->Flags & CHECKED))
  1951.    {
  1952.       fixed = FALSE;
  1953.    }
  1954.    return TRUE;
  1955. }
  1956.  
  1957. BOOL fastFunc ()
  1958. {
  1959.    fast = (item->Flags & CHECKED) != 0;
  1960.    return TRUE;
  1961. }
  1962.  
  1963. BOOL crosshairFunc ()
  1964. {
  1965.    crosshair = (item->Flags & CHECKED) != 0;
  1966.    return TRUE;
  1967. }
  1968.  
  1969. BOOL AboutFunc ()
  1970. {
  1971.  static struct EasyStruct es_about = {
  1972.    20, 0,
  1973.    "Lupe",
  1974.    "%s%s%s%s",
  1975.    "%s"
  1976.  };
  1977.  
  1978.  char *era_about[] = {
  1979.    VERSION " (" __DATE__ ")\n\n",
  1980.    GetString (TXT_ABOUT_WRITTENBY),
  1981.    "\n"
  1982.    "  Frank Toepper\n"
  1983.    "  Maxim Gorki Straße 5A\n"
  1984.    "  Greifswald\n"
  1985.    "  17491\n"
  1986.    "  GERMANY\n\n"
  1987.    "E-Mail:\n"
  1988.    "  toepper@rz.uni-greifswald.de\n"
  1989.    "WWW:\n"
  1990.    "  http://www.user.fh-stralsund.de/~rwermke/di.html\n\n",
  1991.    GetString (TXT_ABOUT_PD),
  1992.    "Ok"
  1993.  };
  1994.  
  1995.    EasyRequestArgs (NULL, &es_about, NULL, era_about);
  1996.    return TRUE;
  1997. }
  1998.  
  1999. BOOL jumpFunc ()
  2000. {
  2001.    if (setupscreen (NULL) == NEWSCREEN)
  2002.    {
  2003.       reopenwin ();
  2004.    }
  2005.    return TRUE;
  2006. }
  2007.  
  2008. BOOL jumptoactiveFunc ()
  2009. {
  2010.    jumptoactivescreen = (item->Flags & CHECKED) != 0;
  2011.    return TRUE;
  2012. }
  2013.  
  2014. BOOL saveFunc ()
  2015. {
  2016.  BPTR dirlock, olddirlock;
  2017.  ULONG reg;
  2018.  
  2019.    if (scalefac == 1)
  2020.    {
  2021.     LONG x = oldx, y = oldy;
  2022.       if (!(destbm = AllocBitMap (innerwidth, innerheight, cybergfxscreen ? 24 : scrdepth, cybergfxscreen ? (BMF_CLEAR | BMF_MINPLANES | PIXFMT_RGB24) : BMF_CLEAR, 0)))
  2023.       {
  2024.          error (GetString (TXT_ERROR_ALLOCBITMAPSAVE));
  2025.          return TRUE;
  2026.       }
  2027.       adjustX (x);
  2028.       adjustY (y);
  2029.       BltBitMap (scrbm, x, y, destbm, 0, 0, innerwidth, innerheight, ABNC | ABC, ~0, NULL);
  2030.    }
  2031.    if (openfilereq ())
  2032.    {
  2033.       BltBitMapRastPort (destbm, 0, 0, winrp, leftoff, topoff, innerwidth, innerheight, ABNC | ABC);
  2034.       dirlock = Lock (iffpath, SHARED_LOCK);
  2035.       if (dirlock)
  2036.       {
  2037.          olddirlock = CurrentDir (dirlock);
  2038.          fh = Open (iffname, MODE_NEWFILE);
  2039.          if (fh)
  2040.          {
  2041.             mywin->Flags &= ~SIZEGADGET;
  2042.             reg = GetAPen (winrp);
  2043.             SetAPen (winrp, 0);
  2044.             saveiff ();
  2045.             Close (fh);
  2046.             BltBitMapRastPort (destbm, 0, 0, winrp, leftoff, topoff, innerwidth, innerheight, ABNC | ABC);
  2047.             SetAPen (winrp, reg);
  2048.             mywin->Flags |= SIZEGADGET;
  2049.          }
  2050.          else
  2051.          {
  2052.             error (GetString (TXT_ERROR_CREATE), iffname);
  2053.          }
  2054.          CurrentDir (olddirlock);
  2055.          UnLock (dirlock);
  2056.       }
  2057.       else
  2058.       {
  2059.          error (GetString (TXT_ERROR_LOCK), iffpath);
  2060.       }
  2061.    }
  2062.    if ((scalefac == 1) && destbm)
  2063.    {
  2064.       FreeBitMap (destbm);
  2065.       destbm = NULL;
  2066.    }
  2067.    return TRUE;
  2068. }
  2069.  
  2070. BOOL coordsFunc ()
  2071. {
  2072.    if (!coords && (item->Flags & CHECKED))
  2073.    {
  2074.       coords = TRUE;
  2075.    }
  2076.    else if (coords && !(item->Flags & CHECKED))
  2077.    {
  2078.       coords = FALSE;
  2079.    }
  2080.    else
  2081.    {
  2082.       return TRUE;  // nothing changed
  2083.    }
  2084.    reopenwin ();
  2085.    return TRUE;
  2086. }
  2087.  
  2088. BOOL gridFunc ()
  2089. {
  2090.    grid = (item->Flags & CHECKED) != 0;
  2091.    setupgrid ();
  2092.    return TRUE;
  2093. }
  2094.  
  2095. BOOL showrgbFunc ()
  2096. {
  2097.    if (!showrgb && (item->Flags & CHECKED))
  2098.    {
  2099.       showrgb = TRUE;
  2100.    }
  2101.    else if (showrgb && !(item->Flags & CHECKED))
  2102.    {
  2103.       showrgb = FALSE;
  2104.    }
  2105.    else
  2106.    {
  2107.       return TRUE;  // nothing changed
  2108.    }
  2109.    reopenwin ();
  2110.    return TRUE;
  2111. }
  2112.  
  2113. BOOL enableFunc ()
  2114. {
  2115.    if (item->Flags & CHECKED)
  2116.    {
  2117.       ActivateCxObj (broker, 1);
  2118.       enable = TRUE;
  2119.    }
  2120.    else if (!(item->Flags & CHECKED))
  2121.    {
  2122.       ActivateCxObj (broker, 0);
  2123.       enable = FALSE;
  2124.    }
  2125.    return TRUE;
  2126. }
  2127.  
  2128. BOOL hideoncloseFunc ()
  2129. {
  2130.    hideonclose = (item->Flags & CHECKED) != 0;
  2131.    return TRUE;
  2132. }
  2133.  
  2134. BOOL hideFunc ()
  2135. {
  2136.    hidewindow ();
  2137.    jump = TRUE;
  2138.    return TRUE;
  2139. }
  2140.  
  2141. BOOL QuitFunc ()
  2142. {
  2143.    return FALSE;
  2144. }
  2145.  
  2146. //- args ---------------------------------------
  2147.  
  2148. BOOL argbool (UBYTE **argv, UBYTE *name, BOOL def)
  2149. {
  2150.  STRPTR value;
  2151.  
  2152.    value = FindToolType (argv, name);
  2153.    if (value)
  2154.    {
  2155.       if (MatchToolValue (value, "YES") || MatchToolValue (value, "ON")) return TRUE;
  2156.       if (MatchToolValue (value, "OFF") || MatchToolValue (value, "NO")) return FALSE;
  2157.    }
  2158.    return def;
  2159. }
  2160.  
  2161. LONG argint (UBYTE **argv, UBYTE *name, LONG def)
  2162. {
  2163.  LONG returnvalue;
  2164.  STRPTR value;
  2165.  
  2166.    value = FindToolType (argv, name);
  2167.    if (value)
  2168.    {
  2169.       if (StrToLong (value, &returnvalue))
  2170.       {
  2171.          return returnvalue;
  2172.       }
  2173.    }
  2174.    return def;
  2175. }
  2176.  
  2177. void argstring (UBYTE *result, UBYTE **argv, UBYTE *name, size_t size = 49)
  2178. {
  2179.  STRPTR value;
  2180.  
  2181.    value = FindToolType ((UBYTE **) argv, name);
  2182.    if (value)
  2183.    {
  2184.       strncpy (result, value, size);
  2185.    }
  2186. }
  2187.  
  2188. void readargs ()
  2189. {
  2190.  // first time always the tooltypes will be evaluated
  2191.  // if we started from Cli the tooltypes can be overloaded
  2192.  UBYTE **argv;
  2193.  STRPTR filename;
  2194.  struct DiskObject *programicon;
  2195.  struct RDArgs * rdargs;
  2196.  struct DrawInfo *drawinfo;
  2197.  LONG a[21];
  2198.  long *args = a;
  2199.  
  2200.    wintop = scr->RastPort.TxHeight + (UWORD) scr->WBorTop + 1;
  2201.    // make the window as square as possible
  2202.    drawinfo = GetScreenDrawInfo (scr);
  2203.    if (drawinfo)
  2204.    {
  2205.       innerheight = innerwidth * drawinfo->dri_Resolution.X / drawinfo->dri_Resolution.Y;
  2206.       FreeScreenDrawInfo (scr, drawinfo);
  2207.    }
  2208.    if (Cli ())
  2209.    {
  2210.       GetProgramName (programname, 108);
  2211.    }
  2212.    else
  2213.    {
  2214.       strncpy (programname, thistask->tc_Node.ln_Name, 109);
  2215.    }
  2216.    IconBase = OpenLibrary ("icon.library", 37);
  2217.    if (IconBase)
  2218.    {
  2219.       programicon = GetDiskObject (programname);
  2220.       if (programicon)
  2221.       {
  2222.          argv = (UBYTE **) programicon->do_ToolTypes;
  2223.          newbroker.nb_Pri = argint (argv, "CX_Priority", newbroker.nb_Pri);
  2224.          fast = argbool (argv, "Fast", fast);
  2225.          maxscalefac = argint (argv, "MaxScaleFactor", maxscalefac);
  2226.          scalefac = argint (argv, "ScaleFactor", scalefac);
  2227.          winleft = argint (argv, "WinLeft", winleft);
  2228.          wintop = argint (argv, "WinTop", wintop);
  2229.          innerheight = argint (argv, "WinHeight", innerheight);
  2230.          innerwidth = argint (argv, "WinWidth", innerwidth);
  2231.          coords = argbool (argv, "Coordinates", coords);
  2232.          crosshair = argbool (argv, "Crosshair", crosshair);
  2233.          argstring (setoriginkey, argv, "SetOriginKey");
  2234.          argstring (resetoriginkey, argv, "ResetOriginKey");
  2235.          fixed = argbool (argv, "Fixed", fixed);
  2236.          argstring (showhidekey, argv, "ShowHideKey");
  2237.          hide = argbool (argv, "Iconify", hide);
  2238.          hideonclose = argbool (argv, "IconifyOnClose", hideonclose);
  2239.          grid = argbool (argv, "Grid", grid);
  2240.          showrgb = argbool (argv, "ShowRGB", showrgb);
  2241.          argstring (iffpath, argv, "IFFFile", 255);
  2242.          jumptoactivescreen = argbool (argv, "JumpToActiveScreen", jumptoactivescreen);
  2243.          argstring (language, argv, "LANGUAGE", 20);
  2244.          FreeDiskObject (programicon);
  2245.       }
  2246.       CloseLibrary (IconBase);
  2247.    }
  2248.    if (Cli ())
  2249.    {
  2250.       memset (args, '\0', 21 * sizeof (LONG));
  2251.       args[1] = fast;
  2252.       args[8] = coords;
  2253.       args[9] = crosshair;
  2254.       args[12] = fixed;
  2255.       args[14] = hide;
  2256.       args[15] = hideonclose;
  2257.       args[16] = grid;
  2258.       args[17] = showrgb;
  2259.       args[19] = jumptoactivescreen;
  2260.       rdargs = ReadArgs (Template, args, NULL);
  2261.       if (rdargs)
  2262.       {
  2263.          if (*args) newbroker.nb_Pri = *args;
  2264.          args++;
  2265.          fast = *args++;
  2266.          if (*args) maxscalefac = *(LONG *) *args;
  2267.          if (*++args) scalefac = *(LONG *) *args;
  2268.          if (*++args) winleft = *(LONG *) *args;
  2269.          if (*++args) wintop = *(LONG *) *args;
  2270.          if (*++args) innerwidth = *(LONG *) *args;
  2271.          if (*++args) innerheight = *(LONG *) *args;
  2272.          args++;
  2273.          coords = *args++;
  2274.          crosshair = *args++;
  2275.          if (*args) strncpy (setoriginkey, (char *) *args, 49);
  2276.          if (*++args) strncpy (resetoriginkey, (char *) *args, 49);
  2277.          args++;
  2278.          fixed = *args++;
  2279.          if (*args) strncpy (showhidekey, (char *) *args, 49);
  2280.          args++;
  2281.          hide = *args++;
  2282.          hideonclose = *args++;
  2283.          grid = *args++;
  2284.          showrgb = *args++;
  2285.          if (*args) strncpy (iffpath, (char *) *args, 255);
  2286.          args++;
  2287.          jumptoactivescreen = *args++ != 0;
  2288.          if (*args) strncpy (language, (char *) *args, 19);
  2289.          FreeArgs (rdargs);
  2290.       }
  2291.    }
  2292.    if (maxscalefac < 5) maxscalefac = 5;
  2293.    // not lower than innerheight or innerwidth
  2294.    // otherwise 'innerheight / scalefac' or 'innerwidth / scalefac'
  2295.    // can go to 0 -> 'AllocBitMap ()' failed
  2296.    if (maxscalefac > MINHEIGHT) maxscalefac = MINHEIGHT;
  2297.    if (scalefac > maxscalefac) scalefac = maxscalefac;
  2298.    if (innerheight < MINHEIGHT) innerheight = MINHEIGHT;
  2299.    if (innerwidth < MINWIDTH) innerwidth = MINWIDTH;
  2300.    
  2301.    filename = PathPart (iffpath);
  2302.    strncpy (iffname, filename, 108);
  2303.    filename[0] = '\0';
  2304. }
  2305.  
  2306. //- main ---------------------------------------
  2307.  
  2308. struct Library *openlib (char *libname, ULONG ver)
  2309. {
  2310.  struct Library *lib;
  2311.    
  2312.    lib = OpenLibrary (libname, ver);
  2313.    if (!lib)
  2314.    {
  2315.       error (GetString (TXT_ERROR_LIBRARY), libname, ver);
  2316.       throw (1);
  2317.    }
  2318.    return lib;
  2319. }
  2320.  
  2321. void main ()
  2322. {
  2323.    try
  2324.    {
  2325.       CxBase = openlib ("commodities.library", 37);
  2326.       GfxBase = (struct GfxBase *) openlib ("graphics.library", 39);
  2327.       GadToolsBase = openlib ("gadtools.library", 37);
  2328.       WorkbenchBase = openlib ("workbench.library", 37);
  2329.       AslBase = openlib ("asl.library", 37);
  2330.       UtilityBase = openlib ("utility.library", 37);
  2331.       LayersBase = openlib ("layers.library", 37);
  2332.       CyberGfxBase = OpenLibrary ("cybergraphics.library", 40);
  2333.       LocaleBase = OpenLibrary ("locale.library", 38);
  2334.       InitRastPort (&destrp);
  2335.       SetAPen (&destrp, 0);
  2336.       InitRastPort (&maskrp);
  2337.       SetDrMd (&maskrp, COMPLEMENT);
  2338.       thistask = FindTask (NULL);
  2339.       if ((topazfont = OpenFont (&topaz_attr)) != 0)
  2340.       {
  2341.          try
  2342.          {
  2343.             setupscreen (NULL);  // needed before readargs ()
  2344.             readargs ();
  2345.             OpenlupeCatalog (0, language[0] ? language : 0);
  2346.             getoffsets ();
  2347.             if (hide)
  2348.             {
  2349.                hidewindow ();
  2350.             }
  2351.             else
  2352.             {
  2353.                openwin ();
  2354.                allocbm ();
  2355.             }
  2356.             if ((timesig = AllocSignal (-1L)) != -1)
  2357.             {
  2358.                if ((showhidesig = AllocSignal (-1L)) != -1)
  2359.                {
  2360.                   try
  2361.                   {
  2362.                      initbroker ();
  2363.                      processmsg ();
  2364.                   }
  2365.                   catch (int) { };
  2366.                   if (broker)
  2367.                   {
  2368.                      DeleteCxObjAll (broker);
  2369.                      broker = NULL;
  2370.                   }
  2371.                   if (broker_mp)
  2372.                   {
  2373.                      DeleteMsgPort (broker_mp);
  2374.                      broker_mp = NULL;
  2375.                   }
  2376.                   FreeSignal (showhidesig);
  2377.                }
  2378.                else
  2379.                {
  2380.                   error (GetString (TXT_ERROR_SIGNAL));
  2381.                }
  2382.                FreeSignal (timesig);
  2383.             }
  2384.             else
  2385.             {
  2386.                error (GetString (TXT_ERROR_SIGNAL));
  2387.             }
  2388.          }  // try
  2389.          catch (int) { }
  2390.          closewin ();
  2391.          CloseDownScreen ();
  2392.          freeappicon ();
  2393.          CloseFont (topazfont);
  2394.          if (screenfont)
  2395.          {
  2396.             CloseFont (screenfont);
  2397.          }
  2398.       }
  2399.       else
  2400.       {
  2401.          error (GetString (TXT_ERROR_FONT));
  2402.       }
  2403.       CloselupeCatalog ();
  2404.       if (LocaleBase)
  2405.       {
  2406.          CloseLibrary (LocaleBase);
  2407.       }
  2408.       if (CyberGfxBase)
  2409.       {
  2410.          CloseLibrary (CyberGfxBase);
  2411.       }
  2412.       CloseLibrary (UtilityBase);
  2413.       CloseLibrary (AslBase);
  2414.       CloseLibrary (WorkbenchBase);
  2415.       CloseLibrary (GadToolsBase);
  2416.       CloseLibrary ((struct Library *) GfxBase);
  2417.       CloseLibrary (CxBase);
  2418.       CloseLibrary (LayersBase);
  2419.    }
  2420.    catch (int) { }
  2421. }
  2422.  
  2423.