home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / VILE327.ZIP / VILE327.TAR / vile3.27 / region.c < prev    next >
C/C++ Source or Header  |  1992-12-14  |  10KB  |  443 lines

  1. /*
  2.  * The routines in this file
  3.  * deal with the region, that magic space
  4.  * between "." and mark. Some functions are
  5.  * commands. Some functions are just for
  6.  * internal use.
  7.  *
  8.  * $Log: region.c,v $
  9.  * Revision 1.19  1992/12/04  09:20:58  foxharp
  10.  * deleted unused assigns
  11.  *
  12.  * Revision 1.18  1992/12/02  09:13:16  foxharp
  13.  * changes for "c-shiftwidth"
  14.  *
  15.  * Revision 1.17  1992/11/19  09:18:45  foxharp
  16.  * name change of kdelete() to ksetup(), and close off with kdone()
  17.  *
  18.  * Revision 1.16  1992/06/01  20:42:15  foxharp
  19.  * honor "tabinsert" mode in {en,de}tabline()
  20.  *
  21.  * Revision 1.15  1992/05/16  12:00:31  pgf
  22.  * prototypes/ansi/void-int stuff/microsoftC
  23.  *
  24.  * Revision 1.14  1992/02/26  21:57:20  pgf
  25.  * shift operators now go by shiftwidth, not tabstop
  26.  *
  27.  * Revision 1.13  1992/01/10  08:09:23  pgf
  28.  * added arg to do_fl_region, which is passed on to the function it calls
  29.  * vi pointer
  30.  *
  31.  * Revision 1.12  1992/01/05  00:06:13  pgf
  32.  * split mlwrite into mlwrite/mlprompt/mlforce to make errors visible more
  33.  * often.  also normalized message appearance somewhat.
  34.  *
  35.  * Revision 1.11  1991/11/27  10:09:09  pgf
  36.  * don't do left shifts on lines starting with # when we're in C mode.
  37.  * i'll bet someone's gonna complain about that.  let's give it a try
  38.  * anyway.
  39.  *
  40.  * Revision 1.10  1991/11/13  20:09:27  pgf
  41.  * X11 changes, from dave lemke
  42.  *
  43.  * Revision 1.9  1991/11/08  13:15:02  pgf
  44.  * yankregion now reports how much was yanked (proposed by dave lemke)
  45.  *
  46.  * Revision 1.8  1991/11/03  17:46:30  pgf
  47.  * removed f,n args from all region functions -- they don't use them,
  48.  * since they're no longer directly called by the user
  49.  *
  50.  * Revision 1.7  1991/11/01  14:38:00  pgf
  51.  * saber cleanup
  52.  *
  53.  * Revision 1.6  1991/10/28  14:26:15  pgf
  54.  * eliminated TABVAL macro -- now use curtabval directly
  55.  *
  56.  * Revision 1.5  1991/08/07  12:35:07  pgf
  57.  * added RCS log messages
  58.  *
  59.  * revision 1.4
  60.  * date: 1991/06/25 19:53:18;
  61.  * massive data structure restructure
  62.  * 
  63.  * revision 1.3
  64.  * date: 1991/06/16 17:40:10;
  65.  * fixed bug in shiftlregion due to not stopping at end of line when scanning
  66.  * for spaces, and
  67.  * added do_fl_region() wrapper routine to do full-line region processing, and
  68.  * rewrote shift[lr]region to use it
  69.  * 
  70.  * revision 1.2
  71.  * date: 1991/05/31 11:21:54;
  72.  * added endline pointer and offset to region struct and getregion() code
  73.  * 
  74.  * revision 1.1
  75.  * date: 1990/09/21 10:25:58;
  76.  * initial vile RCS revision
  77.  */
  78. #include        <stdio.h>
  79. #include    "estruct.h"
  80. #include        "edef.h"
  81.  
  82. #if    MEGAMAX & ST520
  83. overlay    "region"
  84. #endif
  85.  
  86. /*
  87.  * Kill the region. Ask "getregion"
  88.  * to figure out the bounds of the region.
  89.  * Move "." to the start, and kill the characters.
  90.  */
  91. int
  92. killregion()
  93. {
  94.         register int    s;
  95.         REGION          region;
  96.  
  97.         if ((s=getregion(®ion)) != TRUE)
  98.                 return s;
  99.     kregcirculate(TRUE);
  100.         ksetup();                      /* command, so do magic */
  101.     DOT = region.r_orig;
  102.     if (fulllineregions)
  103.         kregflag |= KLINES;
  104.     s = ldelete(region.r_size, TRUE);
  105.     kdone();
  106.     ukb = 0;
  107.         return s;
  108. }
  109.  
  110. /*
  111.  * Copy all of the characters in the
  112.  * region to the kill buffer. Don't move dot
  113.  * at all. This is a bit like a kill region followed
  114.  * by a yank.
  115.  */
  116. int
  117. yankregion()
  118. {
  119.     MARK        m;
  120.         register int    s;
  121.         REGION          region;
  122.  
  123.         if ((s=getregion(®ion)) != TRUE)
  124.                 return s;
  125.     kregcirculate(TRUE);
  126.         ksetup();
  127.     m = region.r_orig;
  128.     if (fulllineregions)
  129.         kregflag |= KLINES|KYANK;
  130.         while (region.r_size--) {
  131.                 if (is_at_end_of_line(m)) {  /* End of line.         */
  132.                         if ((s=kinsert('\n')) != TRUE) {
  133.                 ukb = 0;
  134.                                 return s;
  135.             }
  136.                         m.l = lforw(m.l);
  137.                         m.o = 0;
  138.                 } else {                        /* Middle of line.      */
  139.                         if ((s=kinsert(char_at(m))) != TRUE) {
  140.                 ukb = 0;
  141.                                 return s;
  142.             }
  143.                         ++m.o;
  144.                 }
  145.         }
  146.     if (klines)
  147.         mlwrite("[ %d line%c yanked]", klines,
  148.                     klines == 1 ? ' ':'s');
  149.     else
  150.         mlwrite("[ %d character%c yanked]", kchars, 
  151.                     kchars == 1 ? ' ':'s');
  152.     kdone();
  153.     ukb = 0;
  154.         return TRUE;
  155. }
  156.  
  157. /*
  158.  * insert a shiftwidth at the front of the line
  159.  * don't do it if we're in cmode and the line starts with '#'
  160.  */
  161. int
  162. shift_right_line()
  163. {
  164.     int s, t;
  165.     if (b_val(curbp, MDCMOD) &&
  166.         llength(DOT.l) > 0 && char_at(DOT) == '#')
  167.         return TRUE;
  168.     s = curswval;
  169.     t = curtabval;
  170.     DOT.o = 0;
  171.     if (s) {  /* try to just insert tabs if possible */
  172.         if (b_val(curbp,MDTABINSERT) && s >= t && (s % t == 0)) {
  173.             linsert(s/t, '\t');
  174.         } else {
  175.             detabline(TRUE);
  176.             DOT.o = 0;
  177.             linsert(s, ' ');
  178.         }
  179.         if (b_val(curbp,MDTABINSERT))
  180.             entabline(TRUE);
  181.     }
  182.     firstnonwhite(FALSE,1);
  183.     return TRUE;
  184. }
  185.  
  186. /*
  187.  * shift region right by a tab stop
  188.  */
  189. int
  190. shiftrregion()
  191. {
  192.     return do_fl_region(shift_right_line, 0);
  193. }
  194.  
  195. /*
  196.  * delete a shiftwidth-equivalent from the front of the line
  197.  */
  198. int
  199. shift_left_line()
  200. {
  201.     register int    i;
  202.     register int    lim;
  203.     register int    s;
  204.     register LINE *linep = DOT.l;
  205.  
  206.     i = 0;
  207.  
  208.     s = curswval;
  209.  
  210.     detabline(TRUE);
  211.  
  212.     /* examine the line to the end, or the first shiftwidth, whichever
  213.         comes first */
  214.     lim = (s < llength(linep)) ? s : llength(linep);
  215.  
  216.  
  217.     i = 0;
  218.     /* count the leading spaces */
  219.     while (lgetc(linep,i) == ' ' && i < lim)
  220.         i++;
  221.  
  222.     if (i != 0) { /* did we find space/tabs to kill? */
  223.         DOT.o = 0;
  224.         if ((s = ldelete((long)i,FALSE)) != TRUE)
  225.             return s;
  226.     }
  227.  
  228.     DOT.o = 0;
  229.     if (b_val(curbp,MDTABINSERT))
  230.         entabline(TRUE);
  231.     return TRUE;
  232. }
  233.  
  234. /*
  235.  * shift region left by a tab stop
  236.  */
  237. int
  238. shiftlregion()
  239. {
  240.     return do_fl_region(shift_left_line, 0);
  241. }
  242.  
  243. int
  244. _to_lower(c)
  245. int c;
  246. {
  247.     if (isupper(c))
  248.         return c ^ DIFCASE;
  249.     return -1;
  250. }
  251.  
  252. int
  253. _to_upper(c)
  254. int c;
  255. {
  256.     if (islower(c))
  257.         return c ^ DIFCASE;
  258.     return -1;
  259. }
  260.  
  261. int
  262. _to_caseflip(c)
  263. int c;
  264. {
  265.     if (isalpha(c))
  266.         return c ^ DIFCASE;
  267.     return -1;
  268. }
  269.  
  270. int
  271. flipregion()
  272. {
  273.     return charprocreg(_to_caseflip);
  274. }
  275.  
  276. int
  277. lowerregion()
  278. {
  279.     return charprocreg(_to_lower);
  280. }
  281.  
  282. int
  283. upperregion()
  284. {
  285.     return charprocreg(_to_upper);
  286. }
  287.  
  288. int
  289. charprocreg(func)
  290. int (*func)();
  291. {
  292.     MARK        m;
  293.         register int    c,nc;
  294.         register int    s;
  295.         REGION          region;
  296.  
  297.         if ((s=getregion(®ion)) != TRUE)
  298.                 return s;
  299.         lchange(WFHARD);
  300.     m = region.r_orig;
  301.         while (region.r_size--) {
  302.                 if (is_at_end_of_line(m)) {
  303.                         m.l = lforw(m.l);
  304.                         m.o = 0;
  305.                 } else {
  306.                         c = char_at(m);
  307.             nc = (func)(c);
  308.             if (nc != -1) {
  309.                 copy_for_undo(m.l);
  310.                                 put_char_at(m, nc);
  311.             }
  312.                         ++m.o;
  313.                 }
  314.         }
  315.         return TRUE;
  316. }
  317.  
  318. /*
  319.  * This routine figures out the
  320.  * bounds of the region in the current window, and
  321.  * fills in the fields of the "REGION" structure pointed
  322.  * to by "rp". Because the dot and mark are usually very
  323.  * close together, we scan outward from dot looking for
  324.  * mark. This should save time. Return a standard code.
  325.  */
  326. int
  327. getregion(rp)
  328. register REGION *rp;
  329. {
  330.         register LINE   *flp;
  331.         register LINE   *blp;
  332.         long fsize;
  333.         long bsize;
  334.  
  335.         if (MK.l == NULL) {
  336.                 mlforce("BUG: getregion: no mark set in this window");
  337.                 return FALSE;
  338.         }
  339.         if (sameline(DOT, MK)) {
  340.         if (fulllineregions) {
  341.                     rp->r_orig.l = DOT.l;
  342.                         rp->r_orig.o = 0;
  343.                     rp->r_end.l = lforw(DOT.l);
  344.                         rp->r_end.o = 0;
  345.                         rp->r_size = (long)llength(DOT.l)+1;
  346.             return TRUE;
  347.         }
  348.                 rp->r_orig.l = rp->r_end.l = DOT.l;
  349.                 if (DOT.o < MK.o) {
  350.                         rp->r_orig.o = DOT.o;
  351.                         rp->r_end.o = MK.o;
  352.                         rp->r_size = (long)(MK.o-DOT.o);
  353.                 } else {
  354.                         rp->r_orig.o = MK.o;
  355.                         rp->r_end.o = DOT.o;
  356.                         rp->r_size = (long)(DOT.o-MK.o);
  357.                 }
  358.                 return TRUE;
  359.         }
  360.         blp = DOT.l;
  361.         flp = DOT.l;
  362.     if (fulllineregions) {
  363.         bsize = (long)(llength(blp)+1);
  364.         fsize = (long)(llength(flp)+1);
  365.     } else {
  366.         bsize = (long)DOT.o;
  367.         fsize = (long)(llength(flp) - DOT.o + 1);
  368.     }
  369.         while ((flp!=curbp->b_line.l) || (lback(blp) != curbp->b_line.l)) {
  370.                 if (flp != curbp->b_line.l) {
  371.                         flp = lforw(flp);
  372.                         if (flp == MK.l) {
  373.                                 rp->r_orig = DOT;
  374.                 if (fulllineregions) {
  375.                     rp->r_orig.o = 0;
  376.                     rp->r_size = fsize + llength(MK.l)+1;
  377.                                     rp->r_end.l = lforw(flp);
  378.                     rp->r_end.o = 0;
  379.                                     return TRUE;
  380.                 }
  381.                 rp->r_size = fsize + MK.o;
  382.                                 rp->r_end = MK;
  383.                                 return TRUE;
  384.                         }
  385.                         fsize += llength(flp)+1;
  386.                 }
  387.                 if (lback(blp) != curbp->b_line.l) {
  388.                         blp = lback(blp);
  389.                         bsize += llength(blp)+1;
  390.                         if (blp == MK.l) {
  391.                                 rp->r_orig = MK;
  392.                 if (fulllineregions) {
  393.                     rp->r_orig.o = 0;
  394.                     rp->r_size = bsize;
  395.                                     rp->r_end.l = lforw(DOT.l);
  396.                     rp->r_end.o = 0;
  397.                                     return TRUE;
  398.                 }
  399.                                 rp->r_end = DOT;
  400.                 rp->r_size = bsize - MK.o;
  401.                                 return TRUE;
  402.                         }
  403.                 }
  404.         }
  405.         mlforce("BUG: lost mark");
  406.         return FALSE;
  407. }
  408.  
  409. int
  410. do_fl_region(lineprocfunc,arg)
  411. int (*lineprocfunc)();
  412. int arg;
  413. {
  414.         register LINE   *linep;
  415.         register int    s;
  416.         REGION          region;
  417.  
  418.     fulllineregions = TRUE;
  419.         if ((s=getregion(®ion)) != TRUE)
  420.                 return s;
  421.  
  422.     /* for each line in the region, ... */
  423.     for ( linep = region.r_orig.l;
  424.             linep != region.r_end.l; linep = lforw(linep) ) {
  425.  
  426.         /* nothing on the line? */
  427.         if (llength(linep) == 0)
  428.             continue;
  429.  
  430.         /* move through the region... */
  431.         DOT.l = linep;
  432.         DOT.o = 0;
  433.  
  434.         /* ...and process each line */
  435.         if ((s = (*lineprocfunc)(arg)) != TRUE)
  436.             return s;
  437.  
  438.         }
  439.     firstnonwhite(FALSE,1);
  440.         return TRUE;
  441. }
  442.  
  443.