home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff274.lzh / HP11 / amiga / amiga.c next >
C/C++ Source or Header  |  1989-11-16  |  23KB  |  807 lines

  1. #include "exec/types.h"
  2. #include "exec/ports.h"
  3. #include "exec/io.h"
  4. #include "exec/memory.h"
  5. #include "graphics/gfx.h"
  6. #include "devices/timer.h"
  7. #include "libraries/dos.h"
  8. #include "workbench/startup.h"
  9.  
  10. #include "proto/exec.h"
  11. #include "proto/graphics.h"
  12. #include "proto/layers.h"
  13. #include "proto/intuition.h"
  14. #include "proto/timer.h"
  15. #include "proto/dos.h"
  16.  
  17. #include "string.h"
  18. #include "ctype.h"
  19. #include "dos.h"
  20.  
  21. #include "hp11/hp11.h"
  22. #include "hp11/amiga/internal.h"
  23. #include "hp11/amiga/amiga.h"
  24. #include "hp11/amiga/menus.h"
  25.  
  26. #define MAXWIDTH 29 /* X distance between 2 keys */
  27. #define MAXHEIGHT 29 /* Y distance bewteen 2 keys */
  28. #define KEYWIDTH 20 /* Width of actual key */
  29. #define KEYHEIGHT 16 /* Height of actual key */
  30. #define TOPKEYHEIGHT 9 /* Height of top of key */
  31. #define KEYX (19 + HP11X) /* Position of first key */
  32. #define KEYY (61 + HP11Y)
  33. #define CHAROFFX -1 /* offset in display for first char */
  34. #define CHAROFFY 3
  35. #define CHARWIDTH 14 /* Size of char */
  36. #define CHARHEIGHT 13
  37. #define SCRX0 (53 + HP11X) /* Limits of display for chars */
  38. #define SCRX1 (208 + HP11X)
  39. #define SCRY0 (11 + HP11Y)
  40. #define SCRY1 (37 + HP11Y)
  41. #define fX (SCRX0 + 3 * CHARWIDTH + 2) /* Position of indicators */
  42. #define gX (SCRX0 + 4 * CHARWIDTH - 1)
  43. #define GX (SCRX0 + (int)(6.5 * CHARWIDTH))
  44. #define RADX (GX + 5)
  45. #define PRGMX (SCRX0 + 10 * CHARWIDTH - 6)
  46. #define USERX (SCRX0 + CHARWIDTH)
  47. #define INDICY (SCRY0 + 19)
  48.  
  49. #define CR 13
  50. #define BS 8
  51. #define ESC 27
  52.  
  53. #define COPY 0xc0 /* minterm for straight copy */
  54.  
  55. struct Library *TimerBase; /* Base for calling timer routines */
  56.  
  57. extern struct Border *hp11char[]; /* Character descriptions (as connected lines) */
  58. /* Indicator shapes (as bitmaps) */
  59. extern struct Image fImage, gImage, USERImage, GImage, RADImage, PRGMImage;
  60. extern struct Image off_image; /* Image for sleep */
  61.  
  62. extern struct IntuitionBase *IntuitionBase;
  63. extern struct GfxBase *GfxBase;
  64. struct LayersBase *LayersBase;
  65.  
  66. struct Window *hp11; /* The window containing the hp11 */
  67.  
  68. /* These informations are for RelKey() */
  69. /* The method by which the latest key was obtained :
  70.   From the menus, from the CLOSE gadget, from the keyboard, or by selecting with the mouse */
  71. static enum {menu, gadget, keyboard, mouse} keytype;
  72. /* The keycode of the last key read */
  73. static short lastkey;
  74. /* The Time at which the last key was read */
  75. static ULONG secs, micros;
  76. /* Path to executable */
  77. char *hp11name;
  78. char hp11path[PATHLEN];
  79.  
  80. static struct timerequest *timer; /* The timer which is used */
  81. static struct NewWindow hp11new = { /* Desired window */
  82.    0,0, /* Position of top left corner */
  83.    HP11WIDTH + 6, HP11HEIGHT + 14, /* Width, Height */
  84.    -1,-1, /* Use default pens to draw window */
  85.    CLOSEWINDOW | MOUSEBUTTONS | VANILLAKEY | MENUPICK,
  86.    WINDOWDEPTH | WINDOWCLOSE | WINDOWDRAG | SMART_REFRESH | NOCAREREFRESH,
  87.    NULL, NULL,
  88.    "HP11C", NULL,
  89.    NULL,
  90.    0, 0, 0, 0,
  91.    WBENCHSCREEN /* It opens in the main screen */
  92. };
  93.  
  94. static struct IntuiText canceltext = {
  95.    AUTOFRONTPEN, AUTOBACKPEN,
  96.    AUTODRAWMODE,
  97.    AUTOLEFTEDGE, AUTOTOPEDGE,
  98.    AUTOITEXTFONT,
  99.    "Cancel",
  100.    AUTONEXTTEXT
  101. };
  102.  
  103. static struct IntuiText nomemtext = {
  104.    AUTOFRONTPEN, AUTOBACKPEN,
  105.    AUTODRAWMODE,
  106.    20, 10,
  107.    AUTOITEXTFONT,
  108.    "Not enough memory",
  109.    NULL
  110. };
  111.  
  112. char *mygetpath(to, l)
  113. register char *to;
  114. register BPTR l;
  115. {
  116.    register BPTR tl;
  117.    register int notfirst = FALSE;
  118.    register struct FileInfoBlock *fib = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock), 0);
  119.  
  120.    if (!fib) return(NULL);
  121.    to[0] = '\0';
  122.  
  123.    do {
  124.       if (!Examine(l, fib)) return(NULL);
  125.       if (fib->fib_DirEntryType > 0) strins(to, "/");
  126.       if (fib->fib_FileName[0] == '\0') strins(to, "RAM");
  127.       else strins(to, fib->fib_FileName);
  128.       tl = l;
  129.       l = ParentDir(l);
  130.       if (notfirst) UnLock(tl);
  131.       notfirst = TRUE;
  132.    } while (l);
  133.  
  134.    *(strchr(to, '/')) = ':';
  135.    FreeMem((char *)fib, sizeof(struct FileInfoBlock));
  136.    return(to);
  137. }
  138.  
  139. void split(char *file, char *path, char **name)
  140. {
  141.    int l = strlen(file);
  142.  
  143.    *name = file + l;
  144.    while (--l >= 0 && (*--*name != '/' && **name != ':')) ;
  145.    if (l < 0)
  146.       path[0] = '\0';
  147.    else
  148.    {
  149.       ++*name;
  150.       strncpy(path, file, l + 1);
  151.       path[l + 1] = '\0';
  152.    }
  153. }
  154.  
  155. /* Delete a timer */
  156. static void DeleteTimer(struct timerequest *tr)
  157. {
  158.    TimerBase = (struct Library *)(-1); /* Don't call any more ! */
  159.  
  160.    if (tr != NULL)
  161.    {
  162.       /* Remove the port */
  163.       if (tr->tr_node.io_Message.mn_ReplyPort) DeletePort(tr->tr_node.io_Message.mn_ReplyPort);
  164.  
  165.       CloseDevice((struct IORequest *)tr); /* Close the device */
  166.       DeleteExtIO((struct IORequest *)tr); /* Free the IO request */
  167.    }
  168. }
  169.  
  170. /* Create a timer of type unit */
  171. static struct timerequest *CreateTimer(ULONG unit)
  172. {
  173.    register long error;
  174.  
  175.    register struct MsgPort *timerport;
  176.    register struct timerequest *timermsg;
  177.  
  178.    if ((timerport = CreatePort(NULL, 0)) == NULL) /* first get a port */
  179.       return(NULL); /* failed */
  180.  
  181.    if ((timermsg = (struct timerequest *) /* Then create an IO request for the timer */
  182.            CreateExtIO(timerport, sizeof(struct timerequest))) == NULL)
  183.       return(NULL); /* failed */
  184.  
  185.    if ((error = OpenDevice(TIMERNAME, unit, (struct IORequest *)timermsg, 0)) != 0) /* Finally, open the timer device */
  186.    { /* failed */
  187.       DeleteTimer(timermsg);
  188.       return(NULL);
  189.    }
  190.  
  191.    TimerBase = (struct Library *)timermsg->tr_node.io_Device; /* Allow calls to the time arithmetic routines */
  192.    return(timermsg);
  193. }
  194.  
  195. /* Wait for a specified duration */
  196. static void WaitFor(struct timeval *tv)
  197. {
  198.    timer->tr_node.io_Command = TR_ADDREQUEST;
  199.  
  200.    timer->tr_time = *tv;
  201.  
  202.    DoIO((struct IORequest *)timer); /* Wait for completion of request */
  203. }
  204.  
  205. /* Obtain the system time, assume global timer contains a valid timer */
  206. static void GetSysTime(struct timeval *tv)
  207. {
  208.    timer->tr_node.io_Command = TR_GETSYSTIME;
  209.    DoIO((struct IORequest *)timer);
  210.  
  211.    *tv = timer->tr_time; /* Copy obtained time */
  212. }
  213.  
  214. /* Reverse the key on the keyboard (as if user was holding it down) */
  215. static void ReverseKey(int key)
  216. {
  217.    register int kx, ky, h;
  218.  
  219.    if (key == 30) h = KEYHEIGHT - 1; /* ON, higher than average */
  220.    else if (key == 25) h = MAXHEIGHT + TOPKEYHEIGHT - 1; /* ENTER, even taller */
  221.    else h = TOPKEYHEIGHT - 1;
  222.  
  223. /* -------------------- */
  224. /* Check for bug when using short int */
  225.  
  226.    kx = (key % 10) * MAXWIDTH + KEYX; /* Calc. key position */
  227.    ky = (key / 10) * MAXHEIGHT + KEYY;
  228.  
  229.    SetDrMd(hp11->RPort, COMPLEMENT); /* Draw in reverse */
  230.    RectFill(hp11->RPort, (long)kx, (long)ky, (long)(kx + (KEYWIDTH - 1)), (long)(ky + h));
  231. }
  232.  
  233. /* From positions x & y, deduce which key was pressed */
  234. static int DecodeKey(int x, int y)
  235. {
  236.    register int kx, ky, px, py;
  237.  
  238.    kx = (x - KEYX) / MAXWIDTH; px = (x - KEYX) % MAXWIDTH;
  239.    ky = (y - KEYY) / MAXHEIGHT; py = (y - KEYY) % MAXHEIGHT;
  240.  
  241.    if (/* first, check if in keyboard. x & y are tested (instead of kx, ky)
  242.       because kx & ky suffer a roundoff towards zero for negative values */
  243.        (x >= KEYX && y >= KEYY && kx <= 9 && ky <= 3)
  244.        &&
  245.       /* now the condition on width */
  246.        (px < KEYWIDTH && px >= 0) /* same for all keys */
  247.        &&
  248.      /* condition on height, 2 cases for ENTER is different */
  249.        (
  250.        (kx == 5 && (ky == 2 || (ky == 3 && py < KEYHEIGHT) && (ky = 2))) /* ENTER, set ky to correct value when ky == 3 */
  251.        || /* condition on height */
  252.        (py < KEYHEIGHT && py >= 0)
  253.        )
  254.       ) return(ky * 10 + kx);
  255.    else return(-1);
  256. }
  257.  
  258. /* Mouse was pressed at x,y. Is this a key ? */
  259. static int GetMouseKey(int x, int y)
  260. {
  261.    int key;
  262.  
  263.    if ((key = DecodeKey(x, y)) != -1) { /* yes */
  264.       ReverseKey(key);
  265.       keytype = mouse; /* info for RelKey() */
  266.    }
  267.    return(key);
  268. }
  269.  
  270. /* Key keycode was pressed by the user */
  271. static int GetKeyKey(int _keycode)
  272. {
  273.    register int key = -1, keycode = tolower(_keycode);
  274.  
  275.    switch (keycode) {
  276.       case ESC: key = 30; break;
  277.       case '7': case '8': case '9': key = keycode - ('7' - 6); break;
  278.       case '4': case '5': case '6': key = keycode - ('4' - 16); break;
  279.       case '1': case '2': case '3': key = keycode - ('1' - 26); break;
  280.       case '0': key = 36; break;
  281.       case '.': key = 37; break;
  282.       case '^': key =  3; break;
  283.       case '*': key = 19; break;
  284.       case '-': key = 29; break;
  285.       case '+': key = 39; break;
  286.       case '/': key =  9; break;
  287.       case '_': key =  5; break;
  288.       case CR : key = 25; break;
  289.       case 'f': key = 31; break;
  290.       case 'g': key = 32; break;
  291.       case BS : key = 24; break;
  292.       case 's': key = 12; break;
  293.       case 'c': key = 13; break;
  294.       case 't': key = 14; break;
  295.    }
  296.    if (key != -1) { /* A valid key was given */
  297.       ReverseKey(key);
  298.       keytype = keyboard; /* for RelKey() */
  299.    }
  300.    return(key);
  301. }
  302.  
  303. /* Get a key from the keyboard with/without waiting */
  304. int PollKey(wait)
  305. int wait;
  306. {
  307.    register int key;
  308.    register struct IntuiMessage *msg;
  309.    register ULONG class;
  310.    register UWORD code;
  311.    register WORD x, y;
  312.    register APTR address;
  313.  
  314.    key = -1; /* no key yet */
  315.    do {
  316.       if (wait) WaitPort(hp11->UserPort); /* No active waits in multi-tasking ! */
  317.       msg = (struct IntuiMessage *)GetMsg(hp11->UserPort); /* Get the message if there is one */
  318.       if (msg) { /* yes, there is */
  319.      /* Copy relevant information */
  320.      class = msg->Class;
  321.      code = msg->Code;
  322.      address = msg->IAddress;
  323.      x = msg->MouseX;
  324.      y = msg->MouseY;
  325.      secs = msg->Seconds;
  326.      micros = msg->Micros;
  327.      ReplyMsg((struct Message *)msg); /* & reply to it */
  328.  
  329.      switch (class) { /* type of message */
  330.         case CLOSEWINDOW: /* Window closed = Quit */
  331.            quit = TRUE;
  332.            key = BRESET;
  333.            keytype = gadget;
  334.            break;
  335.         case MOUSEBUTTONS: /* A mouse button was pressed */
  336.            if (code == SELECTDOWN)
  337.           key = GetMouseKey(x, y);
  338.            break;
  339.         case VANILLAKEY: /* a key was pressed */
  340.            key = GetKeyKey(code);
  341.            break;
  342.         case MENUPICK: /* A menu option was chosen */
  343.            key = MenuHandler(code); /* Call menu handler */
  344.            keytype = menu; /* for RelKey() */
  345.            break;
  346.      }
  347.       }
  348.    } while (key == -1 && (msg || wait));
  349.    /* Exit if key read or, if not waiting, no message ready */
  350.  
  351.    lastkey = key; /* save key for RelKey() */
  352.    return(key);
  353. }
  354.  
  355. /* Wait for latest key to be released, returns true if button released
  356.   over key (valid only for mouse) */
  357. BOOL RelKey()
  358. {
  359.    register WORD x, y;
  360.    register BOOL Released;
  361.    register struct IntuiMessage *msg;
  362.    struct timeval event, now, delay;
  363.    register int key = lastkey; /* key last pressed */
  364.  
  365.    lastkey = -1; /* Only release it once ! */
  366.  
  367.    if (key != -1)
  368.       switch (keytype) {
  369.  
  370.      case keyboard: /* Key reversed for a max of .08 secs
  371.         (There is no easy way to wait for its release on the keyboard) */
  372.         event.tv_secs = secs; event.tv_micro = micros;
  373.         GetSysTime(&now);
  374.         SubTime(&now, &event); /* Time elapsed since key pressed */
  375.         delay.tv_secs = 0; delay.tv_micro = 80000;
  376.         if (CmpTime(&now, &delay) == 1) { /* now < delay */
  377.            SubTime(&delay, &now);
  378.            WaitFor(&delay); /* Wait long enough */
  379.         }
  380.         ReverseKey(key); /* un-reverse key */
  381.         return(TRUE);
  382.  
  383.      case mouse:
  384.         Released = FALSE;
  385.         do { /* Wait for mouse button to be released */
  386.            WaitPort(hp11->UserPort);
  387.            msg = (struct IntuiMessage *)GetMsg(hp11->UserPort);
  388.            x = msg->MouseX;
  389.            y = msg->MouseY;
  390.            Released = (msg->Class == MOUSEBUTTONS && msg->Code == SELECTUP);
  391.            ReplyMsg((struct Message *)msg);
  392.         } while (!Released);
  393.         ReverseKey(key); /* un-reverse key */
  394.  
  395.         return((BOOL)(DecodeKey(x, y) == key)); /* Button released over key? */
  396.       }
  397.    return(TRUE); /* if already released */
  398. }
  399.  
  400. /* load picture from open file file, width pixel wide, height pixels high,
  401.   depth bitplanes deep into bitmap bm & colormap cols (if non-null) */
  402. static BOOL LoadBitMap(LONG file, struct BitMap *bm, int width, int height,
  403.                int depth)
  404. {
  405.    register int i;
  406.    register LONG nb, plsize;
  407.  
  408.    InitBitMap(bm, (long)depth, (long)width, (long)height);
  409.    plsize = bm->BytesPerRow * bm->Rows; /* size of 1 plane */
  410.    /* Allocate enough memory for all planes, initialise plane pointers */
  411.    if (!(bm->Planes[0] = (PLANEPTR)AllocMem(plsize * depth, MEMF_CHIP))) return((BOOL) FALSE);
  412.    for (i = 1; i < depth; i++) bm->Planes[i] = bm->Planes[0] + plsize * i;
  413.  
  414.    /* Read data from disk */
  415.    for (i = 0; i < bm->Depth; i++) {
  416.       nb = Read(file, bm->Planes[i], plsize);
  417.       if (nb < plsize) return((BOOL) FALSE);
  418.    }
  419.  
  420.    return((BOOL) TRUE);
  421. }
  422.  
  423. void alert(struct Window *win, char *msg1, char *msg2)
  424. {
  425.     static struct TextAttr alert_attr = { "topaz.font", 8 };
  426.     struct TextFont *alert_font;
  427.     struct IntuiText text1, text2, negative;
  428.     const static struct IntuiText template = {
  429.     0, 1, JAM1,
  430.     8, 0,
  431.     &alert_attr
  432.     };
  433.     int width, height;
  434.     int ysize;
  435.  
  436.     alert_font = OpenFont(&alert_attr);
  437.  
  438.     ysize = alert_font ? alert_font->tf_YSize : 8;
  439.  
  440.     text1 = text2 = negative = template;
  441.     text1.TopEdge = 8;
  442.     text1.IText = msg1;
  443.     width = IntuiTextLength(&text1) + 40;
  444.     height = 37 + 2 * ysize;
  445.     if (msg2 != NULL)
  446.     {
  447.     int w;
  448.  
  449.     text1.NextText = &text2;
  450.     text2.TopEdge = text1.TopEdge + ysize;
  451.     text2.IText = msg2;
  452.  
  453.     height += ysize;
  454.     w = IntuiTextLength(&text2) + 20;
  455.     if (w > width) width = w;
  456.     }
  457.     negative.LeftEdge = 6;
  458.     negative.TopEdge = 4;
  459.     negative.IText = "Ok";
  460.  
  461.     AutoRequest(win, &text1, NULL, &negative, 0L, 0L, width, height);
  462. }
  463.  
  464. /* Amiga specific initialisation */
  465. #define argw ((struct WBStartup *)argv)
  466. BOOL AmigaInit(argc, argv)
  467. int argc;
  468. APTR argv;
  469. {
  470.    register LONG file;
  471.    register BOOL loaded;
  472.    struct BitMap hp11bitmap;
  473.    BPTR hp11dir, old;
  474.    char filename[PATHLEN + 8];
  475.  
  476.    if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33))) /* Open graphics library (1.2) */
  477.       return(FALSE);
  478.  
  479.    if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 33))) /* Open intuition library (1.2) */
  480.       return(FALSE);
  481.  
  482.    if (!(LayersBase = (struct LayersBase *)OpenLibrary("layers.library", 0)))
  483.       return(FALSE);
  484.  
  485.    /* Find path to command (if possible) */
  486.    if (argc == 0) /* WB */
  487.    {
  488.       old = CurrentDir(argw->sm_ArgList[0].wa_Lock);
  489.       split(argw->sm_ArgList[0].wa_Name, hp11path, &hp11name);
  490.       hp11dir = Lock(hp11path, ACCESS_READ);
  491.       if (!mygetpath(hp11path, hp11dir)) hp11path[0] = '\0';
  492.       CurrentDir(old);
  493.       UnLock(hp11dir);
  494.    }
  495.    else
  496.    { /* CLI */
  497.       split(((char **)argv)[0], hp11path, &hp11name);
  498.    }
  499.  
  500.    /* Read the picture */
  501.    if (!(file = Open(strcat(strcpy(filename, hp11path), "hp11.pic"), MODE_OLDFILE)))
  502.       if (!(file = Open("hp11.pic", MODE_OLDFILE)))
  503.       {
  504.      alert(NULL, "Can't find hp11.pic", NULL);
  505.      return(FALSE);
  506.       }
  507.    loaded = LoadBitMap(file, &hp11bitmap, HP11WIDTH, HP11HEIGHT, 2);
  508.    Close(file);
  509.    if (!loaded) return(FALSE);
  510.  
  511.    /* Open the window */
  512.    if (!(hp11 = OpenWindow(&hp11new))) return(FALSE);
  513.  
  514.    /* Move picture into window */
  515.    BltBitMapRastPort(&hp11bitmap, 0, 0, hp11->RPort, HP11X, HP11Y, HP11WIDTH, HP11HEIGHT, COPY);
  516.    FreeMem(hp11bitmap.Planes[0], (long)(hp11bitmap.BytesPerRow * hp11bitmap.Rows * hp11bitmap.Depth));
  517.  
  518.    /* Create timer */
  519.    if ((timer = CreateTimer(UNIT_MICROHZ)) == NULL) return(FALSE);
  520.  
  521.    /* Init menus */
  522.    return(MenusInit(argc, argv));
  523. }
  524. #undef argw
  525.  
  526. void AmigaCleanUp()
  527. {
  528.    MenusCleanUp();
  529.    if (timer) DeleteTimer(timer); /* Close timer */
  530.    if (hp11) CloseWindow(hp11);
  531.    if (LayersBase) CloseLibrary((struct Library *)LayersBase);
  532.    if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase); /* Close libraries */
  533.    if (GfxBase) CloseLibrary((struct Library *)GfxBase);
  534. }
  535.  
  536. /* Display s */
  537. void Display(s)
  538. register char *s;
  539. {
  540.    register int posx;
  541.    register int chr;
  542.    register struct RastPort *rport = hp11->RPort;
  543.  
  544.    /* Clear display */
  545.    SetDrMd(rport, JAM1); SetAPen(rport, 2);
  546.    RectFill(rport, SCRX0 + 1, SCRY0, SCRX1 - 1, SCRY1);
  547.  
  548.    /* Initial position */
  549.    posx = SCRX0 + CHAROFFX;
  550.  
  551.    while (*s) {
  552.       switch (*s) { /* Position of char in char array */
  553.      case '0': case '1': case '2': case '3': case '4': case '5': case '6':
  554.      case '7': case '8': case '9': chr = *s - '0'; break;
  555.      case '-': chr = 10; break;
  556.      case 'E': chr = 11; break;
  557.      case 'r': chr = 12; break;
  558.      case 'o': chr = 13; break;
  559.      case 'R': chr = 14; break;
  560.      case 'u': chr = 15; break;
  561.      case 'n': chr = 16; break;
  562.      case 'i': chr = 17; break;
  563.      case 'g': chr = 18; break;
  564.      case '.': chr = 19; break;
  565.      case ',': chr = 20; break;
  566.      case 'P': chr = 21; break;
  567.      default:  chr = -1; break;
  568.       }
  569.       if (chr != -1)
  570.      DrawBorder(rport, hp11char[chr], (long)posx, SCRY0 + CHAROFFY);
  571.  
  572.       if (*s != '.' && *s != ',') posx += CHARWIDTH;
  573.  
  574.       s++;
  575.    }
  576. }
  577.  
  578. /* Set image to be drawn/erased according to on */
  579. static void SetCol(struct Image *im, int on)
  580. {
  581.    if (on) {
  582.       im->PlanePick = 3;
  583.       im->PlaneOnOff = 0;
  584.    }
  585.    else {
  586.       im->PlanePick = 0;
  587.       im->PlaneOnOff = 2;
  588.    }
  589. }
  590.  
  591. /* Display the indicators */
  592. void Dispf(on)
  593. int on;
  594. {
  595.    SetCol(&fImage, on);
  596.    DrawImage(hp11->RPort, &fImage, fX, INDICY);
  597. }
  598.  
  599. void Dispg(on)
  600. int on;
  601. {
  602.    SetCol(&gImage, on);
  603.    DrawImage(hp11->RPort, &gImage, gX, INDICY);
  604. }
  605.  
  606. void DispUSER(on)
  607. int on;
  608. {
  609.    SetCol(&USERImage, on);
  610.    DrawImage(hp11->RPort, &USERImage, USERX, INDICY);
  611. }
  612.  
  613. void DispG(on)
  614. int on;
  615. {
  616.    SetCol(&GImage, on);
  617.    DrawImage(hp11->RPort, &GImage, GX, INDICY);
  618. }
  619.  
  620. void DispRAD(on)
  621. int on;
  622. {
  623.    SetCol(&RADImage, on);
  624.    DrawImage(hp11->RPort, &RADImage, RADX, INDICY);
  625. }
  626.  
  627. void DispPRGM(on)
  628. int on;
  629. {
  630.    SetCol(&PRGMImage, on);
  631.    DrawImage(hp11->RPort, &PRGMImage, PRGMX, INDICY);
  632. }
  633.  
  634. void beep(void)
  635. {
  636.    DisplayBeep(NULL);
  637. }
  638.  
  639. static struct Window *MakeIcon(struct Image *image,
  640.                    struct BitMap *bm, struct BitMap *tmpbm,
  641.                    LONG x, LONG y, LONG w, LONG h)
  642. {
  643.    register struct Window *win;
  644.    register ULONG size;
  645.    static struct NewWindow new_win =
  646.    { 0, 0, 0, 0, -1, -1, MOUSEBUTTONS | MOUSEMOVE | INACTIVEWINDOW | NOCAREREFRESH,
  647.      SMART_REFRESH | BORDERLESS | REPORTMOUSE | RMBTRAP,
  648.      NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN };
  649.  
  650.    new_win.LeftEdge = x; new_win.TopEdge = y;
  651.    new_win.Width = w; new_win.Height = h;
  652.  
  653.    InitBitMap(bm, 2, w, h);
  654.    size = bm->BytesPerRow * bm->Rows; /* size of 1 plane */
  655.    bm->Planes[0] = (PLANEPTR)image->ImageData;
  656.    bm->Planes[1] = (PLANEPTR)(image->ImageData) + size;
  657.  
  658.    InitBitMap(tmpbm, 2, w, h);
  659.    if (!(tmpbm->Planes[0] = (PLANEPTR)AllocMem(2 * size, MEMF_CHIP)))
  660.      return(NULL);
  661.    tmpbm->Planes[1] = tmpbm->Planes[0] + size;
  662.  
  663.    if (win = OpenWindow(&new_win)) DrawImage(win->RPort, image, 0, 0);
  664.    else FreeMem(tmpbm->Planes[0], 2 * size);
  665.  
  666.    return(win);
  667. }
  668.  
  669. static void GetBounds(struct Window *win, LONG *mx, LONG *my,
  670.               LONG w, LONG h, LONG wx, LONG wy)
  671. {
  672.    struct Screen *scr = win->WScreen;
  673.  
  674.    *mx = scr->MouseX - wx; *my = scr->MouseY - wy;
  675.    if (*mx + w > scr->Width) *mx = scr->Width - w;
  676.    else if (*mx < 0) *mx = 0;
  677.    if (*my + h > scr->Height) *my = scr->Height - h;
  678.    else if (*my < 0) *my = 0;
  679. }
  680.  
  681. static void SwapImage(struct BitMap *scrbm, struct BitMap *drawing,
  682.               struct BitMap *buf, LONG x, LONG y, LONG w, LONG h)
  683. {
  684.    BltBitMap(scrbm, x, y, buf, 0, 0, w, h, COPY, 0xff, NULL);
  685.    BltBitMap(drawing, 0, 0, scrbm, x, y, w, h, COPY, 0xff, NULL);
  686.    BltBitMap(buf, 0, 0, drawing, 0, 0, w, h, COPY, 0xff, NULL);
  687. }
  688.  
  689. static void Iconize(struct Image *image, LONG x, LONG y)
  690. {
  691.    register struct Window *win;
  692.    register struct Screen *scr;
  693.    register struct IntuiMessage *msg;
  694.    LONG mx, my, wx, wy;
  695.    register LONG w, h;
  696.    ULONG oldsecs = 0, oldmicros = 0;
  697.    BOOL cont, moved;
  698.    register BOOL down, wasdown;
  699.    struct BitMap image_bm, tmpbm;
  700.  
  701.    w = image->Width; h = image->Height;
  702.    win = MakeIcon(image, &image_bm, &tmpbm, x, y, w, h);
  703.    if (win)
  704.    {
  705.       scr = win->WScreen;
  706.       cont = TRUE;
  707.       down = FALSE;
  708.       do {
  709.      moved = FALSE; wasdown = down;
  710.      WaitPort(win->UserPort);
  711.      while (msg = (struct IntuiMessage *)GetMsg(win->UserPort))
  712.      {
  713.         switch (msg->Class)
  714.         {
  715.            case MOUSEBUTTONS:
  716.           if (msg->Code == SELECTUP)
  717.           {
  718.              if (DoubleClick(oldsecs, oldmicros, msg->Seconds, msg->Micros))
  719.             cont = FALSE;
  720.              else {
  721.             oldsecs = msg->Seconds;
  722.             oldmicros = msg->Micros;
  723.              }
  724.           }
  725.           down = (msg->Code == SELECTDOWN);
  726.           break;
  727.            case INACTIVEWINDOW: down = FALSE; break;
  728.            case MOUSEMOVE: moved = TRUE; break;
  729.         }
  730.         ReplyMsg((struct Message *)msg);
  731.      }
  732.      if (!wasdown && down)
  733.      {
  734.         wx = win->MouseX; wy = win->MouseY;
  735.         GetBounds(win, &mx, &my, w, h, wx, wy);
  736.         LockLayers(&scr->LayerInfo);
  737.         SwapImage(&scr->BitMap, &image_bm, &tmpbm, mx, my, w, h);
  738.      }
  739.      else if (wasdown)
  740.         if (down)
  741.         {
  742.            if (moved)
  743.            {
  744.           SwapImage(&scr->BitMap, &image_bm, &tmpbm, mx, my, w, h);
  745.           GetBounds(win, &mx, &my, w, h, wx, wy);
  746.           SwapImage(&scr->BitMap, &image_bm, &tmpbm, mx, my, w, h);
  747.            }
  748.         }
  749.         else
  750.         {
  751.            SwapImage(&scr->BitMap, &image_bm, &tmpbm, mx, my, w, h);
  752.            UnlockLayers(&scr->LayerInfo);
  753.            MoveWindow(win, (long)(mx - win->LeftEdge), (long)(my - win->TopEdge));
  754.         }
  755.       } while (cont || down);
  756.  
  757.       CloseWindow(win);
  758.       FreeMem(tmpbm.Planes[0], 2 * RASSIZE(w, h));
  759.    }
  760. }
  761.  
  762. void sleep()
  763. {
  764.    struct BitMap hp11bitmap;
  765.    struct RastPort hp11rport;
  766.    register LONG plsize;
  767.    register LONG x, y;
  768.  
  769.    /* Save picture in bitmap */
  770.    InitBitMap(&hp11bitmap, 2, HP11WIDTH, HP11HEIGHT);
  771.    plsize = hp11bitmap.BytesPerRow * hp11bitmap.Rows; /* size of 1 plane */
  772.    /* Allocate enough memory for all planes, initialise plane pointers */
  773.    if (!(hp11bitmap.Planes[0] = (PLANEPTR)AllocMem(plsize * 2, MEMF_CHIP)))
  774.       Message("Not enough memory");
  775.    else
  776.    {
  777.       hp11bitmap.Planes[1] = hp11bitmap.Planes[0] + plsize;
  778.       InitRastPort(&hp11rport);
  779.       hp11rport.BitMap = &hp11bitmap;
  780.       ClipBlit(hp11->RPort, HP11X, HP11Y, &hp11rport, 0, 0,
  781.            HP11WIDTH, HP11HEIGHT, COPY);
  782.       Forbid();
  783.       x = hp11->LeftEdge; y = hp11->TopEdge;
  784.       Permit();
  785.       ClearMenuStrip(hp11);
  786.       CloseWindow(hp11);
  787.  
  788.       Iconize(&off_image, x, y);
  789.  
  790.       /* Open the window */
  791.       hp11new.LeftEdge = x; hp11new.TopEdge = y;
  792.       if (!(hp11 = OpenWindow(&hp11new)))
  793.       {
  794.      AutoRequest(NULL, &nomemtext, NULL, &canceltext, NULL, NULL, 250, 60);
  795.      quit = TRUE;
  796.       }
  797.       else {
  798.      /* Move picture into window */
  799.      BltBitMapRastPort(&hp11bitmap, 0, 0, hp11->RPort, HP11X, HP11Y, HP11WIDTH, HP11HEIGHT, COPY);
  800.      FreeMem(hp11bitmap.Planes[0], (long)(hp11bitmap.BytesPerRow * hp11bitmap.Rows * hp11bitmap.Depth));
  801.      SetMenuStrip(hp11, hp11menu);
  802.      on = TRUE;
  803.       }
  804.    }
  805. }
  806.  
  807.