home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / jove / part05 / macros.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-02-02  |  8.8 KB  |  474 lines

  1. /************************************************************************
  2.  * This program is Copyright (C) 1986 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.  
  10. struct macro    *macros = 0;        /* Macros */
  11. data_obj    *LastCmd;
  12.  
  13. private
  14. add_mac(new)
  15. struct macro    *new;
  16. {
  17.     register struct macro    *mp,
  18.                 *prev = 0;
  19.  
  20.     for (mp = macros; mp != 0; prev = mp, mp = mp->m_nextm)
  21.         if (mp == new)
  22.             return;
  23.  
  24.     if (prev)
  25.         prev->m_nextm = new;
  26.     else
  27.         macros = new;
  28.     new->m_nextm = 0;
  29.     new->Type = MACRO;
  30. }
  31.  
  32. private
  33. del_mac(mac)
  34. struct macro    *mac;
  35. {
  36.     register struct macro    *m;
  37.  
  38.     for (m = macros; m != 0; m = m->m_nextm)
  39.         if (m->m_nextm == mac) {
  40.             m->m_nextm = mac->m_nextm;
  41.             break;
  42.         }
  43.     free(mac->Name);
  44.     free(mac->m_body);
  45.     free((char *) mac);
  46. }
  47.  
  48. struct macro    KeyMacro;    /* Macro used for defining */
  49.  
  50. #define NMACROS    40        /* This is bad, bad, BAD! */
  51.  
  52. struct macro    *macstack[NMACROS];
  53. private int    stackp = 0;
  54.  
  55. fix_macros()
  56. {
  57.     register int    i;
  58.     register struct macro    *mp;
  59.  
  60.     for (i = 0; macstack[i]; i++) {
  61.         mp = macstack[i];
  62.         macstack[i] = 0;
  63.         mp->m_flags = mp->m_offset = 0;
  64.     }
  65.     stackp = -1;
  66.     KeyMacro.m_flags = KeyMacro.m_offset = 0;
  67. }
  68.  
  69. private
  70. mac_err(err)
  71. char    *err;
  72. {
  73.     KeyMacro.m_flags = 0;
  74.     MacNolen(&KeyMacro);
  75.     complain(err);
  76. }
  77.  
  78. do_macro(mac)
  79. struct macro    *mac;
  80. {
  81.     if (mac->m_flags & EXECUTE)
  82.         mac_err("[Attempt to execute macro recursively!]");
  83.     if (++stackp >= NMACROS)
  84.         complain("[Too many macros at once!]");
  85.     macstack[stackp] = mac;
  86.     mac->m_offset = 0;
  87.     mac->m_ntimes = exp;
  88.     mac->m_flags |= EXECUTE;
  89. }
  90.  
  91. private
  92. MacNolen(m)
  93. struct macro    *m;
  94. {
  95.     m->m_len = m->m_offset = 0;
  96. }
  97.  
  98. private struct macro *
  99. mac_exists(name)
  100. char    *name;
  101. {
  102.     register struct macro    *mp;
  103.  
  104.     for (mp = macros; mp; mp = mp->m_nextm)
  105.         if (strcmp(mp->Name, name) == 0)
  106.             return mp;
  107.     return 0;
  108. }
  109.  
  110. mac_init()
  111. {
  112.     add_mac(&KeyMacro);
  113.     MacNolen(&KeyMacro);
  114.     KeyMacro.Name = "keyboard-macro";
  115.     KeyMacro.m_buflen = 16;
  116.     KeyMacro.m_body = emalloc(KeyMacro.m_buflen);
  117.     KeyMacro.m_ntimes = KeyMacro.m_flags = 0;
  118.     fix_macros();
  119. }
  120.  
  121. mac_putc(c)
  122. int    c;
  123. {
  124.     if (KeyMacro.m_len >= KeyMacro.m_buflen) {
  125.         KeyMacro.m_buflen += 16;
  126.         KeyMacro.m_body = realloc(KeyMacro.m_body, (unsigned) KeyMacro.m_buflen);
  127.         if (KeyMacro.m_body == 0)
  128.             mac_err("[Can't allocate storage for keyboard macro]");
  129.     }
  130.     KeyMacro.m_body[KeyMacro.m_offset++] = c;
  131.     KeyMacro.m_len++;
  132. }
  133.  
  134. in_macro()
  135. {
  136.     return ((stackp >= 0) && ((macstack[stackp])->m_flags & EXECUTE));
  137. }
  138.  
  139. mac_getc()
  140. {
  141.     struct macro    *m;
  142.  
  143.     if (stackp < 0 || ((m = macstack[stackp])->m_flags & EXECUTE) == 0)
  144.         return -1;
  145.     if (m->m_offset == m->m_len) {
  146.         m->m_offset = 0;
  147.         if (--m->m_ntimes == 0) {
  148.             m->m_flags &= ~EXECUTE;
  149.             stackp--;
  150.         }
  151.         return mac_getc();
  152.     }
  153.     return m->m_body[m->m_offset++];
  154. }
  155.  
  156. NameMac()
  157. {
  158.     char    *name;
  159.     struct macro    *m;
  160.  
  161.     if (KeyMacro.m_len == 0)
  162.         complain("[No keyboard macro to name!]");
  163.     if (KeyMacro.m_flags & (DEFINE | EXECUTE))
  164.         complain("[Can't name while defining/executing]");
  165.     if ((m = mac_exists(name = ask((char *) 0, ProcFmt))) == 0)
  166.         m = (struct macro *) emalloc(sizeof *m);
  167.     else {
  168.         if (strcmp(name, KeyMacro.Name) == 0)
  169.             complain("[Can't name it that!]");
  170.         free(m->Name);
  171.         free(m->m_body);
  172.     }
  173.     name = copystr(name);
  174.     m->Type = KeyMacro.Type;
  175.     m->m_len = KeyMacro.m_len;
  176.     m->m_buflen = KeyMacro.m_buflen;
  177.     m->m_body = emalloc(m->m_buflen);
  178.     byte_copy(KeyMacro.m_body, m->m_body, m->m_len);
  179.     m->m_ntimes = m->m_offset = 0;    /* At the beginning */
  180.     m->m_flags = SAVE;
  181.     m->Name = name;
  182.     add_mac(m);
  183. }    
  184.  
  185. RunMacro()
  186. {
  187.     struct macro    *m;
  188.  
  189.     if (m = (struct macro *) findmac(ProcFmt))
  190.         do_macro(m);
  191. }
  192.  
  193. private int    mac_fd;
  194.  
  195. private
  196. mac_io(fcn, ptr, nbytes)
  197. int    (*fcn)();
  198. char    *ptr;
  199. {
  200.     int    nio;
  201.  
  202.     if ((nio = (*fcn)(mac_fd, ptr, nbytes)) != nbytes)
  203.         complain("[Macro %s error: %d got %d]",
  204.              (fcn == read) ? "read" : "write",
  205.              nbytes,
  206.              nio);
  207. }
  208.  
  209. WriteMacs()
  210. {
  211.     struct macro    *m;
  212.     int    namelen,
  213.         netl,
  214.         nmacs = 0;
  215.     char    *file,
  216.         filebuf[FILESIZE];
  217.     long htonl() ;
  218.  
  219.     file = ask_file((char *) 0, (char *) 0, filebuf);
  220.     if ((mac_fd = creat(file, 0666)) == -1)
  221.         complain(IOerr("create", file));
  222.     f_mess("\"%s\"", file);
  223.  
  224.     /* Don't write the keyboard macro which is always the first */
  225.     for (m = macros->m_nextm; m != 0; m = m->m_nextm) {
  226.         if (m->m_len == 0)
  227.             continue;
  228.         nmacs++;
  229.         netl = htonl(m->m_len);
  230.         mac_io(write, (char *) &netl, sizeof m->m_len);
  231.         namelen = strlen(m->Name) + 1;    /* Including the null */
  232.         netl = htonl(namelen);
  233.         mac_io(write, (char *) &netl, sizeof namelen);
  234.         mac_io(write, m->Name, namelen);
  235.         mac_io(write, m->m_body, m->m_len);
  236.         m->m_flags &= ~SAVE;
  237.     }
  238.     (void) close(mac_fd);
  239.     add_mess(" %d macro%n saved.", nmacs, nmacs);
  240. }
  241.  
  242. #define NEWWAY    1
  243. #define OLDWAY    0
  244.  
  245. private int    int_how = NEWWAY;
  246.  
  247. /* Formatting int's the old way or the new "improved" way? */
  248.  
  249. #if vax || pdp11
  250. long htonl(x)
  251. register long x;
  252. {
  253.     return(    (((x >>  0) & 0377) << 24) |
  254.         (((x >>  8) & 0377) << 16) |
  255.         (((x >> 16) & 0377) <<  8) |
  256.         (((x >> 24) & 0377) <<  0) );
  257. }
  258.  
  259. short htons(x)
  260. register short x;
  261. {
  262.     return(    (((x >>  0) & 0377) << 8) |
  263.         (((x >>  8) & 0377) << 0) );
  264. }
  265.  
  266. long ntohl(x)
  267. register long x;
  268. {
  269.     return(    (((x >>  0) & 0377) << 24) |
  270.         (((x >>  8) & 0377) << 16) |
  271.         (((x >> 16) & 0377) <<  8) |
  272.         (((x >> 24) & 0377) <<  0) );
  273. }
  274.  
  275. short ntohs(x)
  276. register short x;
  277. {
  278.     return(    (((x >>  0) & 0377) << 8) |
  279.         (((x >>  8) & 0377) << 0) );
  280. }
  281. #else
  282. long htonl(x)
  283. register long x;
  284. {
  285.     return(x);
  286. }
  287.  
  288. short htons(x)
  289. register short x;
  290. {
  291.     return(x);
  292. }
  293.  
  294. long ntohl(x)
  295. register long x;
  296. {
  297.     return(x);
  298. }
  299.  
  300. short ntohs(x)
  301. register short x;
  302. {
  303.     return(x);
  304. }
  305. #endif
  306.  
  307. int_fmt(i)
  308. {
  309.     if (int_how == NEWWAY)
  310.         return ntohl(i);
  311.     return i;
  312. }
  313.  
  314. ReadMacs()
  315. {
  316.     char    *file,
  317.         filebuf[FILESIZE];
  318.     struct macro    *m;
  319.     int    nmacs = 0,
  320.         namelen,
  321.         bodylen,
  322.         tmp,
  323.         he_is_sure = 0,
  324.         save_em = FALSE;
  325.  
  326.     file = ask_file((char *) 0, (char *) 0, filebuf);
  327.     if ((mac_fd = open(file, 0)) == -1)
  328.         complain(IOerr("open", file));
  329.  
  330.     f_mess("\"%s\"", file);
  331.     while (read(mac_fd, (char *) &tmp, sizeof tmp) == (sizeof tmp)) {
  332. retry:        bodylen = int_fmt(tmp);
  333.         if (!he_is_sure && (bodylen <= 0 || bodylen > 10000)) {
  334.             if (int_how == NEWWAY) {
  335.                 int_how = OLDWAY;
  336.                 save_em = TRUE;
  337.                 goto retry;
  338.             } else {
  339.                 confirm("Are you sure \"%s\" is a JOVE macro file? ", filebuf);
  340.                 he_is_sure = 1;
  341.             }
  342.         }
  343.         nmacs++;
  344.         m = (struct macro *) emalloc (sizeof *m);
  345.         m->m_flags = 0;
  346.         m->m_len = bodylen;
  347.         m->m_buflen = m->m_len;
  348.         mac_io(read, (char *) &namelen, sizeof namelen);
  349.         namelen = int_fmt(namelen);
  350.         m->Name = emalloc(namelen);
  351.         mac_io(read, m->Name, namelen);
  352.         m->m_body = emalloc(m->m_buflen);
  353.         mac_io(read, m->m_body, m->m_len);
  354.         add_mac(m);
  355.     }
  356.     (void) close(mac_fd);
  357.     add_mess(" %d macro%n defined.", nmacs, nmacs);
  358.     if (save_em) {
  359.         char    *msg = "OK to convert to the new format? ",
  360.             ibuf[FILESIZE + 1];
  361.  
  362.         if (!InJoverc) {
  363.             TOstart("Warning", TRUE);
  364.             Typeout("Warning: your macros file is in the old format.");
  365.             Typeout("Do you want me to convert \"%s\" to the new", pr_name(file));
  366.             Typeout("format?");
  367.             f_mess(msg);
  368.             TOstop();
  369.             confirm(msg);
  370.         }
  371.         /* WriteMacs requests a file name.  This is what it'll get. */
  372.         sprintf(ibuf, "%s\n", file);
  373.         Inputp = ibuf;
  374.         WriteMacs();
  375.     }        
  376. }
  377.  
  378. Remember()
  379. {
  380.     if (KeyMacro.m_flags & EXECUTE)
  381.         /* We're already executing the macro; ignore any attempts
  382.            to define the keyboard macro while we are executing. */
  383.         return;
  384.     if (KeyMacro.m_flags & DEFINE)
  385.         message("[Already remembering ... continue with definition]");
  386.     else {
  387.         UpdModLine++;
  388.         KeyMacro.m_flags |= DEFINE;
  389.         MacNolen(&KeyMacro);
  390.         message("Remembering...");
  391.     }
  392. }
  393.  
  394. /* Is `c' a prefix character */
  395.  
  396. private
  397. PrefChar(c)
  398. {
  399.     return (int) IsPrefix(mainmap[c]);
  400. }
  401.  
  402. Forget()
  403. {
  404.     char    *cp;
  405.     struct macro    *m = &KeyMacro;
  406.  
  407.     UpdModLine++;
  408.     if (m->m_flags & DEFINE) {
  409.         message("Keyboard macro defined.");
  410.         m->m_flags &= ~DEFINE;
  411.         cp = &m->m_body[m->m_len - 2];
  412.         if (PrefChar(*cp))
  413.             m->m_len -= 2;
  414.         else if (commands[*++cp].c_proc == Forget)
  415.             m->m_len--;
  416.     }
  417. }
  418.  
  419. ExecMacro()
  420. {
  421.     do_macro(&KeyMacro);
  422. }
  423.  
  424. MacInter()
  425. {
  426.     extern int    Interactive;
  427.  
  428.     if (!Asking)
  429.         return;
  430.     Interactive = 1;
  431. }
  432.  
  433. ModMacs()
  434. {
  435.     register struct macro    *m;
  436.  
  437.     for (m = macros->m_nextm; m != 0; m = m->m_nextm)
  438.         if (m->m_flags & SAVE)
  439.             return 1;
  440.     return 0;
  441. }
  442.  
  443. data_obj *
  444. findmac(prompt)
  445. char    *prompt;
  446. {
  447.     char    *strings[100];
  448.     register char    **strs = strings;
  449.     register int    com;
  450.     register struct macro    *m = macros;
  451.  
  452.     for (; m != 0; m = m->m_nextm)
  453.         *strs++ = m->Name;
  454.     *strs = 0;
  455.  
  456.     if ((com = complete(strings, prompt, NOTHING)) < 0)
  457.         return 0;
  458.     m = macros;
  459.     while (--com >= 0)
  460.         m = m->m_nextm;
  461.     return (data_obj *) m;
  462. }
  463.  
  464. DelMacro()
  465. {
  466.     struct macro    *m;
  467.  
  468.     if ((m = (struct macro *) findmac(ProcFmt)) == 0)
  469.         return;
  470.     if (m == &KeyMacro)
  471.         complain("[It's illegal to delete the keyboard-macro!]");
  472.     del_mac(m);
  473. }
  474.