cmd2.c

Go to the documentation of this file.
00001 /* cmd2.c */
00002 
00003 /* Author:
00004  *      Steve Kirkendall
00005  *      14407 SW Teal Blvd. #C
00006  *      Beaverton, OR 97005
00007  *      kirkenda@cs.pdx.edu
00008  */
00009 
00010 
00011 /* This file contains some of the commands - mostly ones that change text */
00012 
00013 #include "config.h"
00014 #include "ctype.h"
00015 #include "vi.h"
00016 #include "regexp.h"
00017 #if TOS
00018 # include <stat.h>
00019 #else
00020 # if OSK
00021 #  include "osk.h"
00022 # else
00023 #  if AMIGA
00024 #   include "amistat.h"
00025 #  else
00026 #   include <sys/stat.h>
00027 #  endif
00028 # endif
00029 #endif
00030 
00031 
00032 /*ARGSUSED*/
00033 void cmd_substitute(frommark, tomark, cmd, bang, extra)
00034         MARK    frommark;
00035         MARK    tomark;
00036         CMD     cmd;
00037         int     bang;
00038         char    *extra; /* rest of the command line */
00039 {
00040         char    *line;  /* a line from the file */
00041         regexp  *re;    /* the compiled search expression */
00042         char    *subst; /* the substitution string */
00043         char    *opt;   /* substitution options */
00044         long    l;      /* a line number */
00045         char    *s, *d; /* used during subtitutions */
00046         char    *conf;  /* used during confirmation */
00047         long    chline; /* # of lines changed */
00048         long    chsub;  /* # of substitutions made */
00049         static  optp;   /* boolean option: print when done? */
00050         static  optg;   /* boolean option: substitute globally in line? */
00051         static  optc;   /* boolean option: confirm before subst? */
00052 #ifndef CRUNCH
00053         long    oldnlines;
00054 #endif
00055 
00056 
00057         /* for now, assume this will fail */
00058         rptlines = -1L;
00059 
00060         if (cmd == CMD_SUBAGAIN)
00061         {
00062 #ifndef NO_MAGIC
00063                 if (*o_magic)
00064                         subst = "~";
00065                 else
00066 #endif
00067                 subst = "\\~";
00068                 re = regcomp("");
00069 
00070                 /* if visual "&", then turn off the "p" and "c" options */
00071                 if (bang)
00072                 {
00073                         optp = optc = FALSE;
00074                 }
00075         }
00076         else /* CMD_SUBSTITUTE */
00077         {
00078                 /* make sure we got a search pattern */
00079                 if (*extra != '/' && *extra != '?')
00080                 {
00081                         msg("Usage: s/regular expression/new text/");
00082                         return;
00083                 }
00084 
00085                 /* parse & compile the search pattern */
00086                 subst = parseptrn(extra);
00087                 re = regcomp(extra + 1);
00088         }
00089 
00090         /* abort if RE error -- error message already given by regcomp() */
00091         if (!re)
00092         {
00093                 return;
00094         }
00095 
00096         if (cmd == CMD_SUBSTITUTE)
00097         {
00098                 /* parse the substitution string & find the option string */
00099                 for (opt = subst; *opt && *opt != *extra; opt++)
00100                 {
00101                         if (*opt == '\\' && opt[1])
00102                         {
00103                                 opt++;
00104                         }
00105                 }
00106                 if (*opt)
00107                 {
00108                         *opt++ = '\0';
00109                 }
00110 
00111                 /* analyse the option string */
00112                 if (!*o_edcompatible)
00113                 {
00114                         optp = optg = optc = FALSE;
00115                 }
00116                 while (*opt)
00117                 {
00118                         switch (*opt++)
00119                         {
00120                           case 'p':     optp = !optp;   break;
00121                           case 'g':     optg = !optg;   break;
00122                           case 'c':     optc = !optc;   break;
00123                           case ' ':
00124                           case '\t':                    break;
00125                           default:
00126                                 msg("Subst options are p, c, and g -- not %c", opt[-1]);
00127                                 return;
00128                         }
00129                 }
00130         }
00131 
00132         /* if "c" or "p" flag was given, and we're in visual mode, then NEWLINE */
00133         if ((optc || optp) && mode == MODE_VI)
00134         {
00135                 addch('\n');
00136                 exrefresh();
00137         }
00138 
00139         ChangeText
00140         {
00141                 /* reset the change counters */
00142                 chline = chsub = 0L;
00143 
00144                 /* for each selected line */
00145                 for (l = markline(frommark); l <= markline(tomark); l++)
00146                 {
00147                         /* fetch the line */
00148                         line = fetchline(l);
00149 
00150                         /* if it contains the search pattern... */
00151                         if (regexec(re, line, TRUE))
00152                         {
00153                                 /* increment the line change counter */
00154                                 chline++;
00155 
00156                                 /* initialize the pointers */
00157                                 s = line;
00158                                 d = tmpblk.c;
00159 
00160                                 /* do once or globally ... */
00161                                 do
00162                                 {
00163 #ifndef CRUNCH
00164                                         /* confirm, if necessary */
00165                                         if (optc)
00166                                         {
00167                                                 for (conf = line; conf < re->startp[0]; conf++)
00168                                                         addch(*conf);
00169                                                 standout();
00170                                                 for ( ; conf < re->endp[0]; conf++)
00171                                                         addch(*conf);
00172                                                 standend();
00173                                                 for (; *conf; conf++)
00174                                                         addch(*conf);
00175                                                 addch('\n');
00176                                                 exrefresh();
00177                                                 if (getkey(0) != 'y')
00178                                                 {
00179                                                         /* copy accross the original chars */
00180                                                         while (s < re->endp[0])
00181                                                                 *d++ = *s++;
00182 
00183                                                         /* skip to next match on this line, if any */
00184                                                         goto Continue;
00185                                                 }
00186                                         }
00187 #endif /* not CRUNCH */
00188 
00189                                         /* increment the substitution change counter */
00190                                         chsub++;
00191 
00192                                         /* copy stuff from before the match */
00193                                         while (s < re->startp[0])
00194                                         {
00195                                                 *d++ = *s++;
00196                                         }
00197 
00198                                         /* substitute for the matched part */
00199                                         regsub(re, subst, d);
00200                                         s = re->endp[0];
00201                                         d += strlen(d);
00202 
00203 Continue:
00204                                         /* if this regexp could conceivably match
00205                                          * a zero-length string, then require at
00206                                          * least 1 unmatched character between
00207                                          * matches.
00208                                          */
00209                                         if (re->minlen == 0)
00210                                         {
00211                                                 if (!*s)
00212                                                         break;
00213                                                 *d++ = *s++;
00214                                         }
00215 
00216                                 } while (optg && regexec(re, s, FALSE));
00217 
00218                                 /* copy stuff from after the match */
00219                                 while (*d++ = *s++)     /* yes, ASSIGNMENT! */
00220                                 {
00221                                 }
00222 
00223 #ifndef CRUNCH
00224                                 /* NOTE: since the substitution text is allowed to have ^Ms which are
00225                                  * translated into newlines, it is possible that the number of lines
00226                                  * in the file will increase after each line has been substituted.
00227                                  * we need to adjust for this.
00228                                  */
00229                                 oldnlines = nlines;
00230 #endif
00231 
00232                                 /* replace the old version of the line with the new */
00233                                 d[-1] = '\n';
00234                                 d[0] = '\0';
00235                                 change(MARK_AT_LINE(l), MARK_AT_LINE(l + 1), tmpblk.c);
00236 
00237 #ifndef CRUNCH
00238                                 l += nlines - oldnlines;
00239                                 tomark += MARK_AT_LINE(nlines - oldnlines);
00240 #endif
00241 
00242                                 /* if supposed to print it, do so */
00243                                 if (optp)
00244                                 {
00245                                         addstr(tmpblk.c);
00246                                         exrefresh();
00247                                 }
00248 
00249                                 /* move the cursor to that line */
00250                                 cursor = MARK_AT_LINE(l);
00251                         }
00252                 }
00253         }
00254 
00255         /* free the regexp */
00256         free(re);
00257 
00258         /* if done from within a ":g" command, then finish silently */
00259         if (doingglobal)
00260         {
00261                 rptlines = chline;
00262                 rptlabel = "changed";
00263                 return;
00264         }
00265 
00266         /* Reporting */
00267         if (chsub == 0)
00268         {
00269                 msg("Substitution failed");
00270         }
00271         else if (chline >= *o_report)
00272         {
00273                 msg("%ld substitutions on %ld lines", chsub, chline);
00274         }
00275         rptlines = 0L;
00276 }
00277 
00278 
00279 
00280 
00281 /*ARGSUSED*/
00282 void cmd_delete(frommark, tomark, cmd, bang, extra)
00283         MARK    frommark;
00284         MARK    tomark;
00285         CMD     cmd;
00286         int     bang;
00287         char    *extra;
00288 {
00289         MARK    curs2;  /* an altered form of the cursor */
00290 
00291         /* choose your cut buffer */
00292         if (*extra == '"')
00293         {
00294                 extra++;
00295         }
00296         if (*extra)
00297         {
00298                 cutname(*extra);
00299         }
00300 
00301         /* make sure we're talking about whole lines here */
00302         frommark = frommark & ~(BLKSIZE - 1);
00303         tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
00304 
00305         /* yank the lines */
00306         cut(frommark, tomark);
00307 
00308         /* if CMD_DELETE then delete the lines */
00309         if (cmd != CMD_YANK)
00310         {
00311                 curs2 = cursor;
00312                 ChangeText
00313                 {
00314                         /* delete the lines */
00315                         delete(frommark, tomark);
00316                 }
00317                 if (curs2 > tomark)
00318                 {
00319                         cursor = curs2 - tomark + frommark;
00320                 }
00321                 else if (curs2 > frommark)
00322                 {
00323                         cursor = frommark;
00324                 }
00325         }
00326 }
00327 
00328 
00329 /*ARGSUSED*/
00330 void cmd_append(frommark, tomark, cmd, bang, extra)
00331         MARK    frommark;
00332         MARK    tomark;
00333         CMD     cmd;
00334         int     bang;
00335         char    *extra;
00336 {
00337         long    l;      /* line counter */
00338 
00339 #ifndef CRUNCH
00340         /* if '!' then toggle auto-indent */
00341         if (bang)
00342         {
00343                 *o_autoindent = !*o_autoindent;
00344         }
00345 #endif
00346 
00347         ChangeText
00348         {
00349                 /* if we're doing a change, delete the old version */
00350                 if (cmd == CMD_CHANGE)
00351                 {
00352                         /* delete 'em */
00353                         cmd_delete(frommark, tomark, cmd, bang, extra);
00354                 }
00355 
00356                 /* new lines start at the frommark line, or after it */
00357                 l = markline(frommark);
00358                 if (cmd == CMD_APPEND)
00359                 {
00360                         l++;
00361                 }
00362 
00363                 /* get lines until no more lines, or "." line, and insert them */
00364                 while (vgets('\0', tmpblk.c, BLKSIZE) >= 0)
00365                 {
00366                         addch('\n');
00367                         if (!strcmp(tmpblk.c, "."))
00368                         {
00369                                 break;
00370                         }
00371 
00372                         strcat(tmpblk.c, "\n");
00373                         add(MARK_AT_LINE(l), tmpblk.c);
00374                         l++;
00375                 }
00376         }
00377 
00378         /* on the odd chance that we're calling this from vi mode ... */
00379         redraw(MARK_UNSET, FALSE);
00380 }
00381 
00382 
00383 /*ARGSUSED*/
00384 void cmd_put(frommark, tomark, cmd, bang, extra)
00385         MARK    frommark;
00386         MARK    tomark;
00387         CMD     cmd;
00388         int     bang;
00389         char    *extra;
00390 {
00391         /* choose your cut buffer */
00392         if (*extra == '"')
00393         {
00394                 extra++;
00395         }
00396         if (*extra)
00397         {
00398                 cutname(*extra);
00399         }
00400 
00401         /* paste it */
00402         ChangeText
00403         {
00404                 cursor = paste(frommark, TRUE, FALSE);
00405         }
00406 }
00407 
00408 
00409 /*ARGSUSED*/
00410 void cmd_join(frommark, tomark, cmd, bang, extra)
00411         MARK    frommark;
00412         MARK    tomark;
00413         CMD     cmd;
00414         int     bang;
00415         char    *extra;
00416 {
00417         long    l;
00418         char    *scan;
00419         int     len;    /* length of the new line */
00420 
00421         /* if only one line is specified, assume the following one joins too */
00422         if (markline(frommark) == nlines)
00423         {
00424                 msg("Nothing to join with this line");
00425                 return;
00426         }
00427         if (markline(frommark) == markline(tomark))
00428         {
00429                 tomark += BLKSIZE;
00430         }
00431 
00432         /* get the first line */
00433         l = markline(frommark);
00434         strcpy(tmpblk.c, fetchline(l));
00435         len = strlen(tmpblk.c);
00436 
00437         /* build the longer line */
00438         while (++l <= markline(tomark))
00439         {
00440                 /* get the next line */
00441                 scan = fetchline(l);
00442 
00443                 /* remove any leading whitespace */
00444                 while (*scan == '\t' || *scan == ' ')
00445                 {
00446                         scan++;
00447                 }
00448 
00449                 /* see if the line will fit */
00450                 if (strlen(scan) + len + 3 > BLKSIZE)
00451                 {
00452                         msg("Can't join -- the resulting line would be too long");
00453                         return;
00454                 }
00455 
00456                 /* catenate it, with a space (or two) in between */
00457                 if (!bang)
00458                 {
00459                         if (len >= 1)
00460                         {
00461                                 if (tmpblk.c[len - 1] == '.'
00462                                  || tmpblk.c[len - 1] == '?'
00463                                  || tmpblk.c[len - 1] == '!')
00464                                 {
00465                                          tmpblk.c[len++] = ' ';
00466                                 }
00467                                 tmpblk.c[len++] = ' ';
00468                         }
00469                 }
00470                 strcpy(tmpblk.c + len, scan);
00471                 len += strlen(scan);
00472         }
00473         tmpblk.c[len++] = '\n';
00474         tmpblk.c[len] = '\0';
00475 
00476         /* make the change */
00477         ChangeText
00478         {
00479                 frommark &= ~(BLKSIZE - 1);
00480                 tomark &= ~(BLKSIZE - 1);
00481                 tomark += BLKSIZE;
00482                 change(frommark, tomark, tmpblk.c);
00483         }
00484 
00485         /* Reporting... */
00486         rptlines = markline(tomark) - markline(frommark) - 1L;
00487         rptlabel = "joined";
00488 }
00489 
00490 
00491 
00492 /*ARGSUSED*/
00493 void cmd_shift(frommark, tomark, cmd, bang, extra)
00494         MARK    frommark;
00495         MARK    tomark;
00496         CMD     cmd;
00497         int     bang;
00498         char    *extra;
00499 {
00500         long    l;      /* line number counter */
00501         int     oldidx; /* number of chars previously used for indent */
00502         int     newidx; /* number of chars in the new indent string */
00503         int     oldcol; /* previous indent amount */
00504         int     newcol; /* new indent amount */
00505         char    *text;  /* pointer to the old line's text */
00506 
00507         ChangeText
00508         {
00509                 /* for each line to shift... */
00510                 for (l = markline(frommark); l <= markline(tomark); l++)
00511                 {
00512                         /* get the line - ignore empty lines unless ! mode */
00513                         text = fetchline(l);
00514                         if (!*text && !bang)
00515                                 continue;
00516 
00517                         /* calc oldidx and oldcol */
00518                         for (oldidx = 0, oldcol = 0;
00519                              text[oldidx] == ' ' || text[oldidx] == '\t';
00520                              oldidx++)
00521                         {
00522                                 if (text[oldidx] == ' ')
00523                                 {
00524                                         oldcol += 1;
00525                                 }
00526                                 else
00527                                 {
00528                                         oldcol += *o_tabstop - (oldcol % *o_tabstop);
00529                                 }
00530                         }
00531 
00532                         /* calc newcol */
00533                         if (cmd == CMD_SHIFTR)
00534                         {
00535                                 newcol = oldcol + (*o_shiftwidth & 0xff);
00536                         }
00537                         else
00538                         {
00539                                 newcol = oldcol - (*o_shiftwidth & 0xff);
00540                                 if (newcol < 0)
00541                                         newcol = 0;
00542                         }
00543 
00544                         /* if no change, then skip to next line */
00545                         if (oldcol == newcol)
00546                                 continue;
00547 
00548                         /* build a new indent string */
00549                         newidx = 0;
00550                         if (*o_autotab)
00551                         {
00552                                 while (newcol >= *o_tabstop)
00553                                 {
00554                                         tmpblk.c[newidx++] = '\t';
00555                                         newcol -= *o_tabstop;
00556                                 }
00557                         }
00558                         while (newcol > 0)
00559                         {
00560                                 tmpblk.c[newidx++] = ' ';
00561                                 newcol--;
00562                         }
00563                         tmpblk.c[newidx] = '\0';
00564 
00565                         /* change the old indent string into the new */
00566                         change(MARK_AT_LINE(l), MARK_AT_LINE(l) + oldidx, tmpblk.c);
00567                 }
00568         }
00569 
00570         /* Reporting... */
00571         rptlines = markline(tomark) - markline(frommark) + 1L;
00572         if (cmd == CMD_SHIFTR)
00573         {
00574                 rptlabel = ">ed";
00575         }
00576         else
00577         {
00578                 rptlabel = "<ed";
00579         }
00580 }
00581 
00582 
00583 /*ARGSUSED*/
00584 void cmd_read(frommark, tomark, cmd, bang, extra)
00585         MARK    frommark;
00586         MARK    tomark;
00587         CMD     cmd;
00588         int     bang;
00589         char    *extra;
00590 {
00591         int     fd, rc; /* used while reading from the file */
00592         char    *scan;  /* used for finding NUL characters */
00593         int     hadnul; /* boolean: any NULs found? */
00594         int     addnl;  /* boolean: forced to add newlines? */
00595         int     len;    /* number of chars in current line */
00596         long    lines;  /* number of lines in current block */
00597         struct stat statb;
00598 
00599         /* special case: if ":r !cmd" then let the filter() function do it */
00600         if (extra[0] == '!')
00601         {
00602                 filter(frommark, MARK_UNSET, extra + 1, TRUE);
00603                 return;
00604         }
00605 
00606         /* open the file */
00607         fd = open(extra, O_RDONLY);
00608         if (fd < 0)
00609         {
00610                 msg("Can't open \"%s\"", extra);
00611                 return;
00612         }
00613 
00614 #ifndef CRUNCH
00615         if (stat(extra, &statb) < 0)
00616         {
00617                 msg("Can't stat \"%s\"", extra);
00618         }
00619 # if TOS
00620         if (statb.st_mode & S_IJDIR)
00621 # else
00622 #  if OSK
00623         if (statb.st_mode & S_IFDIR)
00624 #  else
00625         if ((statb.st_mode & S_IFMT) != S_IFREG)
00626 #  endif
00627 # endif
00628         {
00629                 msg("\"%s\" is not a regular file", extra);
00630                 return;
00631         }
00632 #endif /* not CRUNCH */
00633 
00634         /* get blocks from the file, and add them */
00635         ChangeText
00636         {
00637                 /* insertion starts at the line following frommark */
00638                 tomark = frommark = (frommark | (BLKSIZE - 1L)) + 1L;
00639                 len = 0;
00640                 hadnul = addnl = FALSE;
00641 
00642                 /* add an extra newline, so partial lines at the end of
00643                  * the file don't trip us up
00644                  */
00645                 add(tomark, "\n");
00646 
00647                 /* for each chunk of text... */
00648                 while ((rc = tread(fd, tmpblk.c, BLKSIZE - 1)) > 0)
00649                 {
00650                         /* count newlines, convert NULs, etc. ... */
00651                         for (lines = 0, scan = tmpblk.c; rc > 0; rc--, scan++)
00652                         {
00653                                 /* break up long lines */
00654                                 if (*scan != '\n' && len + 2 > BLKSIZE)
00655                                 {
00656                                         *scan = '\n';
00657                                         addnl = TRUE;
00658                                 }
00659 
00660                                 /* protect against NUL chars in file */
00661                                 if (!*scan)
00662                                 {
00663                                         *scan = 0x80;
00664                                         hadnul = TRUE;
00665                                 }
00666 
00667                                 /* starting a new line? */
00668                                 if (*scan == '\n')
00669                                 {
00670                                         /* reset length at newline */
00671                                         len = 0;
00672                                         lines++;
00673                                 }
00674                                 else
00675                                 {
00676                                         len++;
00677                                 }
00678                         }
00679 
00680                         /* add the text */
00681                         *scan = '\0';
00682                         add(tomark, tmpblk.c);
00683                         tomark += MARK_AT_LINE(lines) + len - markidx(tomark);
00684                 }
00685 
00686                 /* if partial last line, then retain that first newline */
00687                 if (len > 0)
00688                 {
00689                         msg("Last line had no newline");
00690                         tomark += BLKSIZE; /* <- for the rptlines calc */
00691                 }
00692                 else /* delete that first newline */
00693                 {
00694                         delete(tomark, (tomark | (BLKSIZE - 1L)) + 1L);
00695                 }
00696         }
00697 
00698         /* close the file */
00699         close(fd);
00700 
00701         /* Reporting... */
00702         rptlines = markline(tomark) - markline(frommark);
00703         rptlabel = "read";
00704         if (mode == MODE_EX)
00705         {
00706                 cursor = (tomark & ~BLKSIZE) - BLKSIZE;
00707         }
00708         else
00709         {
00710                 cursor = frommark;
00711         }
00712 
00713         if (addnl)
00714                 msg("Newlines were added to break up long lines");
00715         if (hadnul)
00716                 msg("NULs were converted to 0x80");
00717 }
00718 
00719 
00720 
00721 /*ARGSUSED*/
00722 void cmd_undo(frommark, tomark, cmd, bang, extra)
00723         MARK    frommark;
00724         MARK    tomark;
00725         CMD     cmd;
00726         int     bang;
00727         char    *extra;
00728 {
00729         undo();
00730 }
00731 
00732 
00733 /* print the selected lines */
00734 /*ARGSUSED*/
00735 void cmd_print(frommark, tomark, cmd, bang, extra)
00736         MARK    frommark;
00737         MARK    tomark;
00738         CMD     cmd;
00739         int     bang;
00740         char    *extra;
00741 {
00742         REG char        *scan;
00743         REG long        l;
00744         REG int         col;
00745 
00746         for (l = markline(frommark); l <= markline(tomark); l++)
00747         {
00748                 /* display a line number, if CMD_NUMBER */
00749                 if (cmd == CMD_NUMBER)
00750                 {
00751                         sprintf(tmpblk.c, "%6ld  ", l);
00752                         qaddstr(tmpblk.c);
00753                         col = 8;
00754                 }
00755                 else
00756                 {
00757                         col = 0;
00758                 }
00759 
00760                 /* get the next line & display it */
00761                 for (scan = fetchline(l); *scan; scan++)
00762                 {
00763                         /* expand tabs to the proper width */
00764                         if (*scan == '\t' && cmd != CMD_LIST)
00765                         {
00766                                 do
00767                                 {
00768                                         qaddch(' ');
00769                                         col++;
00770                                 } while (col % *o_tabstop != 0);
00771                         }
00772                         else if (*scan > 0 && *scan < ' ' || *scan == '\177')
00773                         {
00774                                 qaddch('^');
00775                                 qaddch(*scan ^ 0x40);
00776                                 col += 2;
00777                         }
00778                         else if ((*scan & 0x80) && cmd == CMD_LIST)
00779                         {
00780                                 sprintf(tmpblk.c, "\\%03o", UCHAR(*scan));
00781                                 qaddstr(tmpblk.c);
00782                                 col += 4;
00783                         }
00784                         else
00785                         {
00786                                 qaddch(*scan);
00787                                 col++;
00788                         }
00789 
00790                         /* wrap at the edge of the screen */
00791                         if (!has_AM && col >= COLS)
00792                         {
00793                                 addch('\n');
00794                                 col -= COLS;
00795                         }
00796                 }
00797                 if (cmd == CMD_LIST)
00798                 {
00799                         qaddch('$');
00800                 }
00801                 addch('\n');
00802                 exrefresh();
00803         }
00804 }
00805 
00806 
00807 /* move or copy selected lines */
00808 /*ARGSUSED*/
00809 void cmd_move(frommark, tomark, cmd, bang, extra)
00810         MARK    frommark;
00811         MARK    tomark;
00812         CMD     cmd;
00813         int     bang;
00814         char    *extra;
00815 {
00816         MARK    destmark;
00817 
00818         /* parse the destination linespec.  No defaults.  Line 0 is okay */
00819         destmark = cursor;
00820         if (!strcmp(extra, "0"))
00821         {
00822                 destmark = 0L;
00823         }
00824         else if (linespec(extra, &destmark) == extra || !destmark)
00825         {
00826                 msg("invalid destination address");
00827                 return;
00828         }
00829 
00830         /* flesh the marks out to encompass whole lines */
00831         frommark &= ~(BLKSIZE - 1);
00832         tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE;
00833         destmark = (destmark & ~(BLKSIZE - 1)) + BLKSIZE;
00834 
00835         /* make sure the destination is valid */
00836         if (cmd == CMD_MOVE && destmark >= frommark && destmark < tomark)
00837         {
00838                 msg("invalid destination address");
00839         }
00840 
00841         /* Do it */
00842         ChangeText
00843         {
00844                 /* save the text to a cut buffer */
00845                 cutname('\0');
00846                 cut(frommark, tomark);
00847 
00848                 /* if we're not copying, delete the old text & adjust destmark */
00849                 if (cmd != CMD_COPY)
00850                 {
00851                         delete(frommark, tomark);
00852                         if (destmark >= frommark)
00853                         {
00854                                 destmark -= (tomark - frommark);
00855                         }
00856                 }
00857 
00858                 /* add the new text */
00859                 paste(destmark, FALSE, FALSE);
00860         }
00861 
00862         /* move the cursor to the last line of the moved text */
00863         cursor = destmark + (tomark - frommark) - BLKSIZE;
00864         if (cursor < MARK_FIRST || cursor >= MARK_LAST + BLKSIZE)
00865         {
00866                 cursor = MARK_LAST;
00867         }
00868 
00869         /* Reporting... */
00870         rptlabel = ( (cmd == CMD_COPY) ? "copied" : "moved" );
00871 }
00872 
00873 
00874 
00875 /* execute EX commands from a file */
00876 /*ARGSUSED*/
00877 void cmd_source(frommark, tomark, cmd, bang, extra)
00878         MARK    frommark;
00879         MARK    tomark;
00880         CMD     cmd;
00881         int     bang;
00882         char    *extra;
00883 {
00884         /* must have a filename */
00885         if (!*extra)
00886         {
00887                 msg("\"source\" requires a filename");
00888                 return;
00889         }
00890 
00891         doexrc(extra);
00892 }
00893 
00894 
00895 #ifndef NO_AT
00896 /*ARGSUSED*/
00897 void cmd_at(frommark, tomark, cmd, bang, extra)
00898         MARK    frommark;
00899         MARK    tomark;
00900         CMD     cmd;
00901         int     bang;
00902         char    *extra;
00903 {
00904         static  nest = FALSE;
00905         int     result;
00906         char    buf[MAXRCLEN];
00907 
00908         /* don't allow nested macros */
00909         if (nest)
00910         {
00911                 msg("@ macros can't be nested");
00912                 return;
00913         }
00914         nest = TRUE;
00915 
00916         /* require a buffer name */
00917         if (*extra == '"')
00918                 extra++;
00919         if (!*extra || !isascii(*extra) ||!islower(*extra))
00920         {
00921                 msg("@ requires a cut buffer name (a-z)");
00922         }
00923 
00924         /* get the contents of the buffer */
00925         result = cb2str(*extra, buf, (unsigned)(sizeof buf));
00926         if (result <= 0)
00927         {
00928                 msg("buffer \"%c is empty", *extra);
00929         }
00930         else if (result >= sizeof buf)
00931         {
00932                 msg("buffer \"%c is too large to execute", *extra);
00933         }
00934         else
00935         {
00936                 /* execute the contents of the buffer as ex commands */
00937                 exstring(buf, result, '\\');
00938         }
00939 
00940         nest = FALSE;
00941 }
00942 #endif

Generated on Fri Apr 14 22:56:52 2006 for minix by  doxygen 1.4.6