home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d09xx / d0912.lha / Yak / Source / Source.lha / hotkey_types.c < prev    next >
C/C++ Source or Header  |  1993-07-31  |  14KB  |  675 lines

  1. /*
  2.  * Commands relating to Yak hotkey types
  3.  * mws, 27 April 1993
  4.  */
  5. #include <exec/types.h>
  6. #include <exec/libraries.h>
  7. #include <exec/memory.h>
  8. #include <devices/inputevent.h>
  9. #include <dos/dos.h>
  10. #include <dos/datetime.h>
  11. #include <dos/dostags.h>
  12. #include <graphics/displayinfo.h>
  13. #include <libraries/commodities.h>
  14. #include <libraries/reqtools.h>
  15. #include <libraries/locale.h>
  16. #include <intuition/intuitionbase.h>
  17.  
  18. #include <proto/exec.h>
  19. #include <proto/dos.h>
  20. #include <proto/graphics.h>
  21. #include <proto/commodities.h>
  22. #include <proto/intuition.h>
  23. #include <proto/reqtools.h>
  24. #include <proto/locale.h>
  25.  
  26. #include <string.h>
  27.  
  28. #include "hotkey_types.h"
  29. #include "yak.h"
  30. #include "localprotos.h"
  31.  
  32. extern struct IntuitionBase *IntuitionBase;
  33. extern struct Library *LocaleBase;
  34.  
  35. UWORD num_hkeys;
  36.  
  37. /*
  38.  * Utility functions
  39.  */
  40. #define HOW_ZIP        0
  41. #define HOW_SHRINK     1
  42. #define HOW_ENLARGE    2
  43.  
  44. static void HandleWindowKey(int how);
  45. static void __saveds __asm putcharfunc( register __a0 struct Hook *h,
  46.                     register __a2 void *object,
  47.                     register __a1 char c);
  48. static struct InputEvent *FlipIEvents(struct InputEvent *);
  49. static int AddToStream(char *str); 
  50. static struct Window * FindWBWindow(void);
  51. static void __saveds DoPalette(void);
  52. static int palette_count;
  53. static LONG beginCommand(char *command);
  54.  
  55.  
  56. /*
  57.  * HotKey Action function prototypes
  58.  */
  59. static void     act_DosCommand(YakHotKey *yhk), act_CloseWindow(YakHotKey *yhk),
  60.         act_ZipWindow(YakHotKey *yhk), act_ShrinkWindow(YakHotKey *yhk),
  61.         act_ExpandWindow(YakHotKey *yhk), act_CycleWindows(YakHotKey *yhk),
  62.         act_OpenPalette(YakHotKey *yhk), act_ScreenToFront(YakHotKey *yhk),
  63.         act_ScreenToBack(YakHotKey *yhk), act_ActivateWorkbench(YakHotKey *yhk),
  64.         act_CentreScreen(YakHotKey *yhk), act_BlankDisplay(YakHotKey *yhk),
  65.         act_InsertText(YakHotKey *yhk), act_InsertDate(YakHotKey *yhk),
  66.         act_ShowInterface(YakHotKey *yhk);
  67.  
  68. #define EMPTY_MINLIST {NULL,NULL,NULL}
  69. YakHotKeyType yhktypes[NUM_HOTKEY_TYPES] = {
  70.  
  71.     { EMPTY_MINLIST, act_DosCommand, 0, TAKES_ARGUMENT|HAS_OPTIONS },
  72.     { EMPTY_MINLIST, act_CloseWindow, 0, 0L },
  73.     { EMPTY_MINLIST, act_ZipWindow, 0, 0L },
  74.     { EMPTY_MINLIST, act_ShrinkWindow, 0, 0L },
  75.     { EMPTY_MINLIST, act_ExpandWindow, 0, 0L },
  76.     { EMPTY_MINLIST, act_CycleWindows, 0, 0L },
  77.     { EMPTY_MINLIST, act_OpenPalette, 0, HAS_OPTIONS },
  78.     { EMPTY_MINLIST, act_ScreenToFront, 0, 0L },
  79.     { EMPTY_MINLIST, act_ScreenToBack, 0, 0L },
  80.     { EMPTY_MINLIST, act_ActivateWorkbench, 0, 0L },
  81.     { EMPTY_MINLIST, act_CentreScreen, 0, 0L },
  82.     { EMPTY_MINLIST, act_BlankDisplay, 0, 0L },
  83.     { EMPTY_MINLIST, act_InsertText, 0, TAKES_ARGUMENT },
  84.     { EMPTY_MINLIST, act_InsertDate, 0, TAKES_ARGUMENT },
  85.     { EMPTY_MINLIST, act_ShowInterface, 0, 0L }
  86. };
  87.  
  88.  
  89. /*
  90.  * Utility functions
  91.  */
  92. #define AdjustedLeftEdge(w, width) \
  93.     (w->LeftEdge + width > w->WScreen->Width ? \
  94.     w->WScreen->Width - width : w->LeftEdge)
  95. #define AdjustedTopEdge(w, height) \
  96.     (w->TopEdge + height > w->WScreen->Height ? \
  97.     w->WScreen->Height - height : w->TopEdge)
  98.  
  99. /* zip/enlarge or whatever the currently active window */
  100. static void
  101. HandleWindowKey(int how)
  102. {
  103.     struct Window *window;
  104.     ULONG lock;
  105.  
  106.     lock = LockIBase(0);
  107.     if (window = IntuitionBase->ActiveWindow)
  108.     {
  109.         switch (how)
  110.         {
  111.         case HOW_ZIP:
  112.             if (window->Flags & WFLG_HASZOOM)
  113.                 ZipWindow(window);
  114.             break;
  115.  
  116.         case HOW_SHRINK:
  117.             if (window->Flags & WFLG_SIZEGADGET)
  118.                 ChangeWindowBox(window,
  119.                         window->LeftEdge,
  120.                         window->TopEdge,
  121.                         window->MinWidth,
  122.                         window->MinHeight);
  123.             break;
  124.  
  125.         case HOW_ENLARGE:
  126.             {    /* sometimes Max vars are -1 == NO LIMIT */
  127.             USHORT width, height;
  128.  
  129.             width = window->MaxWidth;
  130.             if (width == -1) width = window->WScreen->Width-width;
  131.             height = window->MaxHeight;
  132.             if (height == -1) height = window->WScreen->Height-height;
  133.             
  134.             if (window->Flags & WFLG_SIZEGADGET)
  135.                 ChangeWindowBox(window,
  136.                         AdjustedLeftEdge(window, width),
  137.                         AdjustedTopEdge(window, height),
  138.                         width,
  139.                         height);
  140.             }
  141.             break;
  142.  
  143.         } /* switch */
  144.     }
  145.     UnlockIBase(lock);
  146. }
  147.  
  148. /* hook-function for inserting chars into input-stream */
  149. static void __saveds __asm
  150. putcharfunc(    register __a0 struct Hook *h,
  151.         register __a2 void *object,
  152.         register __a1 char c)
  153. {
  154.     struct InputEvent ev;
  155.  
  156.     if (c)    /* stop at null-terminator */
  157.     {
  158.         ev.ie_NextEvent = NULL;
  159.         InvertKeyMap(c, &ev, NULL);
  160.         AddIEvents(&ev);
  161.     }
  162. }
  163. /* and its associated structure */
  164. static struct Hook putcharhook = {
  165.     {NULL, NULL},
  166.     (APTR)putcharfunc,
  167.     NULL,
  168.     NULL
  169. };
  170.  
  171. /* given a list of input events, reverse their order */
  172. /* NB: the list BETTER terminate... */
  173. static struct InputEvent *
  174. FlipIEvents(struct InputEvent *ie)
  175. {
  176.     struct InputEvent *oldtail, *newtail = NULL;
  177.  
  178.     while (ie)
  179.     {
  180.         /* remove head, set next event */
  181.         oldtail = ie->ie_NextEvent;    /* this will be prev event */
  182.         ie->ie_NextEvent = newtail;    /* add to head */
  183.         newtail = ie;
  184.         ie = oldtail;            /* what's left */
  185.     }
  186.     return newtail;
  187. }
  188.  
  189. /* adds a string to the input-stream */
  190. static int
  191. AddToStream(char *str)
  192. {
  193.     struct InputEvent *ie;
  194.  
  195.     if (ie = InvertString(str, NULL))
  196.     {
  197.                 ie = FlipIEvents(ie);
  198.                    AddIEvents(ie);
  199.         FreeIEvents(ie);
  200.         return TRUE;
  201.     }
  202.     return FALSE;
  203. }
  204.  
  205. /* find (a) Workbench window */
  206. static struct Window *
  207. FindWBWindow()
  208. {
  209.     struct Screen *s = LockPubScreen("Workbench");
  210.     if (s)
  211.     {
  212.     struct Window *w = s->FirstWindow;
  213.     WBenchToFront();
  214.     Forbid();
  215.     for (; w; w = w->NextWindow)
  216.         if (w->Flags & WFLG_WBENCHWINDOW)
  217.             break;
  218.     Permit();
  219.     UnlockPubScreen(NULL, s);
  220.     return w;
  221.     }
  222.     return NULL;
  223. }
  224.  
  225. /* bring a palette up on frontmost screen */
  226. /* CreateNewProc this function... */
  227. static void __saveds
  228. DoPalette()
  229. {
  230.     struct ReqToolsBase *ReqToolsBase;
  231.     LONG tags[3];
  232.  
  233.     palette_count++;
  234.     if (ReqToolsBase = (void *)OpenLibrary("reqtools.library", 0L))
  235.     {
  236.         tags[0] = RT_Screen;
  237.         tags[1] = (LONG)ReqToolsBase->IntuitionBase->FirstScreen;
  238.         tags[2] = TAG_DONE;
  239.         (void) rtPaletteRequestA("Palette", NULL, (struct TagItem *)tags);
  240.         CloseLibrary(ReqToolsBase);
  241.     }
  242.     palette_count--;
  243. }
  244.  
  245. /*
  246.  * Asynchronous external command started with its own autocon Input/Output
  247.  * Result will only reflect whether System() call itself succeeded.
  248.  * If System() call fails, result will be -1L; -2L for window failure.
  249.  * We are using -2L as result if our Open of CON: fails
  250.  */
  251. #define AUTOCON "CON:0/25/640/150/Yak Command/AUTO/CLOSE/WAIT/ALT0/25/80/50"
  252. static LONG
  253. beginCommand(char *command)
  254. {
  255.     static ULONG stags[] = {
  256.         SYS_Input, NULL,
  257.         SYS_Output, NULL,
  258.         SYS_Asynch, TRUE,
  259.         SYS_UserShell, TRUE,
  260.         NP_Priority, 0L,
  261.         TAG_DONE
  262.     };
  263.     BPTR file;
  264.     char *filename;
  265.  
  266. #ifdef NOTDEF    /* will this screw up sometimes? */
  267.     char *t;
  268.     int inquote = FALSE, usecon = TRUE;
  269.  
  270.     /* determine (simple-mindedly) whether there's redirection */
  271.     for (t = command; *t; t++)
  272.     {
  273.         if (*t == '\"')
  274.             if (t <= command || t[-1] != '*')
  275.                 inquote ^= 1;
  276.         if (!inquote)
  277.             if (*t == '>')
  278.             {
  279.                 usecon = FALSE;
  280.                 break;
  281.             }
  282.     }
  283.  
  284.     filename = usecon ? AUTOCON : "NIL:";
  285. #else
  286.     filename = AUTOCON;
  287. #endif
  288.     if (file = Open(filename, MODE_OLDFILE))
  289.         {
  290.         stags[1] = (ULONG)file;
  291.         return(SystemTagList(command, (struct TagItem *)stags));
  292.         }
  293.     else return(-2);
  294. }
  295.  
  296.  
  297. /*
  298.  * the hotkey actions themselves
  299.  */
  300.  
  301. /* asynchronously execute a dos command */
  302. static void
  303. act_DosCommand(YakHotKey *yhk)
  304. {
  305.     if (yhk->yhk_ArgStr)
  306.     {
  307.         LONG rc = beginCommand(yhk->yhk_ArgStr);
  308.  
  309.         if (rc == -1)
  310.             PostError("Could not start process for command\n\"%s\"",
  311.                     yhk->yhk_ArgStr);
  312.         else if (rc == -2)
  313.             PostError("Could not open con: for command\n\"%s\"",
  314.                     yhk->yhk_ArgStr);
  315.      }
  316.     else PostError("No command specified for hotkey \"%s\".", yhk->yhk_KeyDef);
  317. }
  318.  
  319. static void
  320. act_CloseWindow(YakHotKey *yhk)
  321. {
  322.     struct InputEvent ev;
  323.     struct Window *window;
  324.     ULONG lock;
  325.  
  326.     lock = LockIBase(0);
  327.     window = IntuitionBase->ActiveWindow;
  328.     UnlockIBase(lock);
  329.  
  330.     if (window && (window->IDCMPFlags & CLOSEWINDOW))
  331.     {
  332.         ev.ie_NextEvent = NULL;
  333.         ev.ie_Class = IECLASS_CLOSEWINDOW;
  334.         ev.ie_SubClass = 0;
  335.         ev.ie_Code = 0;
  336.         ev.ie_Qualifier = 0;
  337.         ev.ie_EventAddress = 0;
  338.         AddIEvents(&ev);
  339.     }
  340. }
  341.  
  342. static void
  343. act_ZipWindow(YakHotKey *yhk)
  344. {
  345.     HandleWindowKey(HOW_ZIP);
  346. }
  347.  
  348. static void
  349. act_ShrinkWindow(YakHotKey *yhk)
  350. {
  351.     HandleWindowKey(HOW_SHRINK);
  352. }
  353.  
  354. static void
  355. act_ExpandWindow(YakHotKey *yhk)
  356. {
  357.     HandleWindowKey(HOW_ENLARGE);
  358. }
  359.  
  360. static void
  361. act_CycleWindows(YakHotKey *yhk)
  362. {
  363. #define NOCYCLEFLAGS (WFLG_BACKDROP)
  364.  
  365.     struct Screen *s;
  366.     struct Window *w, *backmost;
  367.     struct Layer *l;
  368.     ULONG lock;
  369.  
  370.     lock = LockIBase(0);
  371.     if (s = IntuitionBase->FirstScreen)
  372.     {
  373.         Forbid();
  374.         backmost = NULL;
  375.         for (l = s->LayerInfo.top_layer; l; l = l->back)
  376.         {
  377.             w = (struct Window *)l->Window;
  378.             if (w && !(w->Flags & NOCYCLEFLAGS))
  379.                 backmost = w;
  380.         }
  381.  
  382.         if (backmost)
  383.         {
  384.             ScreenToFront(s);
  385.             WindowToFront(backmost);
  386.             ActivateWindow(backmost);
  387.         }
  388.         Permit();
  389.     }
  390.     UnlockIBase(lock);
  391. }
  392.  
  393. /* taglist for CreateNewProc */
  394. static LONG palette_taglist[] = {
  395.     NP_Entry, (LONG)DoPalette,
  396.     NP_Name, (LONG)"Yak Palette",
  397.     TAG_DONE
  398. };
  399.  
  400. static void
  401. act_OpenPalette(YakHotKey *yhk)
  402. {
  403.     CreateNewProc((struct TagItem *)palette_taglist);
  404. }
  405.  
  406. static void
  407. act_ScreenToFront(YakHotKey *yhk)
  408. {
  409.     struct Screen *s;
  410.     ULONG lock;
  411.  
  412.     lock = LockIBase(0);
  413.     for (s = IntuitionBase->FirstScreen; s; s = s->NextScreen)
  414.         if (!s->NextScreen)
  415.         {
  416.             ScreenToFront(s);
  417.             if (scractivate)
  418.                 ActivateMouseWindow(SCREEN);
  419.             break;
  420.         }
  421.     UnlockIBase(lock);
  422. }
  423.  
  424. static void
  425. act_ScreenToBack(YakHotKey *yhk)
  426. {
  427.     MyScreenToBack(IntuitionBase->FirstScreen);
  428. }
  429.  
  430. static void
  431. act_ActivateWorkbench(YakHotKey *yhk)
  432. {
  433.     struct Window *w;
  434.  
  435.     if (w = FindWBWindow())
  436.     {
  437.         WBenchToFront();
  438.         ActivateWindow(w);
  439.     }
  440. }
  441.  
  442. static void
  443. act_CentreScreen(YakHotKey *yhk)
  444. {
  445.     struct Rectangle rect;
  446.     struct Screen *s;
  447.     ULONG    lock;
  448.     ULONG    modeid;
  449.     WORD    newle;
  450.  
  451.     lock = LockIBase(0);
  452.     if ((s = IntuitionBase->FirstScreen) &&
  453.         (modeid = GetVPModeID(&s->ViewPort)) != INVALID_ID &&
  454.         QueryOverscan(modeid, &rect, OSCAN_TEXT))
  455.     {
  456.         newle = (rect.MinX + rect.MaxX + 1 - s->Width) >> 1;
  457.         MoveScreen(s, newle - s->LeftEdge, 0);
  458.     }
  459.     UnlockIBase(lock);
  460. }
  461.  
  462. static void
  463. act_BlankDisplay(YakHotKey *yhk)
  464. {
  465.     BlankScreen();
  466. }
  467.  
  468. static void
  469. act_InsertText(YakHotKey *yhk)
  470. {
  471.     if (yhk->yhk_ArgStr)
  472.     {
  473.         if (!AddToStream(yhk->yhk_ArgStr))
  474.             PostError("Yak text insertion string invalid:\n \"%s\"", yhk->yhk_ArgStr); 
  475.     }
  476.     else PostError("Yak text hotkey \"%s\" has no text specified.", yhk->yhk_KeyDef);
  477. }
  478.  
  479. static void
  480. act_InsertDate(YakHotKey *yhk)
  481. {
  482.     struct DateTime dat;
  483.     DateStamp(&dat.dat_Stamp);
  484.  
  485.     if (LocaleBase)
  486.     {
  487.         if (yhk->yhk_ArgStr)
  488.             FormatDate(locale, yhk->yhk_ArgStr, &dat.dat_Stamp, &putcharhook);
  489.         else PostError("Yak date hotkey \"%s\" has no format specified.", yhk->yhk_KeyDef);
  490.     }
  491.     else
  492.     {
  493.         /* pre-2.1 OS */
  494.         char datestr[LEN_DATSTRING];
  495.  
  496.         dat.dat_Format = FORMAT_DOS;
  497.         dat.dat_Flags = 0;
  498.         dat.dat_StrDate = datestr;
  499.         dat.dat_StrDay = dat.dat_StrTime = NULL;
  500.         DateToStr(&dat);
  501.         AddToStream(datestr);
  502.     }
  503. }
  504.  
  505. static void
  506. act_ShowInterface(YakHotKey *yhk)
  507. {
  508.     ShowWindow();
  509. }
  510.  
  511. /*
  512.  * the generic hotkey action stub
  513.  */
  514. void
  515. PerformAction(YakHotKey *yhk)
  516. {
  517.     if (yhk->yhk_Options)
  518.     {
  519.         struct Screen *scr;
  520.         char *scrname;
  521.  
  522.         if (yhk->yhk_Options == WB_TO_FRONT)
  523.             scrname = "Workbench";
  524.         else
  525.             scrname = NULL;
  526.         
  527.         if (scr = LockPubScreen(scrname))
  528.         {
  529.             ScreenToFront(scr);
  530.             UnlockPubScreen(NULL, scr);
  531.         }
  532.     }
  533.  
  534.     /* and perform action (gobbledegook!? that's C for you...) */
  535.     (*(yhktypes[yhk->yhk_Type].yhkt_Command))(yhk);
  536. }
  537.  
  538. /*
  539.  * YakHotKey manipulation routines
  540.  */
  541. static void internal_DeleteYakHotKey(YakHotKey *yhk);
  542.  
  543. /* allocate memory region of size len+1, copy string to it */
  544. char *
  545. DupStr(char *str)
  546. {
  547.     char *newstr;
  548.     ULONG len;
  549.  
  550.     if (newstr = AllocVec(len=(strlen(str)+1),MEMF_CLEAR))
  551.     {
  552.         CopyMem(str,newstr,len);
  553.     }
  554.     return newstr;
  555. }
  556.  
  557. /* free fields of hotkey */
  558. static void
  559. internal_DeleteYakHotKey(YakHotKey *yhk)
  560. {
  561.     if (yhk->yhk_ArgStr)
  562.         FreeStr(yhk->yhk_ArgStr);
  563.     if (yhk->yhk_KeyDef)
  564.         FreeStr(yhk->yhk_KeyDef);
  565.     if (yhk->yhk_CxObj)
  566.         DeleteCxObjAll(yhk->yhk_CxObj);
  567. }
  568.  
  569. /* free ALL memory associated with a hotkey and remove from list */
  570. void
  571. DeleteYakHotKey(YakHotKey *yhk)
  572. {
  573.     numkeys(yhk->yhk_Type)--;
  574.     num_hkeys--;
  575.     Remove((struct Node *)yhk);
  576.     internal_DeleteYakHotKey(yhk);
  577.     FreeVec(yhk);
  578. }
  579.  
  580. /* change key definition */
  581. int
  582. ModifyYHKKeyDef(YakHotKey *yhk, char *keystr)
  583. {
  584.     CxObj *filter;
  585.  
  586.     if (filter = HotKey(keystr, broker_mp, (LONG)yhk))
  587.     {
  588.         /* delete old filter and use new one */
  589.         if (yhk->yhk_CxObj)
  590.             DeleteCxObjAll(yhk->yhk_CxObj);
  591.         yhk->yhk_CxObj = filter;
  592.         AttachCxObj(broker, filter);
  593.  
  594.         /* and store new keystr */
  595.         if (yhk->yhk_KeyDef)
  596.             FreeStr(yhk->yhk_KeyDef);
  597.         if (yhk->yhk_KeyDef = DupStr(keystr))
  598.         {
  599.             yhk->yhk_Node.ln_Name = yhk->yhk_KeyDef;
  600.             return TRUE;
  601.         }
  602.         PostError("Allocation error");
  603.     }
  604.     else PostError("Invalid hotkey specification: \"%s\"", keystr);
  605.  
  606.     return FALSE;
  607. }
  608.  
  609. /* change argument string */
  610. int
  611. ModifyYHKArgStr(YakHotKey *yhk, char *argstr)
  612. {
  613.     char *newstr;
  614.  
  615.     if (argstr && *argstr)
  616.     {
  617.         if (newstr = DupStr(argstr))
  618.         {
  619.             FreeStr(yhk->yhk_ArgStr);
  620.             yhk->yhk_ArgStr = newstr;
  621.             return TRUE;
  622.         }
  623.         PostError("Allocation error");
  624.     }
  625.     else PostError("An argument should be specified for this key.");
  626.  
  627.     return FALSE;
  628. }
  629.  
  630. /* add a new hotkey of given type */
  631. YakHotKey *
  632. NewYakHotKey(UWORD type)
  633. {
  634.     YakHotKey *newhk;
  635.  
  636.     if (newhk = AllocVec(sizeof(YakHotKey), MEMF_CLEAR))
  637.     {
  638.         newhk->yhk_Node.ln_Name = "<unset>";
  639.         newhk->yhk_Type = type;
  640.         AddTail(keylist(type), (struct Node *)newhk);
  641.         numkeys(type)++;
  642.         num_hkeys++;
  643.     }
  644.     return newhk;
  645. }
  646.  
  647. /* initialise list */
  648. void
  649. InitYakHotKeyList()
  650. {
  651.     UWORD i;
  652.  
  653.     for (i = 0; i < NUM_HOTKEY_TYPES; i++)
  654.         NewList(keylist(i));
  655. }
  656.  
  657. /* delete whole list */
  658. void
  659. DeleteYakHotKeyList()
  660. {
  661.     YakHotKey *yhk;
  662.     UWORD i;
  663.  
  664.     for (i = 0; i < NUM_HOTKEY_TYPES; i++)
  665.         while (yhk = (YakHotKey *)RemHead(keylist(i)))
  666.             DeleteYakHotKey(yhk);
  667. }
  668.  
  669. /* okay to quit? (not so if palettes open) */
  670. int
  671. OkayToExit()
  672. {
  673.     return (palette_count == 0);
  674. }
  675.