home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / Editors / mjovesrc.zoo / util.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  17KB  |  1,045 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. #define HAVE_STRERROR 1
  16.  
  17. #ifdef    MAC
  18. # include "mac.h"
  19. #else
  20. # ifdef    STDARGS
  21. #  include <stdarg.h>
  22. # else
  23. #  include <varargs.h>
  24. # endif
  25. #endif
  26.  
  27. #ifdef    MSDOS
  28. #include <time.h>
  29. #endif
  30.  
  31. const struct cmd *
  32. FindCmd(proc)
  33. register void    (*proc) proto((void));
  34. {
  35.     register const struct cmd    *cp;
  36.  
  37.     for (cp = commands; cp->Name; cp++)
  38.         if (cp->c_proc == proc)
  39.             return cp;
  40.     return NULL;
  41. }
  42.  
  43. bool    Interactive = NO;    /* True when we invoke with the command handler? */
  44. data_obj    *LastCmd;
  45. char    *ProcFmt = ": %f ";
  46.  
  47. void
  48. ExecCmd(cp)
  49. register data_obj    *cp;
  50. {
  51.     LastCmd = cp;
  52.     if (cp->Type & MAJOR_MODE) {
  53.         SetMajor((cp->Type >> 8));
  54.     } else if (cp->Type & MINOR_MODE) {
  55.         TogMinor((cp->Type >> 8));
  56.     } else    switch (cp->Type&TYPEMASK) {
  57.         case MACRO:
  58.             do_macro((struct macro *) cp);
  59.             break;
  60.  
  61.         case FUNCTION:
  62.             {
  63.             register struct cmd    *cmd = (struct cmd *) cp;
  64.  
  65.             if (cmd->c_proc) {
  66.                 if ((cmd->Type & MODIFIER) &&
  67.                     (BufMinorMode(curbuf, ReadOnly))) {
  68.                     rbell();
  69.                     message("[Buffer is read-only]");
  70.                 } else
  71.                     (*cmd->c_proc)();
  72.             }
  73.             }
  74.     }
  75. }
  76.  
  77. Line *
  78. lastline(lp)
  79. register Line    *lp;
  80. {
  81.     register Line    *next;
  82.  
  83.     while ((next = lp->l_next) != NULL)
  84.         lp = next;
  85.     return lp;
  86. }
  87.  
  88. char    key_strokes[100],
  89.     *keys_p = key_strokes;
  90.  
  91. void
  92. pp_key_strokes(buffer, size)
  93. char    *buffer;
  94. size_t    size;
  95. {
  96.     char    *buf_end = buffer + size - 1,
  97.         *kp = key_strokes,
  98.         c;
  99.  
  100.     *buffer = '\0';
  101.     while ((c = *kp++) != '\0') {
  102.         swritef(buffer, (size_t) (buf_end-buffer), "%p ", c);
  103.         buffer += strlen(buffer);
  104.         if (buffer >= buf_end)
  105.             break;
  106.     }
  107. }
  108.  
  109. private int    *slowp = NULL;    /* for waitchar() */
  110.  
  111. private SIGRESULT
  112. slowpoke(junk)
  113. int    junk;
  114. {
  115.     int save_errno = errno;    /* Subtle, but necessary! */
  116.     char    buffer[100];
  117.  
  118.     if (slowp)
  119.         *slowp = YES;
  120.     pp_key_strokes(buffer, sizeof (buffer));
  121.     f_mess(buffer);
  122.     errno = save_errno;
  123.     SIGRETURN;
  124. }
  125.  
  126. #ifdef    UNIX
  127. # ifdef    BSD4_2
  128. #  define N_SEC    1    /* will be precisely 1 second on 4.2 */
  129. # else
  130. #  define N_SEC    2    /* but from 1 to 2 seconds otherwise */
  131. # endif
  132. #else    /* !UNIX */
  133. # define N_SEC    1
  134. int in_macro();
  135. #endif    /* !UNIX */
  136.  
  137. int
  138. waitchar(slow)
  139. int    *slow;
  140. {
  141.     int    c;
  142. #ifdef    UNIX
  143.     unsigned int    old_time;
  144.     SIGRESULT    (*oldproc) proto((int));
  145. #else    /* !UNIX */
  146.     long sw, time();
  147. #endif    /* !UNIX */
  148.  
  149.     slowp = slow;
  150.  
  151.     if (in_macro())        /* make macros faster ... */
  152.         return getch();
  153.  
  154.     /* If slow is a valid pointer and it's value is yes, then
  155.        we know we have already been slow during this sequence,
  156.        so we just wait for the character and then echo it. */
  157.     if (slow != NULL && *slow == YES) {
  158.         c = getch();
  159.         slowpoke(0);
  160.         return c;
  161.     }
  162. #ifdef    UNIX
  163.     oldproc = signal(SIGALRM, slowpoke);
  164.  
  165.     if ((old_time = alarm((unsigned) N_SEC)) == 0)
  166.         old_time = UpdFreq;
  167.     c = getch();
  168.     (void) alarm(old_time);
  169.     (void) signal(SIGALRM, oldproc);
  170.  
  171.     if (slow != NULL && *slow == YES)
  172.         slowpoke(0);
  173.     return c;
  174.  
  175. #else    /* !UNIX */
  176. #ifdef    MAC
  177.     Keyonly = YES;
  178.     if (charp() || in_macro()) {
  179.         c = getch();    /* to avoid flicker */
  180.         if (slow != NULL && *slow == YES)
  181.             slowpoke();
  182.         return c;
  183.     }
  184. #endif
  185.     time(&sw);
  186.     sw += N_SEC;
  187.     while (time(NULL) <= sw)
  188.         if (charp() || in_macro())
  189.             return getch();
  190. #ifdef    MAC
  191.     menus_off();
  192. #endif
  193.     slowpoke();
  194.     c = getch();
  195.     slowpoke();
  196.  
  197.     return c;
  198. #endif    /* !UNIX */
  199. }
  200.  
  201. char *
  202. StrIndex(dir, buf, charpos, what)
  203. int    dir;    /* FORWARD or BACKWARD */
  204. register char    *buf;
  205. int    charpos;
  206. register int    what;
  207. {
  208.     register char    *cp = &buf[charpos];
  209.     register int    c;
  210.  
  211.     if (dir > 0) {
  212.         while ((c = *cp++) != '\0')
  213.             if ((c == what) != '\0')
  214.                 return (cp - 1);
  215.     } else {
  216.         while (cp >= buf && (c = *cp--)!='\0')
  217.             if (c == what)
  218.                 return (cp + 1);
  219.     }
  220.     return NULL;
  221. }
  222.  
  223. bool
  224. blnkp(buf)
  225. register char    *buf;
  226. {
  227.     register char    c;
  228.  
  229.     do ; while ((c = *buf++)!='\0' && (c == ' ' || c == '\t'));
  230.     return c == 0;    /* It's zero if we got to the end of the Line */
  231. }
  232.  
  233. bool
  234. within_indent()
  235. {
  236.     register char    c;
  237.     register int    i;
  238.  
  239.     i = curchar;
  240.     do ; while (--i >= 0 && ((c = linebuf[i]) == ' ' || c == '\t'));
  241.     return i < 0;        /* it's < 0 if we got to the beginning */
  242. }
  243.  
  244. Line *
  245. next_line(line, num)
  246. register Line    *line;
  247. register int    num;
  248. {
  249.     if (num < 0)
  250.         return prev_line(line, -num);
  251.     if (line)
  252.         while (--num >= 0 && line->l_next != NULL)
  253.             line = line->l_next;
  254.     return line;
  255. }
  256.  
  257. Line *
  258. prev_line(line, num)
  259. register Line    *line;
  260. register int    num;
  261. {
  262.     if (num < 0)
  263.         return next_line(line, -num);
  264.     if (line)
  265.         while (--num >= 0 && line->l_prev != NULL)
  266.             line = line->l_prev;
  267.     return line;
  268. }
  269.  
  270. void
  271. DotTo(line, col)
  272. Line    *line;
  273. int    col;
  274. {
  275.     Bufpos    bp;
  276.  
  277.     bp.p_line = line;
  278.     bp.p_char = col;
  279.     SetDot(&bp);
  280. }
  281.  
  282. /* If bp->p_line is != current line, then save current line.  Then set dot
  283.    to bp->p_line, and if they weren't equal get that line into linebuf.  */
  284.  
  285. void
  286. SetDot(bp)
  287. register Bufpos    *bp;
  288. {
  289.     register int    notequal;
  290.  
  291.     if (bp == NULL)
  292.         return;
  293.  
  294.     notequal = bp->p_line != curline;
  295.     if (notequal)
  296.         lsave();
  297.     if (bp->p_line)
  298.         curline = bp->p_line;
  299.     if (notequal)
  300.         getDOT();
  301.     curchar = bp->p_char;
  302.     if (curchar > length(curline))
  303.         curchar = length(curline);
  304. }
  305.  
  306. void
  307. ToLast()
  308. {
  309.     SetLine(curbuf->b_last);
  310.     Eol();
  311. }
  312.  
  313. int    MarkThresh = 22;    /* average screen size ... */
  314. static int    line_diff;
  315.  
  316. int
  317. LineDist(nextp, endp)
  318. register Line    *nextp,
  319.         *endp;
  320. {
  321.     (void) inorder(nextp, 0, endp, 0);
  322.     return line_diff;
  323. }
  324.  
  325. int
  326. inorder(nextp, char1, endp, char2)
  327. register Line    *nextp,
  328.         *endp;
  329. int    char1,
  330.     char2;
  331. {
  332.     register Line    *prevp = nextp;
  333.  
  334.     line_diff = 0;
  335.     if (nextp == endp)
  336.         return char1 < char2;
  337.  
  338.     while (nextp && prevp) {
  339.         nextp = nextp->l_next;
  340.         prevp = prevp->l_prev;
  341.         line_diff += 1;
  342.         if (nextp == endp)
  343.             return TRUE;
  344.         if (prevp == endp)
  345.             return FALSE;
  346.     }
  347.     while (nextp!=NULL && nextp!=endp) {
  348.         nextp = nextp->l_next;
  349.         line_diff += 1;
  350.     }
  351.     while (prevp!=NULL && prevp!=endp) {
  352.         prevp = prevp->l_prev;
  353.         line_diff += 1;
  354.     }
  355.     /* nextp == prevp implies both are NULL: the lines are not ordered */
  356.     return nextp==prevp? -1 : nextp==endp;
  357. }
  358.  
  359. void
  360. PushPntp(line)
  361. register Line    *line;
  362. {
  363.     if (LineDist(curline, line) >= MarkThresh)
  364.         set_mark();
  365. }
  366.  
  367. void
  368. ToFirst()
  369. {
  370.     SetLine(curbuf->b_first);
  371. }
  372.  
  373. int
  374. length(line)
  375. Line    *line;
  376. {
  377.     return strlen(lcontents(line));
  378. }
  379.  
  380. void
  381. to_word(dir)
  382. register int    dir;
  383. {
  384.     register char    c;
  385.  
  386.     if (dir == FORWARD) {
  387.         while ((c = linebuf[curchar]) != '\0' && !jisword(c))
  388.             curchar += 1;
  389.         if (eolp()) {
  390.             if (curline->l_next == NULL)
  391.                 return;
  392.             SetLine(curline->l_next);
  393.             to_word(dir);
  394.             return;
  395.         }
  396.     } else {
  397.         while (!bolp() && (c = linebuf[curchar - 1], !jisword(c)))
  398.             curchar -= 1;
  399.         if (bolp()) {
  400.             if (curline->l_prev == NULL)
  401.                 return;
  402.             SetLine(curline->l_prev);
  403.             Eol();
  404.             to_word(dir);
  405.         }
  406.     }
  407. }
  408.  
  409. /* Are there any modified buffers?  Allp means include B_PROCESS
  410.    buffers in the check. */
  411.  
  412. bool
  413. ModBufs(allp)
  414. bool    allp;
  415. {
  416.     register Buffer    *b;
  417.  
  418.     for (b = world; b != NULL; b = b->b_next)
  419.         if (b->b_type != B_SCRATCH
  420.         && (b->b_type == B_FILE || allp)
  421.         && IsModified(b))
  422.             return YES;
  423.     return NO;
  424. }
  425.  
  426. char *
  427. filename(b)
  428. register Buffer    *b;
  429. {
  430.     return b->b_fname ? pr_name(b->b_fname, YES) : "[No file]";
  431. }
  432.  
  433. char *
  434. itoa(num)
  435. register int    num;
  436. {
  437.     static char    line[15];
  438.  
  439.     swritef(line, sizeof(line), "%d", num);
  440.     return line;
  441. }
  442.  
  443. int
  444. min(a, b)
  445. register int    a,
  446.         b;
  447. {
  448.     return (a < b) ? a : b;
  449. }
  450.  
  451. int
  452. max(a, b)
  453. register int    a,
  454.         b;
  455. {
  456.     return (a > b) ? a : b;
  457. }
  458.  
  459. void
  460. tiewind(w, bp)
  461. register Window    *w;
  462. register Buffer    *bp;
  463. {
  464.     int    not_tied = (w->w_bufp != bp);
  465.  
  466.     UpdModLine = YES;    /* kludge ... but speeds things up considerably */
  467.     w->w_line = bp->b_dot;
  468.     w->w_char = bp->b_char;
  469.     w->w_bufp = bp;
  470.     if (not_tied)
  471.         CalcWind(w);    /* ah, this has been missing since the
  472.                    beginning of time! */
  473. }
  474.  
  475. char *
  476. lcontents(line)
  477. register Line    *line;
  478. {
  479.     if (line == curline)
  480.         return linebuf;
  481.     else
  482.         return lbptr(line);
  483. }
  484.  
  485. char *
  486. ltobuf(line, buf)
  487. Line    *line;
  488. char    *buf;
  489. {
  490.     if (line == curline) {
  491.         if (buf != linebuf)
  492.             strcpy(buf, linebuf);
  493.         Jr_Len = strlen(linebuf);
  494.     } else
  495.         getline(line->l_dline, buf);
  496.     return buf;
  497. }
  498.  
  499. void
  500. DOTsave(buf)
  501. Bufpos *buf;
  502. {
  503.     buf->p_line = curline;
  504.     buf->p_char = curchar;
  505. }
  506.  
  507. /* Return none-zero if we had to rearrange the order. */
  508.  
  509. bool
  510. fixorder(line1, char1, line2, char2)
  511. register Line    **line1,
  512.         **line2;
  513. register int    *char1,
  514.         *char2;
  515. {
  516.     Line    *tline;
  517.     int    tchar;
  518.  
  519.     if (inorder(*line1, *char1, *line2, *char2))
  520.         return NO;
  521.  
  522.     tline = *line1;
  523.     tchar = *char1;
  524.     *line1 = *line2;
  525.     *char1 = *char2;
  526.     *line2 = tline;
  527.     *char2 = tchar;
  528.  
  529.     return YES;
  530. }
  531.  
  532. bool
  533. inlist(first, what)
  534. register Line    *first,
  535.         *what;
  536. {
  537.     while (first) {
  538.         if (first == what)
  539.             return YES;
  540.         first = first->l_next;
  541.     }
  542.     return NO;
  543. }
  544.  
  545. /* Make `buf' (un)modified and tell the redisplay code to update the modeline
  546.    if it will need to be changed. */
  547.  
  548. int    ModCount = 0;
  549.  
  550. void
  551. modify()
  552. {
  553.     if (!curbuf->b_modified) {
  554.         UpdModLine = YES;
  555.         curbuf->b_modified = YES;
  556.     }
  557.     DOLsave = YES;
  558.     if (!Asking)
  559.         ModCount += 1;
  560. }
  561.  
  562. void
  563. unmodify()
  564. {
  565.     if (curbuf->b_modified) {
  566.         UpdModLine = YES;
  567.         curbuf->b_modified = NO;
  568.     }
  569. }
  570.  
  571. int
  572. numcomp(s1, s2)
  573. register char    *s1,
  574.         *s2;
  575. {
  576.     register int    count = 0;
  577.  
  578.     while (*s1 != '\0' && *s1++ == *s2++)
  579.         count += 1;
  580.     return count;
  581. }
  582.  
  583. char *
  584. copystr(str)
  585. char    *str;
  586. {
  587.     char    *val;
  588.  
  589.     if (str == NULL)
  590.         return NULL;
  591.     val = emalloc((size_t) (strlen(str) + 1));
  592.  
  593.     strcpy(val, str);
  594.     return val;
  595. }
  596.  
  597. #ifndef    byte_copy
  598. void
  599. byte_copy(from, to, count)
  600. UnivConstPtr    *from;
  601. UnivPtr        *to;
  602. register size_t    count;
  603. {
  604.     register const char    *p = from;
  605.     register char        *q = to;
  606.  
  607.     if (count != 0) {
  608.         do *q++ = *p++; while (--count != 0);
  609.     }
  610. }
  611. #endif
  612.  
  613. void
  614. len_error(flag)
  615. int    flag;
  616. {
  617.     char    *mesg = "[line too long]";
  618.  
  619.     if (flag == COMPLAIN)
  620.         complain(mesg);
  621.     else
  622.         error(mesg);
  623. }
  624.  
  625. /* Insert num number of c's at offset atchar in a linebuf of LBSIZE */
  626.  
  627. void
  628. ins_c(c, buf, atchar, num, max)
  629. int    c;
  630. char    *buf;
  631. int    atchar,
  632.     num,
  633.     max;
  634. {
  635.     register char    *pp, *pp1;
  636.     register int    len;
  637.     int    numchars;    /* number of characters to copy forward */
  638.  
  639.     if (num <= 0)
  640.         return;
  641.     len = atchar + strlen(&buf[atchar]);
  642.     if (len + num >= max)
  643.         len_error(COMPLAIN);
  644.     pp = &buf[len + 1];        /* + 1 so we can --pp (not pp--) */
  645.     pp1 = &buf[len + num + 1];
  646.     numchars = len - atchar;
  647.     while (numchars-- >= 0)
  648.         *--pp1 = *--pp;
  649.     pp = &buf[atchar];
  650.     while (--num >= 0)
  651.         *pp++ = c;
  652. }
  653.  
  654. int
  655. TwoBlank()
  656. {
  657.     register Line    *next = curline->l_next;
  658.  
  659.     return ((next != NULL) &&
  660.         (*(lcontents(next)) == '\0') &&
  661.         (next->l_next != NULL) &&
  662.         (*(lcontents(next->l_next)) == '\0'));
  663. }
  664.  
  665. void
  666. linecopy(onto, atchar, from)
  667. register char    *onto,
  668.         *from;
  669. int    atchar;
  670. {
  671.     register char    *endp = &onto[LBSIZE];
  672.  
  673.     onto += atchar;
  674.  
  675.     do {
  676.         if (onto >= endp)
  677.             len_error(ERROR);
  678.     } while ((*onto++ = *from++) != '\0');
  679. }
  680.  
  681. char *
  682. IOerr(err, file)
  683. char    *err, *file;
  684. {
  685.     return sprint("Couldn't %s \"%s\".", err, file);
  686. }
  687.  
  688. #ifdef    UNIX
  689. void
  690. dopipe(p)
  691. int    *p;
  692. {
  693.     if (pipe(p) == -1)
  694.         complain("[Pipe failed: %s]", strerror(errno));
  695. }
  696.  
  697. void
  698. pipeclose(p)
  699. int    *p;
  700. {
  701.     (void) close(p[0]);
  702.     (void) close(p[1]);
  703. }
  704. #endif    /* UNIX */
  705.  
  706. /* NOSTRICT */
  707.  
  708. UnivPtr
  709. emalloc(size)
  710. size_t    size;
  711. {
  712.     register UnivPtr    ptr;
  713.  
  714.     if ((ptr = malloc(size)) == NULL) {
  715.         /* Try garbage collecting lines */
  716.         GCchunks();
  717.         if ((ptr = malloc(size)) == NULL) {
  718.             /* Uh ... Oh screw it! */
  719.             error("[Out of memory] ");
  720.             /* NOTREACHED */
  721.         }
  722.     }
  723.     return ptr;
  724. }
  725.  
  726. UnivPtr
  727. erealloc(ptr, size)
  728. UnivPtr    ptr;
  729. size_t    size;
  730. {
  731.     if ((ptr = realloc(ptr, size)) == NULL) {
  732.         /* no second chance for realloc! */
  733.         error("[out of memory]");
  734.         /* NOTREACHED */
  735.     }
  736.     return ptr;
  737. }
  738.  
  739. /* Return the basename of file F. */
  740.  
  741. char *
  742. basename(f)
  743. register char    *f;
  744. {
  745.     register char    *cp;
  746.  
  747.     if ((cp = strrchr(f, '/')) != NULL)
  748.         return cp + 1;
  749.     else
  750. #ifdef    MSDOS
  751.         if (cp = strrchr(f, '\\'))
  752.             return cp + 1;
  753.     else
  754.         if (cp = strrchr(f, ':'))
  755.             return cp + 1;
  756. #endif    /* MSDOS */
  757.         return f;
  758. }
  759.  
  760. void
  761. push_env(savejmp)
  762. jmp_buf    savejmp;
  763. {
  764.     byte_copy((UnivPtr) mainjmp, (UnivPtr) savejmp, sizeof (jmp_buf));
  765. }
  766.  
  767. void
  768. pop_env(savejmp)
  769. jmp_buf    savejmp;
  770. {
  771.     byte_copy((UnivPtr) savejmp, (UnivPtr) mainjmp, sizeof (jmp_buf));
  772. }
  773.  
  774. /* get the time buf, designated by *timep, from FROM to TO. */
  775. char *
  776. get_time(timep, buf, from, to)
  777. time_t    *timep;
  778. char    *buf;
  779. int    from,
  780.     to;
  781. {
  782.     time_t    now;
  783.     char    *cp;
  784.  
  785.     if (timep != NULL)
  786.         now = *timep;
  787.     else
  788.         (void) time(&now);
  789.     cp = ctime(&now) + from;
  790. #ifndef    MSDOS
  791.     if (to == -1)
  792. #else    /* MSDOS */
  793.     if ((to == -1) && (cp[strlen(cp)-1] == '\n'))
  794. #endif    /* MSDOS */
  795.         cp[strlen(cp) - 1] = '\0';        /* Get rid of \n */
  796.     else
  797.         cp[to - from] = '\0';
  798.     if (buf) {
  799.         strcpy(buf, cp);
  800.         return buf;
  801.     } else {
  802.         return cp;
  803.     }
  804. }
  805.  
  806. int
  807. casecmp(s1, s2)
  808. register char    *s1,
  809.         *s2;
  810. {
  811.     if (s1==NULL || s2==NULL)
  812.         return 1;    /* which is not zero ... */
  813.     while (CharUpcase(*s1) == CharUpcase(*s2++))
  814.         if (*s1++ == '\0')
  815.             return 0;
  816.     return (*s1 - *--s2);
  817. }
  818.  
  819. int
  820. casencmp(s1, s2, n)
  821. register char    *s1,
  822.         *s2;
  823. register size_t    n;
  824. {
  825.     if (s1==NULL || s2==NULL)
  826.         return 1;    /* which is not zero ... */
  827.     for (;;) {
  828.         if (n == 0)
  829.             return 0;
  830.         n--;
  831.         if (CharUpcase(*s1) != CharUpcase(*s2++))
  832.             return *s1 - *--s2;
  833.         if (*s1++ == '\0')
  834.             return 0;
  835.     }
  836. }
  837.  
  838. void
  839. null_ncpy(to, from, n)
  840. char    *to,
  841.     *from;
  842. size_t    n;
  843. {
  844.     (void) strncpy(to, from, n);
  845.     to[n] = '\0';
  846. }
  847.  
  848. /* Tries to pause for delay/10 seconds OR until a character is typed
  849.    at the keyboard.  This works well on BSD4_2 and not so well on the
  850.    rest. */
  851.  
  852. #ifdef    BSD4_2
  853. # ifndef    BSD2_10
  854. #   include <sys/time.h>
  855. # endif
  856. #endif
  857.  
  858. #ifdef    MSDOS
  859. # include <bios.h>
  860. # include <dos.h>
  861. #endif
  862.  
  863. void
  864. SitFor(delay)
  865. int    delay;
  866. {
  867. #ifdef    MAC
  868.     long    start,
  869.         end;
  870.  
  871. #define Ticks ((long *) 0x16A)    /* 1/60 sec */
  872.     Keyonly = YES;
  873.     redisplay();
  874.     start = *Ticks;
  875.  
  876.     end = start + delay * 6;
  877.     do {
  878.         if ((InputPending = charp()) != NO)
  879.             break;
  880.     } while (*Ticks < end);
  881. #undef    Ticks
  882.  
  883. #else    /* !MAC */
  884.  
  885. #ifndef    MSDOS
  886.     if (!charp()) {
  887. #if    defined(BSD4_2) && !defined(BSD2_10)
  888.         struct timeval    timer;
  889.         long    readfds = 1;
  890.  
  891.         /* So messages that aren't error messages don't
  892.          * hang around forever.
  893.          * Gross that I had to snarf this from getch()
  894.          */
  895.         if (!UpdMesg && !Asking && mesgbuf[0] && !errormsg)
  896.             message(NullStr);
  897.         redisplay();
  898.  
  899.         timer.tv_sec = (delay / 10);
  900.         timer.tv_usec = (delay % 10) * 100000;
  901.         select(1, &readfds, (long *)NULL, (long *)NULL, &timer);
  902. #else    /* !(defined(BSD4_2) && !defined(BSD2_10)) */
  903.         /* Pause by spitting NULs at the terminal.  Ugh! */
  904.         static const int cps[] = {
  905.             0,
  906.             5,
  907.             7,
  908.             11,
  909.             13,
  910.             15,
  911.             20,
  912.             30,
  913.             60,
  914.             120,
  915.             180,
  916.             240,
  917.             480,
  918.             960,
  919.             1920,
  920.             1920,
  921.         };
  922.         register int    nchars,
  923.                 check_cnt;
  924.  
  925.         nchars = (delay * cps[ospeed]) / 10;
  926.         check_cnt = BufSize;
  927.         redisplay();
  928.         if (!NP) {
  929.             while ((--nchars > 0) && !InputPending) {
  930.                 jputchar(PC);
  931.                 if (--check_cnt == 0) {
  932.                     check_cnt = BufSize;
  933.                     InputPending = charp();
  934.                 }
  935.             }
  936.         }
  937. #endif    /* !(defined(BSD4_2) && !defined(BSD2_10)) */
  938.     }
  939. #else    /* MSDOS */
  940.  
  941.     long    start,
  942.         end;
  943. #ifndef    IBMPC
  944.     struct dostime_t tc;
  945. #endif
  946.  
  947.     redisplay();
  948. #ifdef    IBMPC
  949.     _bios_timeofday(_TIME_GETCLOCK, &start);
  950. #else
  951.     _dos_gettime(&tc);
  952.     start = (long)(tc.hour*60L*60L*10L)+(long)(tc.minute*60L*10L)+
  953.         (long)(tc.second*10)+(long)(tc.hsecond/10);
  954. #endif
  955.     end = (start + delay);
  956.     do  {
  957.         if ((InputPending = charp()) != NO)
  958.             break;
  959. #ifdef    IBMPC
  960.         if (_bios_timeofday(_TIME_GETCLOCK, &start))
  961.             break;    /* after midnight */
  962. #else
  963.         start = (long)(tc.hour*60L*60L*10L)+(long)(tc.minute*60L*10L)+
  964.             (long)(tc.second*10)+(long)(tc.hsecond/10);
  965. #endif
  966.     } while (start < end);
  967. #endif    /* MSDOS */
  968. #endif    /* !MAC */
  969. }
  970.  
  971. bool
  972. sindex(pattern, string)
  973. register char    *pattern,
  974.         *string;
  975. {
  976.     register size_t    len = strlen(pattern);
  977.  
  978.     while (*string != '\0') {
  979.         if (*pattern == *string && strncmp(pattern, string, len) == 0)
  980.             return TRUE;
  981.         string += 1;
  982.     }
  983.     return FALSE;
  984. }
  985.  
  986. void
  987. make_argv(argv, ap)
  988. register char    *argv[];
  989. va_list    ap;
  990. {
  991.     register int    i = 0;
  992.  
  993.     argv[i++] = va_arg(ap, char *);
  994.     argv[i++] = basename(argv[0]);
  995.     do ; while ((argv[i++] = va_arg(ap, char *)) != NULL);
  996. }
  997.  
  998. int
  999. pnt_line()
  1000. {
  1001.     register Line    *lp = curbuf->b_first;
  1002.     register int    i;
  1003.  
  1004.     for (i = 0; lp != NULL; i++, lp = lp->l_next)
  1005.         if (lp == curline)
  1006.             break;
  1007.     return i + 1;
  1008. }
  1009.  
  1010. /* Free, then allocate a block.
  1011.  * Like erealloc, except that the previous contents of the block are lost.
  1012.  */
  1013.  
  1014. UnivPtr
  1015. freealloc(obj, size)
  1016. register UnivPtr    obj;
  1017. size_t    size;
  1018. {
  1019.     register UnivPtr    new = NULL;
  1020.  
  1021.     if (obj)
  1022.         new = realloc(obj, size);
  1023.     if (new == NULL)
  1024.         new = emalloc(size);
  1025.     return new;
  1026. }
  1027.  
  1028. #ifndef HAVE_STRERROR
  1029. /*
  1030.  * Unix version of strerror - map error number to descriptive string.
  1031.  * ANSI systems should have this.
  1032.  */
  1033. char *
  1034. strerror(errnum)
  1035. int errnum;
  1036. {
  1037.     extern int sys_nerr;
  1038.     extern char *sys_errlist[];
  1039.  
  1040.     if (errnum > 0 && errnum < sys_nerr)
  1041.         return(sys_errlist[errnum]);
  1042.     return sprint("Error number %d", errnum);
  1043. }
  1044. #endif
  1045.