home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume1 / 8711 / microemacs-3.9 / 9 < prev    next >
Text File  |  1987-11-17  |  32KB  |  1,183 lines

  1. Article 85 of comp.sources.misc:
  2. Path: tut!osu-cis!cbosgd!mandrill!hal!ncoast!allbery
  3. From: nwd@j.cc.purdue.edu (Daniel Lawrence)
  4. Newsgroups: comp.sources.misc
  5. Subject: MicroEmacs 3.9 (Part 9 of 16)
  6. Message-ID: <5685@ncoast.UUCP>
  7. Date: 17 Nov 87 02:32:45 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Lines: 1168
  10. Approved: allbery@ncoast.UUCP
  11. X-Archive: comp.sources.misc/microemacs-3.9/8
  12.  
  13. # This is a shar archive.
  14. # Remove everything above this line.
  15. # Run the file through sh, not csh.
  16. # (type `sh mes.9')
  17. # If you do not see the message
  18. #    `mes.9 completed!'
  19. # then the file was incomplete.
  20. echo extracting - random.c
  21. sed 's/^X//' > random.c << 'FRIDAY_NIGHT'
  22. X/*
  23. X * This file contains the command processing functions for a number of random
  24. X * commands. There is no functional grouping here, for sure.
  25. X */
  26. X
  27. X#include        <stdio.h>
  28. X#include    "estruct.h"
  29. X#include        "edef.h"
  30. X
  31. Xint     tabsize;                        /* Tab size (0: use real tabs)  */
  32. X
  33. X/*
  34. X * Set fill column to n.
  35. X */
  36. Xsetfillcol(f, n)
  37. X{
  38. X        fillcol = n;
  39. X    mlwrite("[Fill column is %d]",n);
  40. X        return(TRUE);
  41. X}
  42. X
  43. X/*
  44. X * Display the current position of the cursor, in origin 1 X-Y coordinates,
  45. X * the character that is under the cursor (in hex), and the fraction of the
  46. X * text that is before the cursor. The displayed column is not the current
  47. X * column, but the column that would be used on an infinite width display.
  48. X * Normally this is bound to "C-X =".
  49. X */
  50. Xshowcpos(f, n)
  51. X{
  52. X        register LINE   *lp;        /* current line */
  53. X        register long   numchars;    /* # of chars in file */
  54. X        register int    numlines;    /* # of lines in file */
  55. X        register long   predchars;    /* # chars preceding point */
  56. X        register int    predlines;    /* # lines preceding point */
  57. X        register int    curchar;    /* character under cursor */
  58. X        int ratio;
  59. X        int col;
  60. X    int savepos;            /* temp save for current offset */
  61. X    int ecol;            /* column pos/end of current line */
  62. X
  63. X    /* starting at the beginning of the buffer */
  64. X        lp = lforw(curbp->b_linep);
  65. X
  66. X    /* start counting chars and lines */
  67. X        numchars = 0;
  68. X        numlines = 0;
  69. X        while (lp != curbp->b_linep) {
  70. X        /* if we are on the current line, record it */
  71. X        if (lp == curwp->w_dotp) {
  72. X            predlines = numlines;
  73. X            predchars = numchars + curwp->w_doto;
  74. X            if ((curwp->w_doto) == llength(lp))
  75. X                curchar = '\n';
  76. X            else
  77. X                curchar = lgetc(lp, curwp->w_doto);
  78. X        }
  79. X        /* on to the next line */
  80. X        ++numlines;
  81. X        numchars += llength(lp) + 1;
  82. X        lp = lforw(lp);
  83. X        }
  84. X
  85. X    /* if at end of file, record it */
  86. X    if (curwp->w_dotp == curbp->b_linep) {
  87. X        predlines = numlines;
  88. X        predchars = numchars;
  89. X    }
  90. X
  91. X    /* Get real column and end-of-line column. */
  92. X    col = getccol(FALSE);
  93. X    savepos = curwp->w_doto;
  94. X    curwp->w_doto = llength(curwp->w_dotp);
  95. X    ecol = getccol(FALSE);
  96. X    curwp->w_doto = savepos;
  97. X
  98. X        ratio = 0;              /* Ratio before dot. */
  99. X        if (numchars != 0)
  100. X                ratio = (100L*predchars) / numchars;
  101. X
  102. X    /* summarize and report the info */
  103. X    mlwrite("Line %d/%d Col %d/%d Char %D/%D (%d%%) char = 0x%x",
  104. X        predlines+1, numlines+1, col, ecol,
  105. X        predchars, numchars, ratio, curchar);
  106. X        return (TRUE);
  107. X}
  108. X
  109. Xgetcline()    /* get the current line number */
  110. X
  111. X{
  112. X        register LINE   *lp;        /* current line */
  113. X        register int    numlines;    /* # of lines before point */
  114. X
  115. X    /* starting at the beginning of the buffer */
  116. X        lp = lforw(curbp->b_linep);
  117. X
  118. X    /* start counting lines */
  119. X        numlines = 0;
  120. X        while (lp != curbp->b_linep) {
  121. X        /* if we are on the current line, record it */
  122. X        if (lp == curwp->w_dotp)
  123. X            break;
  124. X        ++numlines;
  125. X        lp = lforw(lp);
  126. X        }
  127. X
  128. X    /* and return the resulting count */
  129. X    return(numlines + 1);
  130. X}
  131. X
  132. X/*
  133. X * Return current column.  Stop at first non-blank given TRUE argument.
  134. X */
  135. Xgetccol(bflg)
  136. Xint bflg;
  137. X{
  138. X        register int c, i, col;
  139. X        col = 0;
  140. X        for (i=0; i<curwp->w_doto; ++i) {
  141. X                c = lgetc(curwp->w_dotp, i);
  142. X                if (c!=' ' && c!='\t' && bflg)
  143. X                        break;
  144. X                if (c == '\t')
  145. X                        col |= 0x07;
  146. X                else if (c<0x20 || c==0x7F)
  147. X                        ++col;
  148. X                ++col;
  149. X        }
  150. X        return(col);
  151. X}
  152. X
  153. X/*
  154. X * Set current column.
  155. X */
  156. Xsetccol(pos)
  157. X
  158. Xint pos;    /* position to set cursor */
  159. X
  160. X{
  161. X        register int c;        /* character being scanned */
  162. X    register int i;        /* index into current line */
  163. X    register int col;    /* current cursor column   */
  164. X    register int llen;    /* length of line in bytes */
  165. X
  166. X    col = 0;
  167. X    llen = llength(curwp->w_dotp);
  168. X
  169. X    /* scan the line until we are at or past the target column */
  170. X    for (i = 0; i < llen; ++i) {
  171. X        /* upon reaching the target, drop out */
  172. X        if (col >= pos)
  173. X            break;
  174. X
  175. X        /* advance one character */
  176. X                c = lgetc(curwp->w_dotp, i);
  177. X                if (c == '\t')
  178. X                        col |= 0x07;
  179. X                else if (c<0x20 || c==0x7F)
  180. X                        ++col;
  181. X                ++col;
  182. X        }
  183. X
  184. X    /* set us at the new position */
  185. X    curwp->w_doto = i;
  186. X
  187. X    /* and tell weather we made it */
  188. X    return(col >= pos);
  189. X}
  190. X
  191. X/*
  192. X * Twiddle the two characters on either side of dot. If dot is at the end of
  193. X * the line twiddle the two characters before it. Return with an error if dot
  194. X * is at the beginning of line; it seems to be a bit pointless to make this
  195. X * work. This fixes up a very common typo with a single stroke. Normally bound
  196. X * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  197. X */
  198. Xtwiddle(f, n)
  199. X{
  200. X        register LINE   *dotp;
  201. X        register int    doto;
  202. X        register int    cl;
  203. X        register int    cr;
  204. X
  205. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  206. X        return(rdonly());    /* we are in read only mode    */
  207. X        dotp = curwp->w_dotp;
  208. X        doto = curwp->w_doto;
  209. X        if (doto==llength(dotp) && --doto<0)
  210. X                return (FALSE);
  211. X        cr = lgetc(dotp, doto);
  212. X        if (--doto < 0)
  213. X                return (FALSE);
  214. X        cl = lgetc(dotp, doto);
  215. X        lputc(dotp, doto+0, cr);
  216. X        lputc(dotp, doto+1, cl);
  217. X        lchange(WFEDIT);
  218. X        return (TRUE);
  219. X}
  220. X
  221. X/*
  222. X * Quote the next character, and insert it into the buffer. All the characters
  223. X * are taken literally, with the exception of the newline, which always has
  224. X * its line splitting meaning. The character is always read, even if it is
  225. X * inserted 0 times, for regularity. Bound to "C-Q"
  226. X */
  227. Xquote(f, n)
  228. X{
  229. X        register int    s;
  230. X        register int    c;
  231. X
  232. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  233. X        return(rdonly());    /* we are in read only mode    */
  234. X        c = tgetc();
  235. X        if (n < 0)
  236. X                return (FALSE);
  237. X        if (n == 0)
  238. X                return (TRUE);
  239. X        if (c == '\n') {
  240. X                do {
  241. X                        s = lnewline();
  242. X                } while (s==TRUE && --n);
  243. X                return (s);
  244. X        }
  245. X        return (linsert(n, c));
  246. X}
  247. X
  248. X/*
  249. X * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  250. X * tab into file.  If given argument, n, of zero, change to true tabs.
  251. X * If n > 1, simulate tab stop every n-characters using spaces. This has to be
  252. X * done in this slightly funny way because the tab (in ASCII) has been turned
  253. X * into "C-I" (in 10 bit code) already. Bound to "C-I".
  254. X */
  255. Xtab(f, n)
  256. X{
  257. X        if (n < 0)
  258. X                return (FALSE);
  259. X        if (n == 0 || n > 1) {
  260. X                tabsize = n;
  261. X                return(TRUE);
  262. X        }
  263. X        if (! tabsize)
  264. X                return(linsert(1, '\t'));
  265. X        return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  266. X}
  267. X
  268. X#if    AEDIT
  269. Xdetab(f, n)        /* change tabs to spaces */
  270. X
  271. Xint f,n;    /* default flag and numeric repeat count */
  272. X
  273. X{
  274. X    register int inc;    /* increment to next line [sgn(n)] */
  275. X
  276. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  277. X        return(rdonly());    /* we are in read only mode    */
  278. X
  279. X    if (f == FALSE)
  280. X        n = 1;
  281. X
  282. X    /* loop thru detabbing n lines */
  283. X    inc = ((n > 0) ? 1 : -1);
  284. X    while (n) {
  285. X        curwp->w_doto = 0;    /* start at the beginning */
  286. X
  287. X        /* detab the entire current line */
  288. X        while (curwp->w_doto < llength(curwp->w_dotp)) {
  289. X            /* if we have a tab */
  290. X            if (lgetc(curwp->w_dotp, curwp->w_doto) == '\t') {
  291. X                ldelete(1L, FALSE);
  292. X                insspace(TRUE, 8 - (curwp->w_doto & 7));
  293. X            }
  294. X            forwchar(FALSE, 1);
  295. X        }
  296. X
  297. X        /* advance/or back to the next line */
  298. X        forwline(TRUE, inc);
  299. X        n -= inc;
  300. X    }
  301. X    curwp->w_doto = 0;    /* to the begining of the line */
  302. X    thisflag &= ~CFCPCN;    /* flag that this resets the goal column */
  303. X    lchange(WFEDIT);    /* yes, we have made at least an edit */
  304. X    return(TRUE);
  305. X}
  306. X
  307. Xentab(f, n)        /* change spaces to tabs where posible */
  308. X
  309. Xint f,n;    /* default flag and numeric repeat count */
  310. X
  311. X{
  312. X    register int inc;    /* increment to next line [sgn(n)] */
  313. X    register int fspace;    /* pointer to first space if in a run */
  314. X    register int ccol;    /* current cursor column */
  315. X    register char cchar;    /* current character */
  316. X
  317. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  318. X        return(rdonly());    /* we are in read only mode    */
  319. X
  320. X    if (f == FALSE)
  321. X        n = 1;
  322. X
  323. X    /* loop thru entabbing n lines */
  324. X    inc = ((n > 0) ? 1 : -1);
  325. X    while (n) {
  326. X        curwp->w_doto = 0;    /* start at the beginning */
  327. X
  328. X        /* entab the entire current line */
  329. X        fspace = -1;
  330. X        ccol = 0;
  331. X        while (curwp->w_doto < llength(curwp->w_dotp)) {
  332. X            /* see if it is time to compress */
  333. X            if ((fspace >= 0) && (nextab(fspace) <= ccol))
  334. X                if (ccol - fspace < 2)
  335. X                    fspace = -1;
  336. X                else {
  337. X        /* there is a bug here dealing with mixed space/tabed
  338. X           lines.......it will get fixed        */
  339. X                    backchar(TRUE, ccol - fspace);
  340. X                    ldelete((long)(ccol - fspace), FALSE);
  341. X                    linsert(1, '\t');    
  342. X                    fspace = -1;
  343. X                }
  344. X
  345. X            /* get the current character */
  346. X            cchar = lgetc(curwp->w_dotp, curwp->w_doto);
  347. X
  348. X            switch (cchar) {
  349. X                case '\t': /* a tab...count em up */
  350. X                    ccol = nextab(ccol);
  351. X                    break;
  352. X
  353. X                case ' ':  /* a space...compress? */
  354. X                    if (fspace == -1)
  355. X                        fspace = ccol;
  356. X                    ccol++;
  357. X                    break;
  358. X
  359. X                default:   /* any other char...just count */
  360. X                    ccol++;
  361. X                    fspace = -1;
  362. X                    break;
  363. X            }
  364. X            forwchar(FALSE, 1);
  365. X        }
  366. X
  367. X        /* advance/or back to the next line */
  368. X        forwline(TRUE, inc);
  369. X        n -= inc;
  370. X    }
  371. X    curwp->w_doto = 0;    /* to the begining of the line */
  372. X    thisflag &= ~CFCPCN;    /* flag that this resets the goal column */
  373. X    lchange(WFEDIT);    /* yes, we have made at least an edit */
  374. X    return(TRUE);
  375. X}
  376. X
  377. Xtrim(f, n)    /* trim trailing whitespace from the point to eol */
  378. X
  379. Xint f,n;    /* default flag and numeric repeat count */
  380. X
  381. X{
  382. X    register LINE *lp;    /* current line pointer */
  383. X    register int offset;    /* original line offset position */
  384. X    register int length;    /* current length */
  385. X    register int inc;    /* increment to next line [sgn(n)] */
  386. X
  387. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  388. X        return(rdonly());    /* we are in read only mode    */
  389. X
  390. X    if (f == FALSE)
  391. X        n = 1;
  392. X
  393. X    /* loop thru trimming n lines */
  394. X    inc = ((n > 0) ? 1 : -1);
  395. X    while (n) {
  396. X        lp = curwp->w_dotp;        /* find current line text */
  397. X        offset = curwp->w_doto;        /* save original offset */
  398. X        length = lp->l_used;        /* find current length */
  399. X
  400. X        /* trim the current line */
  401. X        while (length > offset) {
  402. X            if (lgetc(lp, length-1) != ' ' &&
  403. X                lgetc(lp, length-1) != '\t')
  404. X                    break;
  405. X            length--;
  406. X        }
  407. X        lp->l_used = length;
  408. X
  409. X        /* advance/or back to the next line */
  410. X        forwline(TRUE, inc);
  411. X        n -= inc;
  412. X    }
  413. X    lchange(WFEDIT);
  414. X    thisflag &= ~CFCPCN;    /* flag that this resets the goal column */
  415. X    return(TRUE);
  416. X}
  417. X#endif
  418. X
  419. X/*
  420. X * Open up some blank space. The basic plan is to insert a bunch of newlines,
  421. X * and then back up over them. Everything is done by the subcommand
  422. X * procerssors. They even handle the looping. Normally this is bound to "C-O".
  423. X */
  424. Xopenline(f, n)
  425. X{
  426. X        register int    i;
  427. X        register int    s;
  428. X
  429. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  430. X        return(rdonly());    /* we are in read only mode    */
  431. X        if (n < 0)
  432. X                return (FALSE);
  433. X        if (n == 0)
  434. X                return (TRUE);
  435. X        i = n;                                  /* Insert newlines.     */
  436. X        do {
  437. X                s = lnewline();
  438. X        } while (s==TRUE && --i);
  439. X        if (s == TRUE)                          /* Then back up overtop */
  440. X                s = backchar(f, n);             /* of them all.         */
  441. X        return (s);
  442. X}
  443. X
  444. X/*
  445. X * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic
  446. X * indentation as specified.
  447. X */
  448. Xnewline(f, n)
  449. X{
  450. X    register int    s;
  451. X
  452. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  453. X        return(rdonly());    /* we are in read only mode    */
  454. X    if (n < 0)
  455. X        return (FALSE);
  456. X
  457. X    /* if we are in C mode and this is a default <NL> */
  458. X    if (n == 1 && (curbp->b_mode & MDCMOD) &&
  459. X        curwp->w_dotp != curbp->b_linep)
  460. X        return(cinsert());
  461. X
  462. X        /*
  463. X         * If a newline was typed, fill column is defined, the argument is non-
  464. X         * negative, wrap mode is enabled, and we are now past fill column,
  465. X     * and we are not read-only, perform word wrap.
  466. X         */
  467. X        if ((curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
  468. X        getccol(FALSE) > fillcol &&
  469. X        (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
  470. X        execute(META|SPEC|'W', FALSE, 1);
  471. X
  472. X    /* insert some lines */
  473. X    while (n--) {
  474. X        if ((s=lnewline()) != TRUE)
  475. X            return (s);
  476. X    }
  477. X    return (TRUE);
  478. X}
  479. X
  480. Xcinsert()    /* insert a newline and indentation for C */
  481. X
  482. X{
  483. X    register char *cptr;    /* string pointer into text to copy */
  484. X    register int tptr;    /* index to scan into line */
  485. X    register int bracef;    /* was there a brace at the end of line? */
  486. X    register int i;
  487. X    char ichar[NSTRING];    /* buffer to hold indent of last line */
  488. X
  489. X    /* grab a pointer to text to copy indentation from */
  490. X    cptr = &curwp->w_dotp->l_text[0];
  491. X
  492. X    /* check for a brace */
  493. X    tptr = curwp->w_doto - 1;
  494. X    bracef = (cptr[tptr] == '{');
  495. X
  496. X    /* save the indent of the previous line */
  497. X    i = 0;
  498. X    while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t')
  499. X        && (i < NSTRING - 1)) {
  500. X        ichar[i] = cptr[i];
  501. X        ++i;
  502. X    }
  503. X    ichar[i] = 0;        /* terminate it */
  504. X
  505. X    /* put in the newline */
  506. X    if (lnewline() == FALSE)
  507. X        return(FALSE);
  508. X
  509. X    /* and the saved indentation */
  510. X    linstr(ichar);
  511. X
  512. X    /* and one more tab for a brace */
  513. X    if (bracef)
  514. X        tab(FALSE, 1);
  515. X
  516. X    return(TRUE);
  517. X}
  518. X
  519. X#if    NBRACE
  520. Xinsbrace(n, c)    /* insert a brace into the text here...we are in CMODE */
  521. X
  522. Xint n;    /* repeat count */
  523. Xint c;    /* brace to insert (always } for now) */
  524. X
  525. X{
  526. X    register int ch;    /* last character before input */
  527. X    register int oc;    /* caractere oppose a c */
  528. X    register int i, count;
  529. X    register int target;    /* column brace should go after */
  530. X    register LINE *oldlp;
  531. X    register int  oldoff;
  532. X
  533. X    /* if we aren't at the beginning of the line... */
  534. X    if (curwp->w_doto != 0)
  535. X
  536. X    /* scan to see if all space before this is white space */
  537. X        for (i = curwp->w_doto - 1; i >= 0; --i) {
  538. X            ch = lgetc(curwp->w_dotp, i);
  539. X            if (ch != ' ' && ch != '\t')
  540. X                return(linsert(n, c));
  541. X        }
  542. X
  543. X    /* chercher le caractere oppose correspondant */
  544. X    switch (c) {
  545. X        case '}': oc = '{'; break;
  546. X        case ']': oc = '['; break;
  547. X        case ')': oc = '('; break;
  548. X        default: return(FALSE);
  549. X    }
  550. X    
  551. X    oldlp = curwp->w_dotp;
  552. X    oldoff = curwp->w_doto;
  553. X    
  554. X    count = 1; backchar(FALSE, 1);
  555. X    
  556. X    while (count > 0) {
  557. X        if (curwp->w_doto == llength(curwp->w_dotp))
  558. X            ch = '\n';
  559. X        else
  560. X            ch = lgetc(curwp->w_dotp, curwp->w_doto);
  561. X
  562. X        if (ch == c)  ++count;
  563. X        if (ch == oc) --count;
  564. X        
  565. X        backchar(FALSE, 1);
  566. X        if (boundry(curwp->w_dotp, curwp->w_doto, REVERSE))
  567. X            break;
  568. X    }
  569. X    
  570. X    if (count != 0) {    /* no match */
  571. X        curwp->w_dotp = oldlp;
  572. X        curwp->w_doto = oldoff;
  573. X        return(linsert(n, c));
  574. X    }
  575. X    
  576. X    curwp->w_doto = 0;        /* debut de ligne */
  577. X    /* aller au debut de la ligne apres la tabulation */
  578. X    while ((ch = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || ch == '\t')
  579. X        forwchar(FALSE, 1);
  580. X
  581. X    /* delete back first */
  582. X    target = getccol(FALSE);    /* c'est l'indent que l'on doit avoir */
  583. X    curwp->w_dotp = oldlp;
  584. X    curwp->w_doto = oldoff;
  585. X    
  586. X    while (target != getccol(FALSE)) {
  587. X        if (target < getccol(FALSE))    /* on doit detruire des caracteres */
  588. X            while (getccol(FALSE) > target)
  589. X                backdel(FALSE, 1);
  590. X        else {                /* on doit en inserer */
  591. X            while (target - getccol(FALSE) >= 8)
  592. X                linsert(1,'\t');
  593. X            linsert(target - getccol(FALSE), ' ');
  594. X        }
  595. X    }
  596. X
  597. X    /* and insert the required brace(s) */
  598. X    return(linsert(n, c));
  599. X}
  600. X#else
  601. Xinsbrace(n, c)    /* insert a brace into the text here...we are in CMODE */
  602. X
  603. Xint n;    /* repeat count */
  604. Xint c;    /* brace to insert (always { for now) */
  605. X
  606. X{
  607. X    register int ch;    /* last character before input */
  608. X    register int i;
  609. X    register int target;    /* column brace should go after */
  610. X
  611. X    /* if we are at the beginning of the line, no go */
  612. X    if (curwp->w_doto == 0)
  613. X        return(linsert(n,c));
  614. X
  615. X    /* scan to see if all space before this is white space */
  616. X    for (i = curwp->w_doto - 1; i >= 0; --i) {
  617. X        ch = lgetc(curwp->w_dotp, i);
  618. X        if (ch != ' ' && ch != '\t')
  619. X            return(linsert(n, c));
  620. X    }
  621. X
  622. X    /* delete back first */
  623. X    target = getccol(FALSE);    /* calc where we will delete to */
  624. X    target -= 1;
  625. X    target -= target % (tabsize == 0 ? 8 : tabsize);
  626. X    while (getccol(FALSE) > target)
  627. X        backdel(FALSE, 1);
  628. X
  629. X    /* and insert the required brace(s) */
  630. X    return(linsert(n, c));
  631. X}
  632. X#endif
  633. X
  634. Xinspound()    /* insert a # into the text here...we are in CMODE */
  635. X
  636. X{
  637. X    register int ch;    /* last character before input */
  638. X    register int i;
  639. X
  640. X    /* if we are at the beginning of the line, no go */
  641. X    if (curwp->w_doto == 0)
  642. X        return(linsert(1,'#'));
  643. X
  644. X    /* scan to see if all space before this is white space */
  645. X    for (i = curwp->w_doto - 1; i >= 0; --i) {
  646. X        ch = lgetc(curwp->w_dotp, i);
  647. X        if (ch != ' ' && ch != '\t')
  648. X            return(linsert(1, '#'));
  649. X    }
  650. X
  651. X    /* delete back first */
  652. X    while (getccol(FALSE) >= 1)
  653. X        backdel(FALSE, 1);
  654. X
  655. X    /* and insert the required pound */
  656. X    return(linsert(1, '#'));
  657. X}
  658. X
  659. X/*
  660. X * Delete blank lines around dot. What this command does depends if dot is
  661. X * sitting on a blank line. If dot is sitting on a blank line, this command
  662. X * deletes all the blank lines above and below the current line. If it is
  663. X * sitting on a non blank line then it deletes all of the blank lines after
  664. X * the line. Normally this command is bound to "C-X C-O". Any argument is
  665. X * ignored.
  666. X */
  667. Xdeblank(f, n)
  668. X{
  669. X        register LINE   *lp1;
  670. X        register LINE   *lp2;
  671. X        long nld;
  672. X
  673. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  674. X        return(rdonly());    /* we are in read only mode    */
  675. X        lp1 = curwp->w_dotp;
  676. X        while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  677. X                lp1 = lp2;
  678. X        lp2 = lp1;
  679. X        nld = 0;
  680. X        while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  681. X                ++nld;
  682. X        if (nld == 0)
  683. X                return (TRUE);
  684. X        curwp->w_dotp = lforw(lp1);
  685. X        curwp->w_doto = 0;
  686. X        return (ldelete(nld, FALSE));
  687. X}
  688. X
  689. X/*
  690. X * Insert a newline, then enough tabs and spaces to duplicate the indentation
  691. X * of the previous line. Assumes tabs are every eight characters. Quite simple.
  692. X * Figure out the indentation of the current line. Insert a newline by calling
  693. X * the standard routine. Insert the indentation by inserting the right number
  694. X * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  695. X * subcomands failed. Normally bound to "C-J".
  696. X */
  697. Xindent(f, n)
  698. X{
  699. X        register int    nicol;
  700. X        register int    c;
  701. X        register int    i;
  702. X
  703. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  704. X        return(rdonly());    /* we are in read only mode    */
  705. X        if (n < 0)
  706. X                return (FALSE);
  707. X        while (n--) {
  708. X                nicol = 0;
  709. X                for (i=0; i<llength(curwp->w_dotp); ++i) {
  710. X                        c = lgetc(curwp->w_dotp, i);
  711. X                        if (c!=' ' && c!='\t')
  712. X                                break;
  713. X                        if (c == '\t')
  714. X                                nicol |= 0x07;
  715. X                        ++nicol;
  716. X                }
  717. X                if (lnewline() == FALSE
  718. X                || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  719. X                || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  720. X                        return (FALSE);
  721. X        }
  722. X        return (TRUE);
  723. X}
  724. X
  725. X/*
  726. X * Delete forward. This is real easy, because the basic delete routine does
  727. X * all of the work. Watches for negative arguments, and does the right thing.
  728. X * If any argument is present, it kills rather than deletes, to prevent loss
  729. X * of text if typed with a big argument. Normally bound to "C-D".
  730. X */
  731. Xforwdel(f, n)
  732. X{
  733. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  734. X        return(rdonly());    /* we are in read only mode    */
  735. X        if (n < 0)
  736. X                return (backdel(f, -n));
  737. X        if (f != FALSE) {                       /* Really a kill.       */
  738. X                if ((lastflag&CFKILL) == 0)
  739. X                        kdelete();
  740. X                thisflag |= CFKILL;
  741. X        }
  742. X        return (ldelete((long)n, f));
  743. X}
  744. X
  745. X/*
  746. X * Delete backwards. This is quite easy too, because it's all done with other
  747. X * functions. Just move the cursor back, and delete forwards. Like delete
  748. X * forward, this actually does a kill if presented with an argument. Bound to
  749. X * both "RUBOUT" and "C-H".
  750. X */
  751. Xbackdel(f, n)
  752. X{
  753. X        register int    s;
  754. X
  755. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  756. X        return(rdonly());    /* we are in read only mode    */
  757. X        if (n < 0)
  758. X                return (forwdel(f, -n));
  759. X        if (f != FALSE) {                       /* Really a kill.       */
  760. X                if ((lastflag&CFKILL) == 0)
  761. X                        kdelete();
  762. X                thisflag |= CFKILL;
  763. X        }
  764. X        if ((s=backchar(f, n)) == TRUE)
  765. X                s = ldelete((long)n, f);
  766. X        return (s);
  767. X}
  768. X
  769. X/*
  770. X * Kill text. If called without an argument, it kills from dot to the end of
  771. X * the line, unless it is at the end of the line, when it kills the newline.
  772. X * If called with an argument of 0, it kills from the start of the line to dot.
  773. X * If called with a positive argument, it kills from dot forward over that
  774. X * number of newlines. If called with a negative argument it kills backwards
  775. X * that number of newlines. Normally bound to "C-K".
  776. X */
  777. Xkilltext(f, n)
  778. X{
  779. X        register LINE   *nextp;
  780. X        long chunk;
  781. X
  782. X    if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  783. X        return(rdonly());    /* we are in read only mode    */
  784. X        if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  785. X                kdelete();                      /* last wasn't a kill.  */
  786. X        thisflag |= CFKILL;
  787. X        if (f == FALSE) {
  788. X                chunk = llength(curwp->w_dotp)-curwp->w_doto;
  789. X                if (chunk == 0)
  790. X                        chunk = 1;
  791. X        } else if (n == 0) {
  792. X                chunk = curwp->w_doto;
  793. X                curwp->w_doto = 0;
  794. X        } else if (n > 0) {
  795. X                chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  796. X                nextp = lforw(curwp->w_dotp);
  797. X                while (--n) {
  798. X                        if (nextp == curbp->b_linep)
  799. X                                return (FALSE);
  800. X                        chunk += llength(nextp)+1;
  801. X                        nextp = lforw(nextp);
  802. X                }
  803. X        } else {
  804. X                mlwrite("neg kill");
  805. X                return (FALSE);
  806. X        }
  807. X        return(ldelete(chunk, TRUE));
  808. X}
  809. X
  810. Xsetmode(f, n)    /* prompt and set an editor mode */
  811. X
  812. Xint f, n;    /* default and argument */
  813. X
  814. X{
  815. X    adjustmode(TRUE, FALSE);
  816. X}
  817. X
  818. Xdelmode(f, n)    /* prompt and delete an editor mode */
  819. X
  820. Xint f, n;    /* default and argument */
  821. X
  822. X{
  823. X    adjustmode(FALSE, FALSE);
  824. X}
  825. X
  826. Xsetgmode(f, n)    /* prompt and set a global editor mode */
  827. X
  828. Xint f, n;    /* default and argument */
  829. X
  830. X{
  831. X    adjustmode(TRUE, TRUE);
  832. X}
  833. X
  834. Xdelgmode(f, n)    /* prompt and delete a global editor mode */
  835. X
  836. Xint f, n;    /* default and argument */
  837. X
  838. X{
  839. X    adjustmode(FALSE, TRUE);
  840. X}
  841. X
  842. Xadjustmode(kind, global)    /* change the editor mode status */
  843. X
  844. Xint kind;    /* true = set,        false = delete */
  845. Xint global;    /* true = global flag,    false = current buffer flag */
  846. X{
  847. X    register char *scan;        /* scanning pointer to convert prompt */
  848. X    register int i;            /* loop index */
  849. X    register int status;        /* error return on input */
  850. X#if    COLOR
  851. X    register int uflag;        /* was modename uppercase?    */
  852. X#endif
  853. X    char prompt[50];    /* string to prompt user with */
  854. X    char cbuf[NPAT];        /* buffer to recieve mode name into */
  855. X
  856. X    /* build the proper prompt string */
  857. X    if (global)
  858. X        strcpy(prompt,"Global mode to ");
  859. X    else
  860. X        strcpy(prompt,"Mode to ");
  861. X
  862. X    if (kind == TRUE)
  863. X        strcat(prompt, "add: ");
  864. X    else
  865. X        strcat(prompt, "delete: ");
  866. X
  867. X    /* prompt the user and get an answer */
  868. X
  869. X    status = mlreply(prompt, cbuf, NPAT - 1);
  870. X    if (status != TRUE)
  871. X        return(status);
  872. X
  873. X    /* make it uppercase */
  874. X
  875. X    scan = cbuf;
  876. X#if    COLOR
  877. X    uflag = (*scan >= 'A' && *scan <= 'Z');
  878. X#endif
  879. X    while (*scan != 0) {
  880. X        if (*scan >= 'a' && *scan <= 'z')
  881. X            *scan = *scan - 32;
  882. X        scan++;
  883. X    }
  884. X
  885. X    /* test it first against the colors we know */
  886. X    for (i=0; i<NCOLORS; i++) {
  887. X        if (strcmp(cbuf, cname[i]) == 0) {
  888. X            /* finding the match, we set the color */
  889. X#if    COLOR
  890. X            if (uflag)
  891. X                if (global)
  892. X                    gfcolor = i;
  893. X                else
  894. X                    curwp->w_fcolor = i;
  895. X            else
  896. X                if (global)
  897. X                    gbcolor = i;
  898. X                else
  899. X                    curwp->w_bcolor = i;
  900. X
  901. X            curwp->w_flag |= WFCOLR;
  902. X#endif
  903. X            mlerase();
  904. X            return(TRUE);
  905. X        }
  906. X    }
  907. X
  908. X    /* test it against the modes we know */
  909. X
  910. X    for (i=0; i < NUMMODES; i++) {
  911. X        if (strcmp(cbuf, modename[i]) == 0) {
  912. X            /* finding a match, we process it */
  913. X            if (kind == TRUE)
  914. X                if (global)
  915. X                    gmode |= (1 << i);
  916. X                else
  917. X                    curbp->b_mode |= (1 << i);
  918. X            else
  919. X                if (global)
  920. X                    gmode &= ~(1 << i);
  921. X                else
  922. X                    curbp->b_mode &= ~(1 << i);
  923. X            /* display new mode line */
  924. X            if (global == 0)
  925. X                upmode();
  926. X            mlerase();    /* erase the junk */
  927. X            return(TRUE);
  928. X        }
  929. X    }
  930. X
  931. X    mlwrite("No such mode!");
  932. X    return(FALSE);
  933. X}
  934. X
  935. X/*    This function simply clears the message line,
  936. X        mainly for macro usage            */
  937. X
  938. Xclrmes(f, n)
  939. X
  940. Xint f, n;    /* arguments ignored */
  941. X
  942. X{
  943. X    mlforce("");
  944. X    return(TRUE);
  945. X}
  946. X
  947. X/*    This function writes a string on the message line
  948. X        mainly for macro usage            */
  949. X
  950. Xwritemsg(f, n)
  951. X
  952. Xint f, n;    /* arguments ignored */
  953. X
  954. X{
  955. X    register char *sp;    /* pointer into buf to expand %s */
  956. X    register char *np;    /* ptr into nbuf */
  957. X    register int status;
  958. X    char buf[NPAT];        /* buffer to recieve message into */
  959. X    char nbuf[NPAT*2];    /* buffer to expand string into */
  960. X
  961. X    if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE)
  962. X        return(status);
  963. X
  964. X    /* expand all '%' to "%%" so mlwrite won't expect arguments */
  965. X    sp = buf;
  966. X    np = nbuf;
  967. X    while (*sp) {
  968. X        *np++ = *sp;
  969. X        if (*sp++ == '%')
  970. X            *np++ = '%';
  971. X    }
  972. X    *np = '\0';
  973. X
  974. X    /* write the message out */
  975. X    mlforce(nbuf);
  976. X    return(TRUE);
  977. X}
  978. X
  979. X#if    CFENCE
  980. X/*    the cursor is moved to a matching fence    */
  981. X
  982. Xgetfence(f, n)
  983. X
  984. Xint f, n;    /* not used */
  985. X
  986. X{
  987. X    register LINE *oldlp;    /* original line pointer */
  988. X    register int oldoff;    /* and offset */
  989. X    register int sdir;    /* direction of search (1/-1) */
  990. X    register int count;    /* current fence level count */
  991. X    register char ch;    /* fence type to match against */
  992. X    register char ofence;    /* open fence */
  993. X    register char c;    /* current character in scan */
  994. X
  995. X    /* save the original cursor position */
  996. X    oldlp = curwp->w_dotp;
  997. X    oldoff = curwp->w_doto;
  998. X
  999. X    /* get the current character */
  1000. X    if (oldoff == llength(oldlp))
  1001. X        ch = '\n';
  1002. X    else
  1003. X        ch = lgetc(oldlp, oldoff);
  1004. X
  1005. X    /* setup proper matching fence */
  1006. X    switch (ch) {
  1007. X        case '(': ofence = ')'; sdir = FORWARD; break;
  1008. X        case '{': ofence = '}'; sdir = FORWARD; break;
  1009. X        case '[': ofence = ']'; sdir = FORWARD; break;
  1010. X        case ')': ofence = '('; sdir = REVERSE; break;
  1011. X        case '}': ofence = '{'; sdir = REVERSE; break;
  1012. X        case ']': ofence = '['; sdir = REVERSE; break;
  1013. X        default: TTbeep(); return(FALSE);
  1014. X    }
  1015. X
  1016. X    /* set up for scan */
  1017. X    count = 1;
  1018. X    if (sdir == REVERSE)
  1019. X        backchar(FALSE, 1);
  1020. X    else
  1021. X        forwchar(FALSE, 1);
  1022. X
  1023. X    /* scan until we find it, or reach the end of file */
  1024. X    while (count > 0) {
  1025. X        if (curwp->w_doto == llength(curwp->w_dotp))
  1026. X            c = '\n';
  1027. X        else
  1028. X            c = lgetc(curwp->w_dotp, curwp->w_doto);
  1029. X        if (c == ch)
  1030. X            ++count;
  1031. X        if (c == ofence)
  1032. X            --count;
  1033. X        if (sdir == FORWARD)
  1034. X            forwchar(FALSE, 1);
  1035. X        else
  1036. X            backchar(FALSE, 1);
  1037. X        if (boundry(curwp->w_dotp, curwp->w_doto, sdir))
  1038. X            break;
  1039. X    }
  1040. X
  1041. X    /* if count is zero, we have a match, move the sucker */
  1042. X    if (count == 0) {
  1043. X        if (sdir == FORWARD)
  1044. X            backchar(FALSE, 1);
  1045. X        else
  1046. X            forwchar(FALSE, 1);
  1047. X        curwp->w_flag |= WFMOVE;
  1048. X        return(TRUE);
  1049. X    }
  1050. X
  1051. X    /* restore the current position */
  1052. X    curwp->w_dotp = oldlp;
  1053. X    curwp->w_doto = oldoff;
  1054. X    TTbeep();
  1055. X    return(FALSE);
  1056. X}
  1057. X#endif
  1058. X
  1059. X/*    Close fences are matched against their partners, and if
  1060. X    on screen the cursor briefly lights there        */
  1061. X
  1062. Xfmatch(ch)
  1063. X
  1064. Xchar ch;    /* fence type to match against */
  1065. X
  1066. X{
  1067. X    register LINE *oldlp;    /* original line pointer */
  1068. X    register int oldoff;    /* and offset */
  1069. X    register LINE *toplp;    /* top line in current window */
  1070. X    register int count;    /* current fence level count */
  1071. X    register char opench;    /* open fence */
  1072. X    register char c;    /* current character in scan */
  1073. X    register int i;
  1074. X
  1075. X    /* first get the display update out there */
  1076. X    update(FALSE);
  1077. X
  1078. X    /* save the original cursor position */
  1079. X    oldlp = curwp->w_dotp;
  1080. X    oldoff = curwp->w_doto;
  1081. X
  1082. X    /* setup proper open fence for passed close fence */
  1083. X    if (ch == ')')
  1084. X        opench = '(';
  1085. X    else if (ch == '}')
  1086. X        opench = '{';
  1087. X    else
  1088. X        opench = '[';
  1089. X
  1090. X    /* find the top line and set up for scan */
  1091. X    toplp = curwp->w_linep->l_bp;
  1092. X    count = 1;
  1093. X    backchar(FALSE, 2);
  1094. X
  1095. X    /* scan back until we find it, or reach past the top of the window */
  1096. X    while (count > 0 && curwp->w_dotp != toplp) {
  1097. X        if (curwp->w_doto == llength(curwp->w_dotp))
  1098. X            c = '\n';
  1099. X        else
  1100. X            c = lgetc(curwp->w_dotp, curwp->w_doto);
  1101. X        if (c == ch)
  1102. X            ++count;
  1103. X        if (c == opench)
  1104. X            --count;
  1105. X        backchar(FALSE, 1);
  1106. X        if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp &&
  1107. X            curwp->w_doto == 0)
  1108. X            break;
  1109. X    }
  1110. X
  1111. X    /* if count is zero, we have a match, display the sucker */
  1112. X    /* there is a real machine dependant timing problem here we have
  1113. X       yet to solve......... */
  1114. X    if (count == 0) {
  1115. X        forwchar(FALSE, 1);
  1116. X        for (i = 0; i < term.t_pause; i++)
  1117. X            update(FALSE);
  1118. X    }
  1119. X
  1120. X    /* restore the current position */
  1121. X    curwp->w_dotp = oldlp;
  1122. X    curwp->w_doto = oldoff;
  1123. X    return(TRUE);
  1124. X}
  1125. X
  1126. Xistring(f, n)    /* ask for and insert a string into the current
  1127. X           buffer at the current point */
  1128. X
  1129. Xint f, n;    /* ignored arguments */
  1130. X
  1131. X{
  1132. X    register int status;    /* status return code */
  1133. X    char tstring[NPAT+1];    /* string to add */
  1134. X
  1135. X    /* ask for string to insert */
  1136. X    status = mlreplyt("String to insert<META>: ", tstring, NPAT, metac);
  1137. X    if (status != TRUE)
  1138. X        return(status);
  1139. X
  1140. X    if (f == FALSE)
  1141. X        n = 1;
  1142. X
  1143. X    if (n < 0)
  1144. X        n = - n;
  1145. X
  1146. X    /* insert it */
  1147. X    while (n-- && (status = linstr(tstring)))
  1148. X        ;
  1149. X    return(status);
  1150. X}
  1151. X
  1152. Xovstring(f, n)    /* ask for and overwite a string into the current
  1153. X           buffer at the current point */
  1154. X
  1155. Xint f, n;    /* ignored arguments */
  1156. X
  1157. X{
  1158. X    register int status;    /* status return code */
  1159. X    char tstring[NPAT+1];    /* string to add */
  1160. X
  1161. X    /* ask for string to insert */
  1162. X    status = mlreplyt("String to overwrite<META>: ", tstring, NPAT, metac);
  1163. X    if (status != TRUE)
  1164. X        return(status);
  1165. X
  1166. X    if (f == FALSE)
  1167. X        n = 1;
  1168. X
  1169. X    if (n < 0)
  1170. X        n = - n;
  1171. X
  1172. X    /* insert it */
  1173. X    while (n-- && (status = lover(tstring)))
  1174. X        ;
  1175. X    return(status);
  1176. X}
  1177. X
  1178. FRIDAY_NIGHT
  1179. echo mes.9 completed!
  1180. # That's all folks!
  1181.  
  1182.  
  1183.