[BACK]Return to util.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Diff for /src/usr.bin/mg/util.c between version 1.2 and 1.3

version 1.2, 2000/04/13 06:12:16 version 1.3, 2000/09/01 14:59:09
Line 1 
Line 1 
 /*  /*
  *              Assorted commands.   *              Assorted commands.
  * The file contains the command   * This file contains the command processors for a large assortment of
  * processors for a large assortment of unrelated   * unrelated commands.  The only thing they have in common is that they
  * commands. The only thing they have in common is   * are all command processors.
  * that they are all command processors.  
  */   */
 #include        "def.h"  
   
   #include "def.h"
   
 /*  /*
  * Display a bunch of useful information about   * Display a bunch of useful information about the current location of dot.
  * the current location of dot. The character under the   * The character under the cursor (in octal), the current line, row, and
  * cursor (in octal), the current line, row, and column, and   * column, and approximate position of the cursor in the file (as a
  * approximate position of the cursor in the file (as a percentage)   * percentage) is displayed.  The column position assumes an infinite
  * is displayed. The column position assumes an infinite position   * position display; it does not truncate just because the screen does.
  * display; it does not truncate just because the screen does.  
  * This is normally bound to "C-X =".   * This is normally bound to "C-X =".
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 showcpos(f, n)  showcpos(f, n)
           int f, n;
 {  {
         register LINE  *clp;          LINE    *clp;
         register long   nchar;          long     nchar;
         long            cchar;          long     cchar;
         register int    nline, row;          int      nline, row;
         int             cline, cbyte;   /* Current line/char/byte */          int      cline, cbyte;          /* Current line/char/byte */
         int             ratio;          int      ratio;
   
         clp = lforw(curbp->b_linep);    /* Collect the data.     */          /* collect the data */
           clp = lforw(curbp->b_linep);
           cchar = 0;
           cline = 0;
           cbyte = 0;
         nchar = 0;          nchar = 0;
         nline = 0;          nline = 0;
         for (;;) {          for (;;) {
                 ++nline;        /* Count this line       */                  /* count this line */
                   ++nline;
                 if (clp == curwp->w_dotp) {                  if (clp == curwp->w_dotp) {
                         cline = nline;  /* Mark line             */                          /* mark line */
                           cline = nline;
                         cchar = nchar + curwp->w_doto;                          cchar = nchar + curwp->w_doto;
                         if (curwp->w_doto == llength(clp))                          if (curwp->w_doto == llength(clp))
                                 cbyte = '\n';                                  cbyte = '\n';
                         else                          else
                                 cbyte = lgetc(clp, curwp->w_doto);                                  cbyte = lgetc(clp, curwp->w_doto);
                 }                  }
                 nchar += llength(clp);  /* Now count the chars   */                  /* now count the chars */
                   nchar += llength(clp);
                 clp = lforw(clp);                  clp = lforw(clp);
                 if (clp == curbp->b_linep)                  if (clp == curbp->b_linep)
                         break;                          break;
                 nchar++;        /* count the newline     */                  /* count the newline */
                   nchar++;
         }          }
         row = curwp->w_toprow + 1;      /* Determine row.        */          /* determine row */
           row = curwp->w_toprow + 1;
         clp = curwp->w_linep;          clp = curwp->w_linep;
         while (clp != curbp->b_linep && clp != curwp->w_dotp) {          while (clp != curbp->b_linep && clp != curwp->w_dotp) {
                 ++row;                  ++row;
Line 54 
Line 64 
         /* NOSTRICT */          /* NOSTRICT */
         ratio = nchar ? (100L * cchar) / nchar : 100;          ratio = nchar ? (100L * cchar) / nchar : 100;
         ewprintf("Char: %c (0%o)  point=%ld(%d%%)  line=%d  row=%d  col=%d",          ewprintf("Char: %c (0%o)  point=%ld(%d%%)  line=%d  row=%d  col=%d",
                  cbyte, cbyte, cchar, ratio, cline, row, getcolpos());              cbyte, cbyte, cchar, ratio, cline, row, getcolpos());
         return TRUE;          return TRUE;
 }  }
   
   int
 getcolpos()  getcolpos()
 {  {
         register int    col, i, c;          int     col, i, c;
   
         col = 1;                /* Determine column.     */          /* determine column */
           col = 1;
   
         for (i = 0; i < curwp->w_doto; ++i) {          for (i = 0; i < curwp->w_doto; ++i) {
                 c = lgetc(curwp->w_dotp, i);                  c = lgetc(curwp->w_dotp, i);
                 if (c == '\t'                  if (c == '\t'
 #ifdef  NOTAB  #ifdef NOTAB
                     && !(curbp->b_flag & BFNOTAB)                      && !(curbp->b_flag & BFNOTAB)
 #endif  #endif /* NOTAB */
                         ) {                          ) {
                         col |= 0x07;                          col |= 0x07;
                         ++col;                          ++col;
Line 78 
Line 91 
         }          }
         return col;          return col;
 }  }
   
 /*  /*
  * Twiddle the two characters on either side of   * Twiddle the two characters on either side of dot.  If dot is at the end
  * dot. If dot is at the end of the line twiddle the   * of the line twiddle the two characters before it.  Return with an error
  * two characters before it. Return with an error if dot   * if dot is at the beginning of line; it seems to be a bit pointless to
  * is at the beginning of line; it seems to be a bit   * make this work.  This fixes up a very common typo with a single stroke.
  * pointless to make this work. This fixes up a very   * Normally bound to "C-T".  This always works within a line, so "WFEDIT"
  * common typo with a single stroke. Normally bound   * is good enough.
  * to "C-T". This always works within a line, so  
  * "WFEDIT" is good enough.  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 twiddle(f, n)  twiddle(f, n)
           int f, n;
 {  {
         register LINE  *dotp;          LINE    *dotp;
         register int    doto;          int      doto, cr;
         register int    cr;  
         VOID            lchange();  
   
         dotp = curwp->w_dotp;          dotp = curwp->w_dotp;
         doto = curwp->w_doto;          doto = curwp->w_doto;
Line 114 
Line 126 
 }  }
   
 /*  /*
  * Open up some blank space. The basic plan   * Open up some blank space.  The basic plan is to insert a bunch of
  * is to insert a bunch of newlines, and then back   * newlines, and then back up over them.  Everything is done by the
  * up over them. Everything is done by the subcommand   * subcommand procerssors.  They even handle the looping.  Normally this
  * procerssors. They even handle the looping. Normally   * is bound to "C-O".
  * this is bound to "C-O".  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 openline(f, n)  openline(f, n)
           int f, n;
 {  {
         register int    i;          int     i;
         register int    s;          int     s;
   
         if (n < 0)          if (n < 0)
                 return FALSE;                  return FALSE;
         if (n == 0)          if (n == 0)
                 return TRUE;                  return TRUE;
         i = n;                  /* Insert newlines.      */  
           /* insert newlines */
           i = n;
         do {          do {
                 s = lnewline();                  s = lnewline();
         } while (s == TRUE && --i);          } while (s == TRUE && --i);
         if (s == TRUE)          /* Then back up overtop */  
                 s = backchar(f | FFRAND, n);    /* of them all.          */          /* then go back up overtop of them all */
           if (s == TRUE)
                   s = backchar(f | FFRAND, n);
         return s;          return s;
 }  }
   
 /*  /*
  * Insert a newline.   * Insert a newline.  [following "feature" not present in current version of
  * [following "feature" not present in current version of   * Gnu, and now disabled here too] If you are at the end of the line and the
  *  Gnu, and now disabled here too]   * next line is a blank line, just move into the blank line.  This makes
  * If you are at the end of the line and the   * "C-O" and "C-X C-O" work nicely, and reduces the ammount of screen update
  * next line is a blank line, just move into the   * that has to be done.  This would not be as critical if screen update were a
  * blank line. This makes "C-O" and "C-X C-O" work   * lot more efficient.
  * nicely, and reduces the ammount of screen  
  * update that has to be done. This would not be  
  * as critical if screen update were a lot  
  * more efficient.  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 newline(f, n)  newline(f, n)
           int f, n;
 {  {
         register LINE  *lp;          LINE    *lp;
         register int    s;          int      s;
   
         if (n < 0)          if (n < 0)
                 return FALSE;                  return FALSE;
   
         while (n--) {          while (n--) {
                 lp = curwp->w_dotp;                  lp = curwp->w_dotp;
 #ifdef undef  #ifdef undef
Line 168 
Line 184 
                         if ((s = forwchar(FFRAND, 1)) != TRUE)                          if ((s = forwchar(FFRAND, 1)) != TRUE)
                                 return s;                                  return s;
                 } else                  } else
 #endif  #endif /* undef */
                 if ((s = lnewline()) != TRUE)                  if ((s = lnewline()) != TRUE)
                         return s;                          return s;
         }          }
