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