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