Line 176 
Line 192 
 }  }
   
 /*  /*
  * Delete blank lines around dot.   * Delete blank lines around dot. What this command does depends if dot is
  * What this command does depends if dot is   * sitting on a blank line. If dot is sitting on a blank line, this command
  * sitting on a blank line. If dot is sitting on a   * deletes all the blank lines above and below the current line. If it is
  * blank line, this command deletes all the blank lines   * sitting on a non blank line then it deletes all of the blank lines after
  * above and below the current line. If it is sitting   * the line. Normally this command is bound to "C-X C-O". Any argument is
  * on a non blank line then it deletes all of the   * ignored.
  * blank lines after the line. Normally this command  
  * is bound to "C-X C-O". Any argument is ignored.  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 deblank(f, n)  deblank(f, n)
           int f, n;
 {  {
         register LINE  *lp1;          LINE    *lp1, *lp2;
         register LINE  *lp2;          RSIZE    nld;
         register RSIZE  nld;  
   
         lp1 = curwp->w_dotp;          lp1 = curwp->w_dotp;
         while (llength(lp1) == 0 && (lp2 = lback(lp1)) != curbp->b_linep)          while (llength(lp1) == 0 && (lp2 = lback(lp1)) != curbp->b_linep)
                 lp1 = lp2;                  lp1 = lp2;
         lp2 = lp1;          lp2 = lp1;
         nld = (RSIZE) 0;          nld = (RSIZE)0;
         while ((lp2 = lforw(lp2)) != curbp->b_linep && llength(lp2) == 0)          while ((lp2 = lforw(lp2)) != curbp->b_linep && llength(lp2) == 0)
                 ++nld;                  ++nld;
         if (nld == 0)          if (nld == 0)
                 return (TRUE);                  return (TRUE);
         curwp->w_dotp = lforw(lp1);          curwp->w_dotp = lforw(lp1);
         curwp->w_doto = 0;          curwp->w_doto = 0;
         return ldelete((RSIZE) nld, KNONE);          return ldelete((RSIZE)nld, KNONE);
 }  }
   
 /*  /*
  * Delete any whitespace around dot, then insert a space.   * Delete any whitespace around dot, then insert a space.
  */   */
   int
 justone(f, n)  justone(f, n)
           int f, n;
 {  {
         (VOID) delwhite(f, n);          (VOID)delwhite(f, n);
         return linsert(1, ' ');          return linsert(1, ' ');
 }  }
   
 /*  /*
  * Delete any whitespace around dot.   * Delete any whitespace around dot.
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 delwhite(f, n)  delwhite(f, n)
           int f, n;
 {  {
         register int    col, c, s;          int     col, c, s;
   
         col = curwp->w_doto;          col = curwp->w_doto;
   
         while (((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')          while (((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')
                && col < llength(curwp->w_dotp))                 && col < llength(curwp->w_dotp))
                 ++col;                  ++col;
Line 236 
Line 257 
         } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t');          } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t');
   
         if (s == TRUE)          if (s == TRUE)
                 (VOID) forwchar(FFRAND, 1);                  (VOID)forwchar(FFRAND, 1);
         (VOID) ldelete((RSIZE) (col - curwp->w_doto), KNONE);          (VOID)ldelete((RSIZE)(col - curwp->w_doto), KNONE);
         return TRUE;          return TRUE;
 }  }
   
 /*  /*
  * Insert a newline, then enough   * Insert a newline, then enough tabs and spaces to duplicate the indentation
  * tabs and spaces to duplicate the indentation   * of the previous line.  Assumes tabs are every eight characters.  Quite
  * of the previous line. Assumes tabs are every eight   * simple.  Figure out the indentation of the current line.  Insert a newline
  * characters. Quite simple. Figure out the indentation   * by calling the standard routine.  Insert the indentation by inserting the
  * of the current line. Insert a newline by calling   * right number of tabs and spaces.  Return TRUE if all ok.  Return FALSE if
  * the standard routine. Insert the indentation by   * one of the subcomands failed. Normally bound to "C-J".
  * inserting the right number of tabs and spaces.  
  * Return TRUE if all ok. Return FALSE if one  
  * of the subcomands failed. Normally bound  
  * to "C-J".  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 indent(f, n)  indent(f, n)
           int f, n;
 {  {
         register int    nicol;          int     nicol;
         register int    c;          int     c;
         register int    i;          int     i;
   
         if (n < 0)          if (n < 0)
                 return (FALSE);                  return (FALSE);
   
         while (n--) {          while (n--) {
                 nicol = 0;                  nicol = 0;
                 for (i = 0; i < llength(curwp->w_dotp); ++i) {                  for (i = 0; i < llength(curwp->w_dotp); ++i) {
Line 273 
Line 294 
                 }                  }
                 if (lnewline() == FALSE || ((                  if (lnewline() == FALSE || ((
 #ifdef  NOTAB  #ifdef  NOTAB
                                              curbp->b_flag & BFNOTAB) ?                      curbp->b_flag & BFNOTAB) ? linsert(nicol, ' ') == FALSE : (
                                             linsert(nicol, ' ') == FALSE : (  #endif /* NOTAB */
 #endif                      ((i = nicol / 8) != 0 && linsert(i, '\t') == FALSE) ||
                       ((i = nicol / 8) != 0 && linsert(i, '\t') == FALSE) ||                      ((i = nicol % 8) != 0 && linsert(i, ' ') == FALSE))))
                        ((i = nicol % 8) != 0 && linsert(i, ' ') == FALSE))))  
                         return FALSE;                          return FALSE;
         }          }
         return TRUE;          return TRUE;
 }  }
   
 /*  /*
  * Delete forward. This is real   * Delete forward.  This is real easy, because the basic delete routine does
  * easy, because the basic delete routine does   * all of the work.  Watches for negative arguments, and does the right thing.
  * all of the work. Watches for negative arguments,   * If any argument is present, it kills rather than deletes, to prevent loss
  * and does the right thing. If any argument is   * of text if typed with a big argument.  Normally bound to "C-D".
  * present, it kills rather than deletes, to prevent  
  * loss of text if typed with a big argument.  
  * Normally bound to "C-D".  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 forwdel(f, n)  forwdel(f, n)
           int f, n;
 {  {
         if (n < 0)          if (n < 0)
                 return backdel(f | FFRAND, -n);                  return backdel(f | FFRAND, -n);
         if (f & FFARG) {        /* Really a kill.        */  
           /* really a kill */
           if (f & FFARG) {
                 if ((lastflag & CFKILL) == 0)                  if ((lastflag & CFKILL) == 0)
                         kdelete();                          kdelete();
                 thisflag |= CFKILL;                  thisflag |= CFKILL;
         }          }
   
         return ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE);          return ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE);
 }  }
   
 /*  /*
  * Delete backwards. This is quite easy too,   * Delete backwards.  This is quite easy too, because it's all done with
  * because it's all done with other functions. Just   * other functions.  Just move the cursor back, and delete forwards.  Like
  * move the cursor back, and delete forwards.   * delete forward, this actually does a kill if presented with an argument.
  * Like delete forward, this actually does a kill  
  * if presented with an argument.  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 backdel(f, n)  backdel(f, n)
           int f, n;
 {  {
         register int    s;          int     s;
   
         if (n < 0)          if (n < 0)
                 return forwdel(f | FFRAND, -n);                  return forwdel(f | FFRAND, -n);
         if (f & FFARG) {        /* Really a kill.        */  
           /* really a kill */
           if (f & FFARG) {
                 if ((lastflag & CFKILL) == 0)                  if ((lastflag & CFKILL) == 0)
                         kdelete();                          kdelete();
                 thisflag |= CFKILL;                  thisflag |= CFKILL;
         }          }
         if ((s = backchar(f | FFRAND, n)) == TRUE)          if ((s = backchar(f | FFRAND, n)) == TRUE)
                 s = ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE);                  s = ldelete((RSIZE)n, (f & FFARG) ? KFORW : KNONE);
   
         return s;          return s;
 }  }
   
 /*  /*
  * Kill line. If called without an argument,   * Kill line.  If called without an argument, it kills from dot to the end
  * it kills from dot to the end of the line, unless it   * of the line, unless it is at the end of the line, when it kills the
  * is at the end of the line, when it kills the newline.   * newline.  If called with an argument of 0, it kills from the start of the
  * If called with an argument of 0, it kills from the   * line to dot.  If called with a positive argument, it kills from dot
  * start of the line to dot. If called with a positive   * forward over that number of newlines.  If called with a negative argument
  * argument, it kills from dot forward over that number   * it kills any text before dot on the current line, then it kills back
  * of newlines. If called with a negative argument it   * abs(arg) lines.
  * kills any text before dot on the current line,  
  * then it kills back abs(arg) lines.  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 killline(f, n)  killline(f, n)
           int f, n;
 {  {
         register RSIZE  chunk;          LINE    *nextp;
         register LINE  *nextp;          RSIZE    chunk;
         register int    i, c;          int      i, c;
         VOID            kdelete();  
   
         if ((lastflag & CFKILL) == 0)   /* Clear kill buffer if */          /* clear kill buffer if last wasn't a kill */
                 kdelete();      /* last wasn't a kill.   */          if ((lastflag & CFKILL) == 0)
                   kdelete();
         thisflag |= CFKILL;          thisflag |= CFKILL;
         if (!(f & FFARG)) {          if (!(f & FFARG)) {
                 for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)                  for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
Line 372 
Line 397 
                         chunk += llength(nextp) + 1;                          chunk += llength(nextp) + 1;
                         nextp = lforw(nextp);                          nextp = lforw(nextp);
                 }                  }
         } else {                /* n <= 0                */          } else {
                   /* n <= 0 */
                 chunk = curwp->w_doto;                  chunk = curwp->w_doto;
                 curwp->w_doto = 0;                  curwp->w_doto = 0;
                 i = n;                  i = n;
Line 385 
Line 411 
                 }                  }
         }          }
         /*          /*
          * KFORW here is a bug. Should be KBACK/KFORW, but we need to           * KFORW here is a bug.  Should be KBACK/KFORW, but we need to
          * rewrite the ldelete code (later)?           * rewrite the ldelete code (later)?
          */           */
         return (ldelete(chunk, KFORW));          return (ldelete(chunk, KFORW));
 }  }
   
 /*  /*
  * Yank text back from the kill buffer. This   * Yank text back from the kill buffer.  This is really easy.  All of the work
  * is really easy. All of the work is done by the   * is done by the standard insert routines.  All you do is run the loop, and
  * standard insert routines. All you do is run the loop,   * check for errors.  The blank lines are inserted with a call to "newline"
  * and check for errors. The blank   * instead of a call to "lnewline" so that the magic stuff that happens when
  * lines are inserted with a call to "newline"   * you type a carriage return also happens when a carriage return is yanked
  * instead of a call to "lnewline" so that the magic   * back from the kill buffer.  An attempt has been made to fix the cosmetic
  * stuff that happens when you type a carriage   * bug associated with a yank when dot is on the top line of the window
  * return also happens when a carriage return is   * (nothing moves, because all of the new text landed off screen).
  * yanked back from the kill buffer.  
  * An attempt has been made to fix the cosmetic bug  
  * associated with a yank when dot is on the top line of  
  * the window (nothing moves, because all of the new  
  * text landed off screen).  
  */   */
 /* ARGSUSED */  /* ARGSUSED */
   int
 yank(f, n)  yank(f, n)
           int f, n;
 {  {
         register int    c;          LINE    *lp;
         register int    i;          int      c, i, nline;
         register LINE  *lp;  
         register int    nline;  
         VOID            isetmark();  
   
         if (n < 0)          if (n < 0)
                 return FALSE;                  return FALSE;
         nline = 0;              /* Newline counting.     */  
           /* newline counting */
           nline = 0;
   
         while (n--) {          while (n--) {
                 isetmark();     /* mark around last yank */                  /* mark around last yank */
                   isetmark();
                 i = 0;                  i = 0;
                 while ((c = kremove(i)) >= 0) {                  while ((c = kremove(i)) >= 0) {
                         if (c == '\n') {                          if (c == '\n') {
Line 433 
Line 457 
                         ++i;                          ++i;
                 }                  }
         }          }
         lp = curwp->w_linep;    /* Cosmetic adjustment   */          /* cosmetic adjustment */
         if (curwp->w_dotp == lp) {      /* if offscreen insert. */          lp = curwp->w_linep;
   
           /* if offscreen insert */
           if (curwp->w_dotp == lp) {
                 while (nline-- && lback(lp) != curbp->b_linep)                  while (nline-- && lback(lp) != curbp->b_linep)
                         lp = lback(lp);                          lp = lback(lp);
                 curwp->w_linep = lp;    /* Adjust framing.       */                  /* adjust framing */
                   curwp->w_linep = lp;
                 curwp->w_flag |= WFHARD;                  curwp->w_flag |= WFHARD;
         }          }
         return TRUE;          return TRUE;
Line 445 
Line 473 
   
 #ifdef  NOTAB  #ifdef  NOTAB
 /* ARGSUSED */  /* ARGSUSED */
   int
 space_to_tabstop(f, n)  space_to_tabstop(f, n)
         int             f, n;          int f, n;
 {  {
         if (n < 0)          if (n < 0)
                 return FALSE;                  return FALSE;
Line 454 
Line 483 
                 return TRUE;                  return TRUE;
         return linsert((n << 3) - (curwp->w_doto & 7), ' ');          return linsert((n << 3) - (curwp->w_doto & 7), ' ');
 }  }
 #endif  #endif /* NOTAB */

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3