home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / util.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  17KB  |  1,050 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 "termcap.h"
  11. #include "disp.h"
  12. #include "fp.h"
  13. #include <signal.h>
  14. #include <errno.h>
  15.  
  16. #ifdef    MAC
  17. # include "mac.h"
  18. #else
  19. # ifdef    STDARGS
  20. #  include <stdarg.h>
  21. # else
  22. #  include <varargs.h>
  23. # endif
  24. #endif
  25.  
  26. #ifdef    MSDOS
  27. #include <time.h>
  28. #endif
  29.  
  30. #ifndef IBMPC
  31. const
  32. #endif
  33. struct cmd *
  34. FindCmd(proc)
  35. register void    (*proc) proto((void));
  36. {
  37.     register const struct cmd    *cp;
  38.  
  39.     for (cp = commands; cp->Name; cp++)
  40.         if (cp->c_proc == proc)
  41.             return cp;
  42.     return NULL;
  43. }
  44.  
  45. bool    Interactive = NO;    /* True when we invoke with the command handler? */
  46. data_obj    *LastCmd;
  47. char    *ProcFmt = ": %f ";
  48.  
  49. void
  50. ExecCmd(cp)
  51. register data_obj    *cp;
  52. {
  53.     LastCmd = cp;
  54.     if (cp->Type & MAJOR_MODE) {
  55.         SetMajor((cp->Type >> 8));
  56.     } else if (cp->Type & MINOR_MODE) {
  57.         TogMinor((cp->Type >> 8));
  58.     } else    switch (cp->Type&TYPEMASK) {
  59.         case MACRO:
  60.             do_macro((struct macro *) cp);
  61.             break;
  62.  
  63.         case FUNCTION:
  64.             {
  65.             register struct cmd    *cmd = (struct cmd *) cp;
  66.  
  67.             if (cmd->c_proc) {
  68.                 if ((cmd->Type & MODIFIER) &&
  69.                     (BufMinorMode(curbuf, ReadOnly))) {
  70.                     rbell();
  71.                     message("[Buffer is read-only]");
  72.                 } else
  73.                     (*cmd->c_proc)();
  74.             }
  75.             }
  76.     }
  77. }
  78.  
  79. Line *
  80. lastline(lp)
  81. register Line    *lp;
  82. {
  83.     register Line    *next;
  84.  
  85.     while ((next = lp->l_next) != NULL)
  86.         lp = next;
  87.     return lp;
  88. }
  89.  
  90. char    key_strokes[100],
  91.     *keys_p = key_strokes;
  92.  
  93. void
  94. pp_key_strokes(buffer, size)
  95. char    *buffer;
  96. size_t    size;
  97. {
  98.     char    *buf_end = buffer + size - 1,
  99.         *kp = key_strokes,
  100.         c;
  101.  
  102.     *buffer = '\0';
  103.     while ((c = *kp++) != '\0') {
  104.         swritef(buffer, (size_t) (buf_end-buffer), "%p ", c);
  105.         buffer += strlen(buffer);
  106.         if (buffer >= buf_end)
  107.             break;
  108.     }
  109. }
  110.  
  111. private int    *slowp = NULL;    /* for waitchar() */
  112.  
  113. private SIGRESULT
  114. slowpoke(junk)
  115. int    junk;
  116. {
  117.     int save_errno = errno;    /* Subtle, but necessary! */
  118.     char    buffer[100];
  119.  
  120.     if (slowp)
  121.         *slowp = YES;
  122.     pp_key_strokes(buffer, sizeof (buffer));
  123.     f_mess(buffer);
  124.     errno = save_errno;
  125.     SIGRETURN;
  126. }
  127.  
  128. #ifdef    UNIX
  129. # ifdef    BSD4_2
  130. #  define N_SEC    1    /* will be precisely 1 second on 4.2 */
  131. # else
  132. #  define N_SEC    2    /* but from 1 to 2 seconds otherwise */
  133. # endif
  134. #else    /* !UNIX */
  135. # define N_SEC    1
  136. int in_macro();
  137. #endif    /* !UNIX */
  138.  
  139. int
  140. waitchar(slow)
  141. int    *slow;
  142. {
  143.     int    c;
  144. #ifdef    UNIX
  145.     unsigned int    old_time;
  146.     SIGRESULT    (*oldproc) proto((int));
  147. #else    /* !UNIX */
  148.     long sw, time();
  149. #endif    /* !UNIX */
  150.  
  151.     slowp = slow;
  152.  
  153.     if (in_macro())        /* make macros faster ... */
  154.         return getch();
  155.  
  156.     /* If slow is a valid pointer and it's value is yes, then
  157.        we know we have already been slow during this sequence,
  158.        so we just wait for the character and then echo it. */
  159.     if (slow != NULL && *slow == YES) {
  160.         c = getch();
  161.         slowpoke(0);
  162.         return c;
  163.     }
  164. #ifdef    UNIX
  165.     oldproc = signal(SIGALRM, slowpoke);
  166.  
  167.     if ((old_time = alarm((unsigned) N_SEC)) == 0)
  168.         old_time = UpdFreq;
  169.     c = getch();
  170.     (void) alarm(old_time);
  171.     (void) signal(SIGALRM, oldproc);
  172.  
  173.     if (slow != NULL && *slow == YES)
  174.         slowpoke(0);
  175.     return c;
  176.  
  177. #else    /* !UNIX */
  178. #ifdef    MAC
  179.     Keyonly = YES;
  180.     if (charp() || in_macro()) {
  181.         c = getch();    /* to avoid flicker */
  182.         if (slow != NULL && *slow == YES)
  183.             slowpoke();
  184.         return c;
  185.     }
  186. #endif
  187.     time(&sw);
  188.     sw += N_SEC;
  189.     while (time(NULL) <= sw)
  190.         if (charp() || in_macro())
  191.             return getch();
  192. #ifdef    MAC
  193.     menus_off();
  194. #endif
  195.     slowpoke();
  196.     c = getch();
  197.     slowpoke();
  198.  
  199.     return c;
  200. #endif    /* !UNIX */
  201. }
  202.  
  203. char *
  204. StrIndex(dir, buf, charpos, what)
  205. int    dir;    /* FORWARD or BACKWARD */
  206. register char    *buf;
  207. int    charpos;
  208. register int    what;
  209. {
  210.     register char    *cp = &buf[charpos];
  211.     register int    c;
  212.  
  213.     if (dir > 0) {
  214.         while ((c = *cp++) != '\0')
  215.             if ((c == what) != '\0')
  216.                 return (cp - 1);
  217.     } else {
  218.         while (cp >= buf && (c = *cp--)!='\0')
  219.             if (c == what)
  220.                 return (cp + 1);
  221.     }
  222.     return NULL;
  223. }
  224.  
  225. bool
  226. blnkp(buf)
  227. register char    *buf;
  228. {
  229.     register char    c;
  230.  
  231.     do ; while ((c = *buf++)!='\0' && (c == ' ' || c == '\t'));
  232.     return c == 0;    /* It's zero if we got to the end of the Line */
  233. }
  234.  
  235. bool
  236. within_indent()
  237. {
  238.     register char    c;
  239.     register int    i;
  240.  
  241.     i = curchar;
  242.     do ; while (--i >= 0 && ((c = linebuf[i]) == ' ' || c == '\t'));
  243.     return i < 0;        /* it's < 0 if we got to the beginning */
  244. }
  245.  
  246. Line *
  247. next_line(line, num)
  248. register Line    *line;
  249. register int    num;
  250. {
  251.     if (num < 0)
  252.         return prev_line(line, -num);
  253.     if (line)
  254.         while (--num >= 0 && line->l_next != NULL)
  255.             line = line->l_next;
  256.     return line;
  257. }
  258.  
  259. Line *
  260. prev_line(line, num)
  261. register Line    *line;
  262. register int    num;
  263. {
  264.     if (num < 0)
  265.         return next_line(line, -num);
  266.     if (line)
  267.         while (--num >= 0 && line->l_prev != NULL)
  268.             line = line->l_prev;
  269.     return line;
  270. }
  271.  
  272. void
  273. DotTo(line, col)
  274. Line    *line;
  275. int    col;
  276. {
  277.     Bufpos    bp;
  278.  
  279.     bp.p_line = line;
  280.     bp.p_char = col;
  281.     SetDot(&bp);
  282. }
  283.  
  284. /* If bp->p_line is != current line, then save current line.  Then set dot
  285.    to bp->p_line, and if they weren't equal get that line into linebuf.  */
  286.  
  287. void
  288. SetDot(bp)
  289. register Bufpos    *bp;
  290. {
  291.     register int    notequal;
  292.  
  293.     if (bp == NULL)
  294.         return;
  295.  
  296.     notequal = bp->p_line != curline;
  297.     if (notequal)
  298.         lsave();
  299.     if (bp->p_line)
  300.         curline = bp->p_line;
  301.     if (notequal)
  302.         getDOT();
  303.     curchar = bp->p_char;
  304.     if (curchar > length(curline))
  305.         curchar = length(curline);
  306. }
  307.  
  308. void
  309. ToLast()
  310. {
  311.     SetLine(curbuf->b_last);
  312.     Eol();
  313. }
  314.  
  315. int    MarkThresh = 22;    /* average screen size ... */
  316. static int    line_diff;
  317.  
  318. int
  319. LineDist(nextp, endp)
  320. register Line    *nextp,
  321.         *endp;
  322. {
  323.     (void) inorder(nextp, 0, endp, 0);
  324.     return line_diff;
  325. }
  326.  
  327. int
  328. inorder(nextp, char1, endp, char2)
  329. register Line    *nextp,
  330.         *endp;
  331. int    char1,
  332.     char2;
  333. {
  334.     register Line    *prevp = nextp;
  335.  
  336.     line_diff = 0;
  337.     if (nextp == endp)
  338.         return char1 < char2;
  339.  
  340.     while (nextp && prevp) {
  341.         nextp = nextp->l_next;
  342.         prevp = prevp->l_prev;
  343.         line_diff += 1;
  344.         if (nextp == endp)
  345.             return TRUE;
  346.         if (prevp == endp)
  347.             return FALSE;
  348.     }
  349.     while (nextp!=NULL && nextp!=endp) {
  350.         nextp = nextp->l_next;
  351.         line_diff += 1;
  352.     }
  353.     while (prevp!=NULL && prevp!=endp) {
  354.         prevp = prevp->l_prev;
  355.         line_diff += 1;
  356.     }
  357.     /* nextp == prevp implies both are NULL: the lines are not ordered */
  358.     return nextp==prevp? -1 : nextp==endp;
  359. }
  360.  
  361. void
  362. PushPntp(line)
  363. register Line    *line;
  364. {
  365.     if (LineDist(curline, line) >= MarkThresh)
  366.         set_mark();
  367. }
  368.  
  369. void
  370. ToFirst()
  371. {
  372.     SetLine(curbuf->b_first);
  373. }
  374.  
  375. int
  376. length(line)
  377. Line    *line;
  378. {
  379.     return strlen(lcontents(line));
  380. }
  381.  
  382. void
  383. to_word(dir)
  384. register int    dir;
  385. {
  386.     register char    c;
  387.  
  388.     if (dir == FORWARD) {
  389.         while ((c = linebuf[curchar]) != '\0' && !jisword(c))
  390.             curchar += 1;
  391.         if (eolp()) {
  392.             if (curline->l_next == NULL)
  393.                 return;
  394.             SetLine(curline->l_next);
  395.             to_word(dir);
  396.             return;
  397.         }
  398.     } else {
  399.         while (!bolp() && (c = linebuf[curchar - 1], !jisword(c)))
  400.             curchar -= 1;
  401.         if (bolp()) {
  402.             if (curline->l_prev == NULL)
  403.                 return;
  404.             SetLine(curline->l_prev);
  405.             Eol();
  406.             to_word(dir);
  407.         }
  408.     }
  409. }
  410.  
  411. /* Are there any modified buffers?  Allp means include B_PROCESS
  412.    buffers in the check. */
  413.  
  414. bool
  415. ModBufs(allp)
  416. bool    allp;
  417. {
  418.     register Buffer    *b;
  419.  
  420.     for (b = world; b != NULL; b = b->b_next)
  421.         if (b->b_type != B_SCRATCH
  422.         && (b->b_type == B_FILE || allp)
  423.         && IsModified(b))
  424.             return YES;
  425.     return NO;
  426. }
  427.  
  428. char *
  429. filename(b)
  430. register Buffer    *b;
  431. {
  432.     return b->b_fname ? pr_name(b->b_fname, YES) : "[No file]";
  433. }
  434.  
  435. char *
  436. itoa(num)
  437. register int    num;
  438. {
  439.     static char    line[15];
  440.  
  441.     swritef(line, sizeof(line), "%d", num);
  442.     return line;
  443. }
  444.  
  445. int
  446. min(a, b)
  447. register int    a,
  448.         b;
  449. {
  450.     return (a < b) ? a : b;
  451. }
  452.  
  453. int
  454. max(a, b)
  455. register int    a,
  456.         b;
  457. {
  458.     return (a > b) ? a : b;
  459. }
  460.  
  461. void
  462. tiewind(w, bp)
  463. register Window    *w;
  464. register Buffer    *bp;
  465. {
  466.     int    not_tied = (w->w_bufp != bp);
  467.  
  468.     UpdModLine = YES;    /* kludge ... but speeds things up considerably */
  469.     w->w_line = bp->b_dot;
  470.     w->w_char = bp->b_char;
  471.     w->w_bufp = bp;
  472.     if (not_tied)
  473.         CalcWind(w);    /* ah, this has been missing since the
  474.                    beginning of time! */
  475. }
  476.  
  477. char *
  478. lcontents(line)
  479. registe