home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / jove-4.16-src.tgz / tar.out / bsd / jove / macros.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  379 lines

  1. /************************************************************************
  2.  * This program is Copyright (C) 1986-1996 by Jonathan Payne.  JOVE is  *
  3.  * 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 "jctype.h"
  10. #include "fp.h"
  11. #include "chars.h"
  12. #include "disp.h"
  13. #include "ask.h"
  14. #include "commands.h"
  15. #include "macros.h"
  16. #include "extend.h"
  17. #include "fmt.h"
  18. /* #include "util.h" */
  19.  
  20. private void
  21.     pop_macro_stack proto((void));
  22.  
  23. private struct macro
  24.     *ask_macname proto((const char *, int));
  25.  
  26. private bool    UnsavedMacros = NO;    /* are there any macros that need saving to a file? */
  27.  
  28. struct macro    *macros = NULL;        /* macros */
  29. bool    InMacDefine = NO;
  30.  
  31. private void
  32. add_mac(new)
  33. struct macro    *new;
  34. {
  35.     register struct macro    *mp,
  36.                 *prev = NULL;
  37.  
  38.     for (mp = macros; mp != NULL; prev = mp, mp = mp->m_nextm)
  39.         if (mp == new)
  40.             return;
  41.  
  42.     if (prev)
  43.         prev->m_nextm = new;
  44.     else
  45.         macros = new;
  46.     new->m_nextm = NULL;
  47.     new->Type = MACRO;
  48. }
  49.  
  50. /* To execute a macro, we have a "stack" of running macros.  Whenever
  51.    we execute a macro, we push it on the stack, run it, then pop it
  52.    from the stack.  */
  53. struct m_thread {
  54.     struct m_thread    *mt_prev;
  55.     struct macro    *mt_mp;
  56.     int    mt_offset,
  57.         mt_count;
  58. };
  59.  
  60. private struct m_thread    *mac_stack = NULL;
  61.  
  62. private struct m_thread *
  63. alloc_mthread()
  64. {
  65.     return (struct m_thread *) emalloc(sizeof (struct m_thread));
  66. }
  67.  
  68. private void
  69. free_mthread(t)
  70. struct m_thread    *t;
  71. {
  72.     free((UnivPtr) t);
  73. }
  74.  
  75. void
  76. unwind_macro_stack()
  77. {
  78.     while (mac_stack != NULL)
  79.         pop_macro_stack();
  80. }
  81.  
  82. private void
  83. pop_macro_stack()
  84. {
  85.     register struct m_thread    *m;
  86.  
  87.     if ((m = mac_stack) == NULL)
  88.         return;
  89.     mac_stack = m->mt_prev;
  90.     free_mthread(m);
  91. }
  92.  
  93. private void
  94. push_macro_stack(m, count)
  95. register struct macro    *m;
  96. int    count;
  97. {
  98.     register struct m_thread    *t;
  99.  
  100.     for (t = mac_stack; t != NULL; t = t->mt_prev)
  101.         if (t->mt_mp == m)
  102.             complain("[Cannot execute macro recusively]");
  103.     if (count <= 0)
  104.         complain("[Cannot execute macro a negative number of times]");
  105.     t = alloc_mthread();
  106.     t->mt_prev = mac_stack;
  107.     mac_stack = t;
  108.     t->mt_offset = 0;
  109.     t->mt_mp = m;
  110.     t->mt_count = count;
  111. }
  112.  
  113. void
  114. do_macro(mac)
  115. struct macro    *mac;
  116. {
  117.     push_macro_stack(mac, arg_value());
  118. }
  119.  
  120. private struct macro    KeyMacro = {    /* Macro used for defining */
  121.     MACRO, "keyboard-macro", 0, NULL, NULL
  122. };
  123.  
  124. private int    kmac_len;
  125. private int    kmac_buflen = 0;
  126.  
  127. void
  128. mac_init()
  129. {
  130.     add_mac(&KeyMacro);
  131. }
  132.  
  133. void
  134. mac_putc(c)
  135. char    c;
  136. {
  137.     if (kmac_len >= kmac_buflen) {
  138.         KeyMacro.m_body = erealloc((UnivPtr) KeyMacro.m_body, (size_t) kmac_buflen + 16);
  139.         kmac_buflen += 16;
  140.     }
  141.     KeyMacro.m_body[kmac_len++] = c;
  142. }
  143.  
  144. void
  145. note_dispatch()
  146. {
  147.     if (kmac_len > 0)
  148.         KeyMacro.m_len = kmac_len - 1;
  149. }
  150.  
  151. bool
  152. in_macro()
  153. {
  154.     return (mac_stack != NULL);
  155. }
  156.  
  157. ZXchar
  158. mac_getc()
  159. {
  160.     struct m_thread    *mthread;
  161.     struct macro    *m;
  162.  
  163.     if ((mthread = mac_stack) == NULL)
  164.         return EOF;
  165.     m = mthread->mt_mp;
  166.     if (mthread->mt_offset == m->m_len) {
  167.         mthread->mt_offset = 0;
  168.         if (--mthread->mt_count == 0)
  169.             pop_macro_stack();
  170.         return mac_getc();
  171.     }
  172.     return ZXC(m->m_body[mthread->mt_offset++]);
  173. }
  174.  
  175. private void
  176. MacDef(m, name, len, body)
  177. struct macro    *m;    /* NULL, or def to overwrite */
  178. char    *name;    /* must be stable if m isn't NULL */
  179. int    len;
  180. char    *body;
  181. {
  182.     if (m == NULL) {
  183.         m = (struct macro *) emalloc(sizeof *m);
  184.         m->Name = name;
  185.     } else {
  186.         if (m->m_body != NULL)
  187.             free((UnivPtr) m->m_body);
  188.     }
  189.     m->m_len = len;
  190.     if (len == 0) {
  191.         m->m_body = NULL;
  192.     } else {
  193.         m->m_body = emalloc((size_t) len);
  194.         byte_copy(body, m->m_body, (size_t) len);
  195.     }
  196.     add_mac(m);
  197.     if (!InJoverc)
  198.         UnsavedMacros = YES;
  199. }
  200.  
  201. void
  202. NameMac()
  203. {
  204.     char    *name = NULL;
  205.     struct macro    *m;
  206.  
  207.     if (KeyMacro.m_len == 0)
  208.         complain("[No keyboard macro to name!]");
  209.     if (in_macro() || InMacDefine)
  210.         complain("[Can't name while defining/executing]");
  211.     if ((m = ask_macname(ProcFmt, ALLOW_OLD | ALLOW_INDEX | ALLOW_NEW)) == NULL)
  212.         name = copystr(Minibuf);
  213.     if (m == &KeyMacro)
  214.         complain("[Can't name it that!]");
  215.     MacDef(m, name, KeyMacro.m_len, KeyMacro.m_body);
  216. }
  217.  
  218. void
  219. RunMacro()
  220. {
  221.     do_macro((struct macro *) findmac(ProcFmt));
  222. }
  223.  
  224. private void
  225. pr_putc(c, fp)
  226. ZXchar    c;
  227. File    *fp;
  228. {
  229.     if (c == '\\' || c == '^') {
  230.         f_putc('\\', fp);
  231.         f_putc(c, fp);
  232.     } else {
  233.         char    buf[PPWIDTH];
  234.         char    *p;
  235.  
  236.         PPchar(c, buf);
  237.         for (p = buf; *p != '\0'; p++)
  238.             f_putc(*p, fp);
  239.     }
  240. }
  241.  
  242. void
  243. WriteMacs()
  244. {
  245.     struct macro    *m;
  246.     char
  247.         fnamebuf[FILESIZE];
  248.     File    *fp;
  249.     int    i;
  250.  
  251.     (void) ask_file((char *)NULL, (char *)NULL, fnamebuf);
  252.     fp = open_file(fnamebuf, iobuff, F_WRITE, 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(ZXC(m->m_body[i]), fp);
  259. #ifdef USE_CRLF
  260.         f_putc('\r', fp);
  261. #endif /* USE_CRLF */
  262.         f_putc(EOL, fp);
  263.     }
  264.     close_file(fp);
  265.     UnsavedMacros = NO;
  266. }
  267.  
  268. void
  269. DefKBDMac()
  270. {
  271.     struct macro    *m = ask_macname(ProcFmt,
  272.         ALLOW_OLD | ALLOW_INDEX | ALLOW_NEW);
  273.     ZXchar    c;
  274.     char
  275.         *macro_name = m == NULL? copystr(Minibuf) : m->Name,
  276.         *macro_body,
  277.         macro_buffer[LBSIZE];
  278.     int    len;
  279.  
  280.     if (m == &KeyMacro)
  281.         complain("[Can't name it that!]");
  282.     /* ??? I hope that this ask doesn't change *m! */
  283.     macro_body = ask(NullStr, ": %f %s enter body: ", macro_name);
  284.     len = 0;
  285.     while ((c = ZXC(*macro_body++)) != '\0') {
  286.         if (c == '\\' || c == '^')
  287.             c = DecodePair(c, ZXC(*macro_body++));
  288.         if (len >= LBSIZE)
  289.             complain("Macro to large");
  290.         macro_buffer[len++] = c;
  291.     }
  292.     MacDef(m, macro_name, len, macro_buffer);
  293. }
  294.  
  295. void
  296. Remember()
  297. {
  298.     /* We're already executing the macro; ignore any attempts
  299.        to define the keyboard macro while we are executing. */
  300.     if (in_macro())
  301.         return;
  302.     if (InMacDefine)
  303.         message("[Already defining ... continue with definition]");
  304.     else {
  305.         UpdModLine = YES;
  306.         InMacDefine = YES;
  307.         kmac_len = KeyMacro.m_len = 0;
  308.         message("Defining...");
  309.     }
  310. }
  311.  
  312. void
  313. Forget()
  314. {
  315.     UpdModLine = YES;
  316.     if (InMacDefine) {
  317.         message("Keyboard macro defined.");
  318.         InMacDefine = NO;
  319.     } else
  320.         complain("[end-kbd-macro: not currently defining macro!]");
  321. }
  322.  
  323. void
  324. ExecMacro()
  325. {
  326.     do_macro(&KeyMacro);
  327. }
  328.  
  329. void
  330. MacInter()
  331. {
  332.     if (Asking)
  333.         Interactive = YES;
  334. }
  335.  
  336. bool
  337. ModMacs()
  338. {
  339.     return UnsavedMacros;
  340. }
  341.  
  342. /* Ask for macro name, with completion.
  343.  * Flags is passed directly to complete.  If ALLOW_NEW is on,
  344.  * the name might be new, in which case NULL is returned and the
  345.  * actual name in in Minibuf.
  346.  */
  347.  
  348. private struct macro *
  349. ask_macname(prompt, flags)
  350. const char    *prompt;
  351. int flags;
  352. {
  353.     char    *strings[100];
  354.     register char    **strs = strings;
  355.     register int    com;
  356.     register struct macro    *m;
  357.  
  358.     for (m = macros; m != NULL; m = m->m_nextm) {
  359.         if (strs == &strings[elemsof(strings)-1])
  360.             complain("[too many macros]");
  361.         *strs++ = m->Name;
  362.     }
  363.     *strs = NULL;
  364.  
  365.     if ((com = complete(strings, (char *)NULL, prompt, flags)) < 0)
  366.         return NULL;
  367.     m = macros;
  368.     while (--com >= 0)
  369.         m = m->m_nextm;
  370.     return m;
  371. }
  372.  
  373. data_obj *
  374. findmac(prompt)
  375. const char    *prompt;
  376. {
  377.     return (data_obj *)ask_macname(prompt, ALLOW_OLD | ALLOW_INDEX);
  378. }
  379.