home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 198_02 / word.c < prev    next >
C/C++ Source or Header  |  1990-01-23  |  14KB  |  569 lines

  1. /*
  2.  * The routines in this file implement commands that work word or a
  3.  * paragraph at a time.  There are all sorts of word mode commands.  If I
  4.  * do any sentence mode commands, they are likely to be put in this file. 
  5.  */
  6.  
  7. #include    <stdio.h>
  8. #include    "estruct.h"
  9. #include    "edef.h"
  10.  
  11. /* Word wrap on n-spaces. Back-over whatever precedes the point on the current
  12.  * line and stop on the first word-break or the beginning of the line. If we
  13.  * reach the beginning of the line, jump back to the end of the word and start
  14.  * a new line.    Otherwise, break the line at the word-break, eat it, and jump
  15.  * back to the end of the word.
  16.  * Returns TRUE on success, FALSE on errors.
  17.  */
  18. wrapword(f, n)
  19.  
  20. int f;        /* default flag */
  21. int n;        /* numeric argument */
  22.  
  23. {
  24.     register int cnt;    /* size of word wrapped to next line */
  25.     register int c;        /* charector temporary */
  26.  
  27.     /* backup from the <NL> 1 char */
  28.     if (!backchar(FALSE, 1))
  29.         return(FALSE);
  30.  
  31.     /* back up until we aren't in a word,
  32.        make sure there is a break in the line */
  33.     cnt = 0;
  34.     while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
  35.                 && (c != '\t')) {
  36.         cnt++;
  37.         if (!backchar(FALSE, 1))
  38.             return(FALSE);
  39.         /* if we make it to the beginning, start a new line */
  40.         if (curwp->w_doto == 0) {
  41.             goeol(FALSE, 0);
  42.             return(lnewline());
  43.         }
  44.     }
  45.  
  46.     /* delete the forward white space */
  47.      if (!forwdel(FALSE, 1))
  48.         return(FALSE);
  49.  
  50.     /* put in a end of line */
  51.     if (!lnewline())
  52.         return(FALSE);
  53.  
  54.     /* and past the first word */
  55.     while (cnt-- > 0) {
  56.         if (forwchar(FALSE, 1) == FALSE)
  57.             return(FALSE);
  58.     }
  59.     return(TRUE);
  60. }
  61.  
  62. /*
  63.  * Move the cursor backward by "n" words. All of the details of motion are
  64.  * performed by the "backchar" and "forwchar" routines. Error if you try to
  65.  * move beyond the buffers.
  66.  */
  67. backword(f, n)
  68. {
  69.     if (n < 0)
  70.         return (forwword(f, -n));
  71.     if (backchar(FALSE, 1) == FALSE)
  72.         return (FALSE);
  73.     while (n--) {
  74.         while (inword() == FALSE) {
  75.             if (backchar(FALSE, 1) == FALSE)
  76.                 return (FALSE);
  77.         }
  78.         while (inword() != FALSE) {
  79.             if (backchar(FALSE, 1) == FALSE)
  80.                 return (FALSE);
  81.         }
  82.     }
  83.     return (forwchar(FALSE, 1));
  84. }
  85.  
  86. /*
  87.  * Move the cursor forward by the specified number of words. All of the motion
  88.  * is done by "forwchar". Error if you try and move beyond the buffer's end.
  89.  */
  90. forwword(f, n)
  91. {
  92.     if (n < 0)
  93.         return (backword(f, -n));
  94.     while (n--) {
  95.         while (inword() == TRUE) {
  96.             if (forwchar(FALSE, 1) == FALSE)
  97.                 return (FALSE);
  98.         }
  99.  
  100.         while (inword() == FALSE) {
  101.             if (forwchar(FALSE, 1) == FALSE)
  102.                 return (FALSE);
  103.         }
  104.     }
  105.     return(TRUE);
  106. }
  107.  
  108. /*
  109.  * Move the cursor forward by the specified number of words. As you move,
  110.  * convert any characters to upper case. Error if you try and move beyond the
  111.  * end of the buffer. Bound to "M-U".
  112.  */
  113. upperword(f, n)
  114. {
  115.     register int    c;
  116.  
  117.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  118.         return(rdonly());    /* we are in read only mode    */
  119.     if (n < 0)
  120.         return (FALSE);
  121.     while (n--) {
  122.         while (inword() == FALSE) {
  123.             if (forwchar(FALSE, 1) == FALSE)
  124.                 return (FALSE);
  125.         }
  126.         while (inword() != FALSE) {
  127.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  128.             if (c>='a' && c<='z') {
  129.                 c -= 'a'-'A';
  130.                 lputc(curwp->w_dotp, curwp->w_doto, c);
  131.                 lchange(WFHARD);
  132.             }
  133.             if (forwchar(FALSE, 1) == FALSE)
  134.                 return (FALSE);
  135.         }
  136.     }
  137.     return (TRUE);
  138. }
  139.  
  140. /*
  141.  * Move the cursor forward by the specified number of words. As you move
  142.  * convert characters to lower case. Error if you try and move over the end of
  143.  * the buffer. Bound to "M-L".
  144.  */
  145. lowerword(f, n)
  146. {
  147.     register int    c;
  148.  
  149.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  150.         return(rdonly());    /* we are in read only mode    */
  151.     if (n < 0)
  152.         return (FALSE);
  153.     while (n--) {
  154.         while (inword() == FALSE) {
  155.             if (forwchar(FALSE, 1) == FALSE)
  156.                 return (FALSE);
  157.         }
  158.         while (inword() != FALSE) {
  159.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  160.             if (c>='A' && c<='Z') {
  161.                 c += 'a'-'A';
  162.                 lputc(curwp->w_dotp, curwp->w_doto, c);
  163.                 lchange(WFHARD);
  164.             }
  165.             if (forwchar(FALSE, 1) == FALSE)
  166.                 return (FALSE);
  167.         }
  168.     }
  169.     return (TRUE);
  170. }
  171.  
  172. /*
  173.  * Move the cursor forward by the specified number of words. As you move
  174.  * convert the first character of the word to upper case, and subsequent
  175.  * characters to lower case. Error if you try and move past the end of the
  176.  * buffer. Bound to "M-C".
  177.  */
  178. capword(f, n)
  179. {
  180.     register int    c;
  181.  
  182.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  183.         return(rdonly());    /* we are in read only mode    */
  184.     if (n < 0)
  185.         return (FALSE);
  186.     while (n--) {
  187.         while (inword() == FALSE) {
  188.             if (forwchar(FALSE, 1) == FALSE)
  189.                 return (FALSE);
  190.         }
  191.         if (inword() != FALSE) {
  192.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  193.             if (c>='a' && c<='z') {
  194.                 c -= 'a'-'A';
  195.                 lputc(curwp->w_dotp, curwp->w_doto, c);
  196.                 lchange(WFHARD);
  197.             }
  198.             if (forwchar(FALSE, 1) == FALSE)
  199.                 return (FALSE);
  200.             while (inword() != FALSE) {
  201.                 c = lgetc(curwp->w_dotp, curwp->w_doto);
  202.                 if (c>='A' && c<='Z') {
  203.                     c += 'a'-'A';
  204.                     lputc(curwp->w_dotp, curwp->w_doto, c);
  205.                     lchange(WFHARD);
  206.                 }
  207.                 if (forwchar(FALSE, 1) == FALSE)
  208.                     return (FALSE);
  209.             }
  210.         }
  211.     }
  212.     return (TRUE);
  213. }
  214.  
  215. /*
  216.  * Kill forward by "n" words. Remember the location of dot. Move forward by
  217.  * the right number of words. Put dot back where it was and issue the kill
  218.  * command for the right number of characters. With a zero argument, just
  219.  * kill one word and no whitespace. Bound to "M-D".
  220.  */
  221. delfword(f, n)
  222. {
  223.     register LINE    *dotp;    /* original cursor line */
  224.     register int    doto;    /*    and row */
  225.     register int c;        /* temp char */
  226.     long size;        /* # of chars to delete */
  227.  
  228.     /* don't allow this command if we are in read only mode */
  229.     if (curbp->b_mode&MDVIEW)
  230.         return(rdonly());
  231.  
  232.     /* ignore the command if there is a negative argument */
  233.     if (n < 0)
  234.         return (FALSE);
  235.  
  236.     /* Clear the kill buffer if last command wasn't a kill */
  237.     if ((lastflag&CFKILL) == 0)
  238.         kdelete();
  239.     thisflag |= CFKILL;    /* this command is a kill */
  240.  
  241.     /* save the current cursor position */
  242.     dotp = curwp->w_dotp;
  243.     doto = curwp->w_doto;
  244.  
  245.     /* figure out how many characters to give the axe */
  246.     size = 0;
  247.  
  248. #if    DECEDT
  249. #else
  250.     /* get us into a word.... */
  251.     while (inword() == FALSE) {
  252.         if (forwchar(FALSE, 1) == FALSE)
  253.             return(FALSE);
  254.         ++size;
  255.     }
  256. #endif
  257.  
  258.     if (n == 0) {
  259.         /* skip one word, no whitespace! */
  260.         while (inword() == TRUE) {
  261.             if (forwchar(FALSE, 1) == FALSE)
  262.                 return(FALSE);
  263.             ++size;
  264.         }
  265.     } else {
  266.         /* skip n words.... */
  267.         while (n--) {
  268.     
  269.             /* if we are at EOL; skip to the beginning of the next */
  270.             while (curwp->w_doto == llength(curwp->w_dotp)) {
  271.                 if (forwchar(FALSE, 1) == FALSE)
  272.                     return(FALSE);
  273.                 ++size;
  274.             }
  275.     
  276.             /* move forward till we are at the end of the word */
  277.             while (inword() == TRUE) {
  278.                 if (forwchar(FALSE, 1) == FALSE)
  279.                     return(FALSE);
  280.                 ++size;
  281.             }
  282.     
  283.             /* if there are more words, skip the interword stuff */
  284.             if (n != 0)
  285.                 while (inword() == FALSE) {
  286.                     if (forwchar(FALSE, 1) == FALSE)
  287.                         return(FALSE);
  288.                     ++size;
  289.                 }
  290.         }
  291.     
  292.         /* skip whitespace and newlines */
  293.         while ((curwp->w_doto == llength(curwp->w_dotp)) ||
  294.             ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ') ||
  295.             (c == '\t')) {
  296.                 if (forwchar(FALSE, 1) == FALSE)
  297.                     break;
  298.                 ++size;
  299.         }
  300.     }
  301.  
  302.     /* restore the original position and delete the words */
  303.     curwp->w_dotp = dotp;
  304.     curwp->w_doto = doto;
  305.     return (ldelete(size, TRUE));
  306. }
  307.  
  308. /*
  309.  * Kill backwards by "n" words. Move backwards by the desired number of words,
  310.  * counting the characters. When dot is finally moved to its resting place,
  311.  * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
  312.  */
  313. delbword(f, n)
  314. {
  315.     long size;
  316.  
  317.     /* don't allow this command if we are in read only mode */
  318.     if (curbp->b_mode&MDVIEW)
  319.         return(rdonly());
  320.  
  321.     /* ignore the command if there is a nonpositive argument */
  322.     if (n <= 0)
  323.         return (FALSE);
  324.  
  325.     /* Clear the kill buffer if last command wasn't a kill */
  326.     if ((lastflag&CFKILL) == 0)
  327.         kdelete();
  328.     thisflag |= CFKILL;    /* this command is a kill */
  329.  
  330.     if (backchar(FALSE, 1) == FALSE)
  331.         return (FALSE);
  332.     size = 0;
  333.     while (n--) {
  334.         while (inword() == FALSE) {
  335.             if (backchar(FALSE, 1) == FALSE)
  336.                 return (FALSE);
  337.             ++size;
  338.         }
  339.         while (inword() != FALSE) {
  340.             ++size;
  341.             if (backchar(FALSE, 1) == FALSE)
  342.                 goto bckdel;
  343.         }
  344.     }
  345.     if (forwchar(FALSE, 1) == FALSE)
  346.         return (FALSE);
  347. bckdel:    return (ldelete(size, TRUE));
  348. }
  349.  
  350. /*
  351.  * Return TRUE if the character at dot is a character that is considered to be
  352.  * part of a word. The word character list is hard coded. Should be setable.
  353.  */
  354. inword()
  355. {
  356.     register int    c;
  357.  
  358.     if (curwp->w_doto == llength(curwp->w_dotp))
  359.         return (FALSE);
  360.     c = lgetc(curwp->w_dotp, curwp->w_doto);
  361. #if    DECEDT
  362.     return((c > 0x20 && c < 0x7F) ? TRUE : FALSE );
  363. #else
  364.     if (c>='a' && c<='z')
  365.         return (TRUE);
  366.     if (c>='A' && c<='Z')
  367.         return (TRUE);
  368.     if (c>='0' && c<='9')
  369.         return (TRUE);
  370.     return (FALSE);
  371. #endif
  372. }
  373.  
  374. #if    WORDPRO
  375. fillpara(f, n)    /* Fill the current paragraph according to the current
  376.            fill column                        */
  377.  
  378. int f, n;    /* deFault flag and Numeric argument */
  379.  
  380. {
  381.     register int c;            /* current char durring scan    */
  382.     register int wordlen;        /* length of current word    */
  383.     register int clength;        /* position on line during fill    */
  384.     register int i;            /* index during word copy    */
  385.     register int newlength;        /* tentative new line length    */
  386.     register int eopflag;        /* Are we at the End-Of-Paragraph? */
  387.     register int firstwflag;    /* first word? (needs no space)    */
  388.     register LINE *eopline;        /* pointer to line just past EOP */
  389.     register int dotflag;        /* was the last char a period?    */
  390.     char wbuf[NSTRING];        /* buffer for current word    */
  391.  
  392.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  393.         return(rdonly());    /* we are in read only mode    */
  394.     if (fillcol == 0) {    /* no fill column set */
  395.         mlwrite("No fill column set");
  396.         return(FALSE);
  397.     }
  398.  
  399.     /* record the pointer to the line just past the EOP */
  400.     goeop(FALSE, 1);
  401.     eopline = lforw(curwp->w_dotp);
  402.  
  403.     /* and back top the beginning of the paragraph */
  404.     gobop(FALSE, 1);
  405.  
  406.     /* initialize various info */
  407.     clength = curwp->w_doto;
  408.     if (clength && curwp->w_dotp->l_text[0] == TAB)
  409.         clength = tabsize;
  410.     wordlen = 0;
  411.     dotflag = FALSE;
  412.  
  413.     /* scan through lines, filling words */
  414.     firstwflag = TRUE;
  415.     eopflag = FALSE;
  416.     while (!eopflag) {
  417.         /* get the next character in the paragraph */
  418.         if (curwp->w_doto == llength(curwp->w_dotp)) {
  419.             c = ' ';
  420.             if (lforw(curwp->w_dotp) == eopline ||
  421.                 curwp->w_dotp == curbp->b_linep)
  422.                 eopflag = TRUE;
  423.         } else
  424.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  425.  
  426.         /* and then delete it */
  427.         ldelete(1L, FALSE);
  428.  
  429.         /* if not a separator, just add it in */
  430.         if (c != ' ' && c != '\t') {
  431.             dotflag = (c == '.');        /* was it a dot */
  432.             if (wordlen < NSTRING - 1)
  433.                 wbuf[wordlen++] = c;
  434.         } else if (wordlen) {
  435.             /* at a word break with a word waiting */
  436.             /* calculate tentitive new length with word added */
  437.             newlength = clength + 1 + wordlen;
  438.             if (newlength <= fillcol || clength == 0) {
  439.                 /* add word to current line */
  440.                 if (!firstwflag) {
  441.                     linsert(1, ' '); /* the space */
  442.                     ++clength;
  443.                 }
  444.                 firstwflag = FALSE;
  445.             } else {
  446.                 /* start a new line */
  447.                 lnewline();
  448.                 clength = 0;
  449.             }
  450.  
  451.             /* and add the word in in either case */
  452.             for (i=0; i<wordlen; i++) {
  453.                 linsert(1, wbuf[i]);
  454.                 ++clength;
  455.             }
  456.             if (dotflag) {
  457.                 linsert(1, ' ');
  458.                 ++clength;
  459.             }
  460.             wordlen = 0;
  461.         }
  462.     }
  463.     /* and add a last newline for the end of our new paragraph */
  464.     if (curwp->w_dotp != curbp->b_linep)
  465.         lnewline();
  466.     return(TRUE);
  467. }
  468.  
  469. killpara(f, n)    /* delete n paragraphs starting with the current one */
  470.  
  471. int f;    /* default flag */
  472. int n;    /* # of paras to delete */
  473.  
  474. {
  475.     register int status;    /* returned status of functions */
  476.  
  477.     while (n--) {        /* for each paragraph to delete */
  478.  
  479.         /* mark out the end and beginning of the para to delete */
  480.         goeop(FALSE, 1);
  481.  
  482.         /* set the mark here */
  483.         curwp->w_markp = curwp->w_dotp;
  484.         curwp->w_marko = curwp->w_doto;
  485.  
  486.         /* go to the beginning of the paragraph */
  487.         gobop(FALSE, 1);
  488.         curwp->w_doto = 0;    /* force us to the beginning of line */
  489.     
  490.         /* and delete it */
  491.         if ((status = killregion(FALSE, 1)) != TRUE)
  492.             return(status);
  493.  
  494.         /* and clean up the 2 extra lines */
  495.         ldelete(2L, TRUE);
  496.     }
  497.     return(TRUE);
  498. }
  499.  
  500.  
  501. /*    wordcount:    count the # of words in the marked region,
  502.             along with average word sizes, # of chars, etc,
  503.             and report on them.            */
  504.  
  505. wordcount(f, n)
  506.  
  507. int f, n;    /* ignored numeric arguments */
  508.  
  509. {
  510.     register LINE *lp;    /* current line to scan */
  511.     register int offset;    /* current char to scan */
  512.     long size;        /* size of region left to count */
  513.     register int ch;    /* current character to scan */
  514.     register int wordflag;    /* are we in a word now? */
  515.     register int lastword;    /* were we just in a word? */
  516.     long nwords;        /* total # of words */
  517.     long nchars;        /* total number of chars */
  518.     int nlines;        /* total number of lines in region */
  519.     int avgch;        /* average number of chars/word */
  520.     int status;        /* status return code */
  521.     REGION region;        /* region to look at */
  522.  
  523.     /* make sure we have a region to count */
  524.     if ((status = getregion(®ion)) != TRUE)
  525.         return(status);
  526.     lp = region.r_linep;
  527.     offset = region.r_offset;
  528.     size = region.r_size;
  529.  
  530.     /* count up things */
  531.     lastword = FALSE;
  532.     nchars = 0L;
  533.     nwords = 0L;
  534.     nlines = 0;
  535.     while (size-- > 0L) {
  536.  
  537.         /* get the current character */
  538.         if (offset == llength(lp)) {    /* end of line */
  539.             ch = '\n';
  540.             lp = lforw(lp);
  541.             offset = 0;
  542.             ++nlines;
  543.         } else {
  544.             ch = lgetc(lp, offset);
  545.             ++offset;
  546.         }
  547.  
  548.         /* and tabulate it */
  549.         wordflag = ((ch >= 'a' && ch <= 'z') ||
  550.                 (ch >= 'A' && ch <= 'Z') ||
  551.                 (ch >= '0' && ch <= '9'));
  552.         if (wordflag == TRUE && lastword == FALSE)
  553.             ++nwords;
  554.         lastword = wordflag;
  555.         ++nchars;
  556.     }
  557.  
  558.     /* and report on the info */
  559.     if (nwords > 0L)
  560.         avgch = (int)((100L * nchars) / nwords);
  561.     else
  562.         avgch = 0;
  563.  
  564.     mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
  565.         nwords, nchars, nlines + 1, avgch);
  566.     return(TRUE);
  567. }
  568. #endif
  569.