home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / jove414s.zip / macros.c < prev    next >
C/C++ Source or Header  |  1991-07-06  |  8KB  |  409 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "ctype.h"
  10. #include "fp.h"
  11. #include "chars.h"
  12. #include "disp.h"
  13.  
  14. private void
  15.     add_mac proto((struct macro *)),
  16.     del_mac proto((struct macro *)),
  17.     pop_macro_stack proto((void)),
  18.     push_macro_stack proto((struct macro *, int));
  19.  
  20. private struct macro *mac_exists proto((char *));
  21.  
  22. #define SAVE        01    /* this macro needs saving to a file */
  23.  
  24. struct macro    *macros = 0;        /* macros */
  25. int    InMacDefine = NO;
  26.  
  27. private void
  28. add_mac(new)
  29. struct macro    *new;
  30. {
  31.     /* register */ struct macro    *mp,
  32.                 *prev = 0;
  33.  
  34.     for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm)
  35.         if (mp == new)
  36.             return;
  37.  
  38.     if (prev)
  39.         prev->m_nextm = new;
  40.     else
  41.         macros = new;
  42.     new->m_nextm = 0;
  43.     new->Type = MACRO;
  44. }
  45.  
  46. private void
  47. del_mac(mac)
  48. struct macro    *mac;
  49. {
  50.     /* register */ struct macro    *m;
  51.  
  52.     for (m = macros; m != 0; m = m->m_nextm)
  53.         if (m->m_nextm == mac) {
  54.             m->m_nextm = mac->m_nextm;
  55.             break;
  56.         }
  57.     free(mac->Name);
  58.     free(mac->m_body);
  59.     free((char *) mac);
  60. }
  61.  
  62. struct macro    KeyMacro;    /* Macro used for defining */
  63.  
  64. /* To execute a macro, we have a "stack" of running macros.  Whenever
  65.    we execute a macro, we push it on the stack, run it, then pop it
  66.    from the stack.  */
  67. struct m_thread {
  68.     struct m_thread    *mt_prev;
  69.     struct macro    *mt_mp;
  70.     int    mt_offset,
  71.         mt_count;
  72. };
  73.  
  74. private struct m_thread    *mac_stack = 0;
  75.  
  76. private struct m_thread *
  77. alloc_mthread()
  78. {
  79.     return (struct m_thread *) emalloc(sizeof (struct m_thread));
  80. }
  81.  
  82. private void
  83. free_mthread(t)
  84. struct m_thread    *t;
  85. {
  86.     free((char *) t);
  87. }
  88.  
  89. void
  90. unwind_macro_stack()
  91. {
  92.     while (mac_stack != 0)
  93.         pop_macro_stack();
  94. }
  95.  
  96. private void
  97. pop_macro_stack()
  98. {
  99.     /* register */ struct m_thread    *m;
  100.  
  101.     if ((m = mac_stack) == 0)
  102.         return;
  103.     mac_stack = m->mt_prev;
  104.     free_mthread(m);
  105. }
  106.  
  107. private void
  108. push_macro_stack(m, count)
  109. /* register */ struct macro    *m;
  110. int    count;
  111. {
  112.     /* register */ struct m_thread    *t;
  113.  
  114.     for (t = mac_stack; t != 0; t = t->mt_prev)
  115.         if (t->mt_mp == m)
  116.             complain("[Cannot execute macro recusively]");
  117.     if (count <= 0)
  118.         complain("[Cannot execute macro a negative number of times]");
  119.     t = alloc_mthread();
  120.     t->mt_prev = mac_stack;
  121.     mac_stack = t;
  122.     t->mt_offset = 0;
  123.     t->mt_mp = m;
  124.     t->mt_count = count;
  125. }
  126.  
  127. void
  128. do_macro(mac)
  129. struct macro    *mac;
  130. {
  131.     push_macro_stack(mac, arg_value());
  132. }
  133.  
  134. private struct macro *
  135. mac_exists(name)
  136. char    *name;
  137. {
  138.     /* register */ struct macro    *mp;
  139.  
  140.     for (mp = macros; mp; mp = mp->m_nextm)
  141.         if (strcmp(mp->Name, name) == 0)
  142.             return mp;
  143.     return 0;
  144. }
  145.  
  146. void
  147. mac_init()
  148. {
  149.     add_mac(&KeyMacro);
  150.     KeyMacro.Name = "keyboard-macro";
  151.     KeyMacro.m_len = 0;
  152.     KeyMacro.m_buflen = 16;
  153.     KeyMacro.m_body = emalloc((size_t) KeyMacro.m_buflen);
  154. }
  155.  
  156. void
  157. mac_putc(c)
  158. int    c;
  159. {
  160.     if (KeyMacro.m_len >= KeyMacro.m_buflen) {
  161.         KeyMacro.m_buflen += 16;
  162.         KeyMacro.m_body = realloc(KeyMacro.m_body, (size_t) KeyMacro.m_buflen);
  163.         if (KeyMacro.m_body == 0) {
  164.             KeyMacro.m_buflen = KeyMacro.m_len = 0;
  165.             complain("[Can't allocate storage for keyboard macro]");
  166.         }
  167.     }
  168.     KeyMacro.m_body[KeyMacro.m_len++] = c;
  169. }
  170.  
  171. int
  172. in_macro()
  173. {
  174.     return (mac_stack != NULL);
  175. }
  176.  
  177. int
  178. mac_getc()
  179. {
  180.     struct m_thread    *mthread;
  181.     struct macro    *m;
  182.  
  183.     if ((mthread = mac_stack) == NULL)
  184.         return EOF;
  185.     m = mthread->mt_mp;
  186.     if (mthread->mt_offset == m->m_len) {
  187.         mthread->mt_offset = 0;
  188.         if (--mthread->mt_count == 0)
  189.             pop_macro_stack();
  190.         return mac_getc();
  191.     }
  192.     return m->m_body[mthread->mt_offset++];
  193. }
  194.  
  195. void
  196. NameMac()
  197. {
  198.     char    *name;
  199.     struct macro    *m;
  200.  
  201.     if (KeyMacro.m_len == 0)
  202.         complain("[No keyboard macro to name!]");
  203.     if (in_macro() || InMacDefine)
  204.         complain("[Can't name while defining/executing]");
  205.     if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0)
  206.         m = (struct macro *) emalloc(sizeof *m);
  207.     else {
  208.         if (strcmp(name, KeyMacro.Name) == 0)
  209.             complain("[Can't name it that!]");
  210.         free(m->Name);
  211.         free(m->m_body);
  212.     }
  213.     name = copystr(name);
  214.     m->Type = KeyMacro.Type;
  215.     m->m_len = KeyMacro.m_len;
  216.     m->m_buflen = KeyMacro.m_buflen;
  217.     m->m_body = emalloc((size_t) m->m_buflen);
  218.     byte_copy(KeyMacro.m_body, m->m_body, (size_t) m->m_len);
  219.     m->m_flags = SAVE;
  220.     m->Name = name;
  221.     add_mac(m);
  222. }
  223.  
  224. void
  225. RunMacro()
  226. {
  227.     struct macro    *m;
  228.  
  229.     if ((m = (struct macro *) findmac(ProcFmt)) != NULL)
  230.         do_macro(m);
  231. }
  232.  
  233. private void
  234. pr_putc(c, fp)
  235. int    c;
  236. File    *fp;
  237. {
  238.     if (c == '\\' || c == '^')
  239.         jputc('\\', fp);
  240.      else if (isctrl(c)) {
  241.         jputc('^', fp);
  242.         c = (c == RUBOUT) ? '?' : (c + '@');
  243.     }
  244.     jputc(c, fp);
  245. }
  246.  
  247. void
  248. WriteMacs()
  249. {
  250.     struct macro    *m;
  251.     char    *file,
  252.         filebuf[FILESIZE];
  253.     File    *fp;
  254.     int    i;
  255.  
  256.     file = ask_file((char *) 0, (char *) 0, filebuf);
  257.     fp = open_file(file, iobuff, F_WRITE, YES, YES);
  258.  
  259.     /* Don't write the keyboard macro which is always the first */
  260.     for (m = macros->m_nextm; m != 0; m = m->m_nextm) {
  261.         fwritef(fp, "define-macro %s ", m->Name);
  262.         for (i = 0; i < m->m_len; i++)
  263.             pr_putc(m->m_body[i], fp);
  264.         jputc('\n', fp);
  265.         m->m_flags &= ~SAVE;
  266.     }
  267.     close_file(fp);
  268. }
  269.  
  270. void
  271. DefKBDMac()
  272. {
  273.     char    *macro_name,
  274.         *macro_body,
  275.         nextc,
  276.         c,
  277.         macro_buffer[LBSIZE];
  278.     int    i;
  279.     struct macro    *m;
  280.  
  281.     macro_name = do_ask(" \r\n", (int (*) proto((int))) 0, (char *) 0,
  282.         ProcFmt);
  283.     if (macro_name == 0)
  284.         complain("[No default]");
  285.     macro_name = copystr(macro_name);
  286.     if ((m = mac_exists(macro_name)) != NULL)
  287.         del_mac(m);
  288.     macro_body = ask((char *) 0, ": %f %s enter body: ", macro_name);
  289.     i = 0;
  290.     while ((c = *macro_body++) != '\0') {
  291.         if (c == '\\') {
  292.             if ((nextc = *macro_body++) == LF)
  293.                 complain("[Premature end of line]");
  294.             c = nextc;
  295.         } else if (c == '^') {
  296.             if ((nextc = *macro_body++) == '?')
  297.                 c = RUBOUT;
  298.             else if (isalpha(nextc) || strchr("@[\\]^_", nextc))
  299.                 c = CTL(nextc);
  300.             else
  301.                 complain("Bad control-character: '%c'", nextc);
  302.         }
  303.         macro_buffer[i++] = c;
  304.     }
  305.     m = (struct macro *) emalloc(sizeof (*m));
  306.     m->Name = macro_name;
  307.     m->m_len = m->m_buflen = i;
  308.     m->m_body = emalloc((size_t) i);
  309.     m->m_flags = InJoverc ? 0 : SAVE;
  310.     byte_copy(macro_buffer, m->m_body, (size_t) i);
  311.     add_mac(m);
  312. }
  313.  
  314. void
  315. Remember()
  316. {
  317.     /* We're already executing the macro; ignore any attempts
  318.        to define the keyboard macro while we are executing. */
  319.     if (in_macro())
  320.         return;
  321.     if (InMacDefine)
  322.         message("[Already defining ... continue with definition]");
  323.     else {
  324.         UpdModLine = YES;
  325.         InMacDefine = YES;
  326.         KeyMacro.m_len = 0;
  327.         message("Defining...");
  328.     }
  329. }
  330.  
  331. void
  332. Forget()
  333. {
  334.     char    *cp;
  335.     struct macro    *m = &KeyMacro;
  336.  
  337.     UpdModLine = YES;
  338.     if (InMacDefine) {
  339.         message("Keyboard macro defined.");
  340.         InMacDefine = NO;
  341.  
  342.         /* try and strip off the key sequence that invoked us */
  343.         cp = &m->m_body[m->m_len - 2];
  344.         if (PrefChar(*cp))
  345.             m->m_len -= 2;
  346.         else if (commands[cp[1]].c_proc == Forget)
  347.             m->m_len -= 1;
  348.     } else
  349.         complain("[end-kbd-macro: not currently defining macro!]");
  350. }
  351.  
  352. void
  353. ExecMacro()
  354. {
  355.     do_macro(&KeyMacro);
  356. }
  357.  
  358. void
  359. MacInter()
  360. {
  361.     if (!Asking)
  362.         return;
  363.     Interactive = 1;
  364. }
  365.  
  366. int
  367. ModMacs()
  368. {
  369.     /* register */ struct macro    *m;
  370.  
  371.     for (m = macros->m_nextm; m != 0; m = m->m_nextm)
  372.         if (m->m_flags & SAVE)
  373.             return YES;
  374.     return NO;
  375. }
  376.  
  377. data_obj *
  378. findmac(prompt)
  379. char    *prompt;
  380. {
  381.     char    *strings[100];
  382.     /* register */ char    **strs = strings;
  383.     /* register */ int    com;
  384.     /* register */ struct macro    *m = macros;
  385.  
  386.     for (; m != 0; m = m->m_nextm)
  387.         *strs++ = m->Name;
  388.     *strs = 0;
  389.  
  390.     if ((com = complete(strings, prompt, NOTHING)) < 0)
  391.         return 0;
  392.     m = macros;
  393.     while (--com >= 0)
  394.         m = m->m_nextm;
  395.     return (data_obj *) m;
  396. }
  397.  
  398. void
  399. DelMacro()
  400. {
  401.     struct macro    *m;
  402.  
  403.     if ((m = (struct macro *) findmac(ProcFmt)) == 0)
  404.         return;
  405.     if (m == &KeyMacro)
  406.         complain("[It's illegal to delete the keyboard-macro!]");
  407.     del_mac(m);
  408. }
  409.