home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / REGION.C < prev    next >
Text File  |  1991-09-07  |  16KB  |  568 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. #include        <stdio.h>
  9. #include    "estruct.h"
  10. #include    "eproto.h"
  11. #include        "edef.h"
  12. #include    "elang.h"
  13.  
  14. /*    reglines:    how many lines in the current region
  15.             used by the trim/entab/detab-region commands
  16. */
  17.  
  18. int PASCAL NEAR reglines()
  19.  
  20. {
  21.         register LINE *linep;    /* position while scanning */
  22.     register int n;        /* number of lines in this current region */
  23.         REGION region;
  24.  
  25.     /* check for a valid region first */
  26.         if (getregion(®ion) != TRUE)
  27.                 return(0);
  28.  
  29.     /* start at the top of the region.... */
  30.         linep = region.r_linep;
  31.     region.r_size += region.r_offset;
  32.         n = 0;
  33.  
  34.         /* scan the region... counting lines */
  35.         while (region.r_size > 0L) {
  36.         region.r_size -= llength(linep) + 1;
  37.         linep = lforw(linep);
  38.         n++;
  39.     }
  40.  
  41.     /* place us at the beginning of the region */
  42.         curwp->w_dotp = region.r_linep;
  43.         curwp->w_doto = region.r_offset;
  44.  
  45.         return(n);
  46. }
  47.  
  48. /*
  49.  * Kill the region. Ask "getregion"
  50.  * to figure out the bounds of the region.
  51.  * Move "." to the start, and kill the characters.
  52.  * Bound to "C-W".
  53.  */
  54. PASCAL NEAR killregion(f, n)
  55.  
  56. int f,n;    /* prefix flag and argument */
  57.  
  58. {
  59.         register int    s;
  60.         REGION          region;
  61.  
  62.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  63.         return(rdonly());    /* we are in read only mode    */
  64.         if ((s=getregion(®ion)) != TRUE)
  65.                 return(s);
  66.         if ((lastflag&CFKILL) == 0)             /* This is a kill type  */
  67.                 kdelete();                      /* command, so do magic */
  68.         thisflag |= CFKILL;                     /* kill buffer stuff.   */
  69.         curwp->w_dotp = region.r_linep;
  70.         curwp->w_doto = region.r_offset;
  71.         return(ldelete(region.r_size, TRUE));
  72. }
  73.  
  74. /*
  75.  * Copy all of the characters in the
  76.  * region to the kill buffer. Don't move dot
  77.  * at all. This is a bit like a kill region followed
  78.  * by a yank. Bound to "M-W".
  79.  */
  80. PASCAL NEAR copyregion(f, n)
  81.  
  82. int f,n;    /* prefix flag and argument */
  83.  
  84. {
  85.         register LINE   *linep;
  86.         register int    loffs;
  87.         register int    s;
  88.         REGION          region;
  89.  
  90.         if ((s=getregion(®ion)) != TRUE)
  91.                 return(s);
  92.         if ((lastflag&CFKILL) == 0)             /* Kill type command.   */
  93.                 kdelete();
  94.         thisflag |= CFKILL;
  95.         linep = region.r_linep;                 /* Current line.        */
  96.         loffs = region.r_offset;                /* Current offset.      */
  97.         while (region.r_size--) {
  98.                 if (loffs == llength(linep)) {  /* End of line.         */
  99.                         if ((s=kinsert(FORWARD, '\r')) != TRUE)
  100.                                 return(s);
  101.                         linep = lforw(linep);
  102.                         loffs = 0;
  103.                 } else {                        /* Middle of line.      */
  104.                         if ((s=kinsert(FORWARD, lgetc(linep, loffs))) != TRUE)
  105.                                 return(s);
  106.                         ++loffs;
  107.                 }
  108.         }
  109.     mlwrite(TEXT70);
  110. /*              "[region copied]" */
  111.         return(TRUE);
  112. }
  113.  
  114. /*
  115.  * Lower case region. Zap all of the upper
  116.  * case characters in the region to lower case. Use
  117.  * the region code to set the limits. Scan the buffer,
  118.  * doing the changes. Call "lchange" to ensure that
  119.  * redisplay is done in all buffers. Bound to
  120.  * "C-X C-L".
  121.  */
  122. PASCAL NEAR lowerregion(f, n)
  123.  
  124. int f,n;    /* prefix flag and argument */
  125.  
  126. {
  127.         register LINE   *linep;
  128.         register int    loffs;
  129.         register int    s;
  130.         int c;
  131.         REGION          region;
  132.  
  133.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  134.         return(rdonly());    /* we are in read only mode    */
  135.         if ((s=getregion(®ion)) != TRUE)
  136.                 return(s);
  137.         lchange(WFHARD);
  138.         linep = region.r_linep;
  139.         loffs = region.r_offset;
  140.         while (region.r_size--) {
  141.                 if (loffs == llength(linep)) {
  142.                         linep = lforw(linep);
  143.                         loffs = 0;
  144.                 } else {
  145.                         c = lgetc(linep, loffs);
  146.             c = lowerc(c);
  147.                         lputc(linep, loffs, c);
  148.                         ++loffs;
  149.                 }
  150.         }
  151.         return(TRUE);
  152. }
  153.  
  154. /*
  155.  * Upper case region. Zap all of the lower
  156.  * case characters in hüSRCo upper case. Use
  157.  * the region code to set the limits. Scan the buffer,
  158.  * doing the changes. Call "lchange" to ensure that
  159.  * redisplay is done in all buffers. Bound to
  160.  * "C-X C-L".
  161.  */
  162. PASCAL NEAR upperregion(f, n)
  163.  
  164. int f,n;    /* prefix flag and argument */
  165.  
  166. {
  167.         register LINE   *linep;
  168.         register int    loffs;
  169.         register int    s;
  170.         int c;
  171.         REGION          region;
  172.  
  173.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  174.         return(rdonly());    /* we are in read only mode    */
  175.         if ((s=getregion(®ion)) != TRUE)
  176.                 return(s);
  177.         lchange(WFHARD);
  178.         linep = region.r_linep;
  179.         loffs = region.r_offset;
  180.         while (region.r_size--) {
  181.                 if (loffs == llength(linep)) {
  182.                         linep = lforw(linep);
  183.                         loffs = 0;
  184.                 } else {
  185.                         c = lgetc(linep, loffs);
  186.             c = upperc(c);
  187.                         lputc(linep, loffs, c);
  188.                         ++loffs;
  189.                 }
  190.         }
  191.         return(TRUE);
  192. }
  193.  
  194. /*    Narrow-to-region (^X-<) makes all but the current region in
  195.     the current buffer invisable and unchangable
  196. */
  197.  
  198. PASCAL NEAR narrow(f, n)
  199.  
  200. int f,n;    /* prefix flag and argument */
  201.  
  202. {
  203.         register int status;    /* return status */
  204.     BUFFER *bp;        /* buffer being narrowed */
  205.     SCREEN *scrp;        /* screen to fix pointers in */
  206.     WINDOW *wp;        /* windows to fix up pointers in as well */
  207.     REGION creg;        /* region boundry structure */
  208.     int cmark;        /* current mark */
  209.  
  210.     /* find the proper buffer and make sure we aren't already narrow */
  211.     bp = curwp->w_bufp;        /* find the right buffer */
  212.     if (bp->b_flag&BFNAROW) {
  213.         mlwrite(TEXT71);
  214. /*                      "%%This buffer is already narrowed" */
  215.         return(FALSE);
  216.     }
  217.  
  218.     /* find the boundries of the current region */
  219.         if ((status=getregion(&creg)) != TRUE)
  220.                 return(status);
  221.         curwp->w_dotp = creg.r_linep;    /* only by full lines please! */
  222.         curwp->w_doto = 0;
  223.     creg.r_size += (long)creg.r_offset;
  224.     if (creg.r_size <= (long)curwp->w_dotp->l_used) {
  225.         mlwrite(TEXT72);
  226. /*                      "%%Must narrow at least 1 full line" */
  227.         return(FALSE);
  228.     }
  229.  
  230.     /* archive the top fragment */
  231.     if (bp->b_linep->l_fp != creg.r_linep) {
  232.         bp->b_topline = bp->b_linep->l_fp;
  233.         creg.r_linep->l_bp->l_fp = (LINE *)NULL;
  234.         bp->b_linep->l_fp = creg.r_linep;
  235.         creg.r_linep->l_bp = bp->b_linep;
  236.     }
  237.  
  238.     /* move forward to the end of this region
  239.        (a long number of bytes perhaps) */
  240.     while (creg.r_size > (long)32000) {
  241.         forwchar(TRUE, 32000);
  242.         creg.r_size -= (long)32000;
  243.     }
  244.     forwchar(TRUE, (int)creg.r_size);
  245.     curwp->w_doto = 0;        /* only full lines! */
  246.  
  247.     /* archive the bottom fragment */
  248.     if (bp->b_linep != curwp->w_dotp) {
  249.         bp->b_botline = curwp->w_dotp;
  250.         bp->b_botline->l_bp->l_fp = bp->b_linep;
  251.         bp->b_linep->l_bp->l_fp = (LINE *)NULL;
  252.         bp->b_linep->l_bp = bp->b_botline->l_bp;
  253.     }
  254.  
  255.     /* in all screens.... */
  256.     scrp = first_screen;
  257.     while (scrp) {
  258.  
  259.         /* let all the proper windows be updated */
  260.         wp = scrp->s_first_window;
  261.         while (wp) {
  262.             if (wp->w_bufp == bp) {
  263.                 wp->w_linep = creg.r_linep;
  264.                 wp->w_dotp = creg.r_linep;
  265.                 wp->w_doto = 0;
  266.                 for (cmark = 0; cmark < NMARKS; cmark++) {
  267.                     wp->w_markp[cmark] = creg.r_linep;
  268.                     wp->w_marko[cmark] = 0;
  269.                 }
  270.                 wp->w_flag |= (WFHARD|WFMODE);
  271.             }
  272.             wp = wp->w_wndp;
  273.         }
  274.  
  275.         /* next screen! */
  276.         scrp = scrp->s_next_screen;
  277.     }
  278.  
  279.     /* and now remember we are narrowed */
  280.     bp->b_flag |= BFNAROW;
  281.     mlwrite(TEXT73);
  282. /*              "[Buffer is narrowed]" */
  283.         return(TRUE);
  284. }
  285.  
  286. /*    widen-from-region (^X->) restores a narrowed region    */
  287.  
  288. PASCAL NEAR widen(f, n)
  289.  
  290. int f,n;    /* prefix flag and argument */
  291.  
  292. {
  293.     LINE *lp;    /* temp line pointer */
  294.     BUFFER *bp;    /* buffer being narrowed */
  295.     SCREEN *scrp;    /* screen to fix pointers in */
  296.     WINDOW *wp;    /* windows to fix up pointers in as well */
  297.     int cmark;    /* current mark */
  298.  
  299.     /* find the proper buffer and make sure we are narrow */
  300.     bp = curwp->w_bufp;        /* find the right buffer */
  301.     if ((bp->b_flag&BFNAROW) == 0) {
  302.         mlwrite(TEXT74);
  303. /*                      "%%This buffer is not narrowed" */
  304.         return(FALSE);
  305.     }
  306.  
  307.     /* recover the top fragment */
  308.     if (bp->b_topline != (LINE *)NULL) {
  309.         lp = bp->b_topline;
  310.         while (lp->l_fp != (LINE *)NULL)
  311.             lp = lp->l_fp;
  312.         lp->l_fp = bp->b_linep->l_fp;
  313.         lp->l_fp->l_bp = lp;
  314.         bp->b_linep->l_fp = bp->b_topline;
  315.         bp->b_topline->l_bp = bp->b_linep;
  316.         bp->b_topline = (LINE *)NULL;
  317.     }
  318.  
  319.     /* recover the bottom fragment */
  320.     if (bp->b_botline != (LINE *)NULL) {
  321.  
  322.         /* if the point is at EOF, move it to
  323.            the beginning of the bottom fragment */
  324.         if (curwp->w_dotp == bp->b_linep) {
  325.             curwp->w_dotp = bp->b_botline;
  326.             curwp->w_doto = 0;        /* this should be redundent */
  327.         }
  328.     
  329.         /* if any marks are at EOF, move them to
  330.            the beginning of the bottom fragment */
  331.         for (cmark = 0; cmark < NMARKS; cmark++) {
  332.             if (curwp->w_markp[cmark] == bp->b_linep) {
  333.                 curwp->w_markp[cmark] = bp->b_botline;
  334.                 curwp->w_marko[cmark] = 0;
  335.             }
  336.         }
  337.  
  338.         /* connect the bottom fragment */
  339.         lp = bp->b_botline;
  340.         while (lp->l_fp != (LINE *)NULL)
  341.             lp = lp->l_fp;
  342.         lp->l_fp = bp->b_linep;
  343.         bp->b_linep->l_bp->l_fp = bp->b_botline;
  344.         bp->b_botline->l_bp = bp->b_linep->l_bp;
  345.         bp->b_linep->l_bp = lp;
  346.         bp->b_botline = (LINE *)NULL;
  347.     }
  348.  
  349.     /* in all screens.... */
  350.     scrp = first_screen;
  351.     while (scrp) {
  352.  
  353.         /* let all the proper windows be updated */
  354.         wp = scrp->s_first_window;
  355.         while (wp) {
  356.             if (wp->w_bufp == bp)
  357.                 wp->w_flag |= (WFHARD|WFMODE);
  358.             wp = wp->w_wndp;
  359.         }
  360.  
  361.         /* next screen! */
  362.         scrp = scrp->s_next_screen;
  363.     }
  364.  
  365.     /* and now remember we are not narrowed */
  366.     bp->b_flag &= (~BFNAROW);
  367.     mlwrite(TEXT75);
  368. /*              "[Buffer is widened]" */
  369.         return(TRUE);
  370. }
  371.  
  372. /*
  373.  * This routine figures out the bounds of the region in the current
  374.  * window, and fills in the fields of the "REGION" structure pointed to by
  375.  * "rp". Because the dot and mark are usually very close together, we scan
  376.  * outward from dot looking for mark. This should save time. Return a
  377.  * standard code. Callers of this routine should be prepared to get an
  378.  * "ABORT" status; we might make this have the confirm thing later.
  379.  */
  380.  
  381. PASCAL NEAR getregion(rp)
  382.  
  383. register REGION *rp;
  384.  
  385. {
  386.         register LINE   *flp;
  387.         register LINE   *blp;
  388.         long fsize;
  389.         long bsize;
  390.  
  391.         if (curwp->w_markp[0] == (LINE *)NULL) {
  392.                 mlwrite(TEXT76);
  393. /*                      "No mark set in this window" */
  394.                 return(FALSE);
  395.         }
  396.         if (curwp->w_dotp == curwp->w_markp[0]) {
  397.                 rp->r_linep = curwp->w_dotp;
  398.                 if (curwp->w_doto < curwp->w_marko[0]) {
  399.                         rp->r_offset = curwp->w_doto;
  400.                         rp->r_size = (long)(curwp->w_marko[0]-curwp->w_doto);
  401.                 } else {
  402.                         rp->r_offset = curwp->w_marko[0];
  403.                         rp->r_size = (long)(curwp->w_doto-curwp->w_marko[0]);
  404.                 }
  405.                 return(TRUE);
  406.         }
  407.         blp = curwp->w_dotp;
  408.         bsize = (long)curwp->w_doto;
  409.         flp = curwp->w_dotp;
  410.         fsize = (long)(llength(flp)-curwp->w_doto+1);
  411.         while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
  412.                 if (flp != curbp->b_linep) {
  413.                         flp = lforw(flp);
  414.                         if (flp == curwp->w_markp[0]) {
  415.                                 rp->r_linep = curwp->w_dotp;
  416.                                 rp->r_offset = curwp->w_doto;
  417.                                 rp->r_size = fsize+curwp->w_marko[0];
  418.                                 return(TRUE);
  419.                         }
  420.                         fsize += llength(flp)+1;
  421.                 }
  422.                 if (lback(blp) != curbp->b_linep) {
  423.                         blp = lback(blp);
  424.                         bsize += llength(blp)+1;
  425.                         if (blp == curwp->w_markp[0]) {
  426.                                 rp->r_linep = blp;
  427.                                 rp->r_offset = curwp->w_marko[0];
  428.                                 rp->r_size = bsize - curwp->w_marko[0];
  429.                                 return(TRUE);
  430.                         }
  431.                 }
  432.         }
  433.         mlwrite(TEXT77);
  434. /*              "Bug: lost mark" */
  435.         return(FALSE);
  436. }
  437.  
  438. /*
  439.  * Copy all of the characters in the region to the string buffer.
  440.  * It is assumed that the buffer size is at least one plus the
  441.  * region size.
  442.  */
  443. char *PASCAL NEAR regtostr(buf, region)
  444.  
  445. char *buf;
  446. REGION *region;
  447.  
  448. {
  449.     register LINE    *linep;
  450.     register int    loffs;
  451.     register long    rsize;
  452.     register char    *ptr;
  453.  
  454.     ptr = buf;
  455.     linep = region->r_linep;        /* Current line.    */
  456.     loffs = region->r_offset;        /* Current offset.    */
  457.     rsize = region->r_size;
  458.     while (rsize--) {
  459.         if (loffs == llength(linep)) {    /* End of line.        */
  460.             *ptr = '\r';
  461.             linep = lforw(linep);
  462.             loffs = 0;
  463.         } else {            /* Middle of line.    */
  464.             *ptr = lgetc(linep, loffs);
  465.             ++loffs;
  466.         }
  467.         ptr++;
  468.     }
  469.     *ptr = '\0';
  470.     return buf;
  471. }
  472.  
  473. char *PASCAL NEAR getreg(value)    /* return some of the contents of the current region */
  474.  
  475. char *value;
  476.  
  477. {
  478.     REGION region;
  479.  
  480.     /* get the region limits */
  481.     if (getregion(®ion) != TRUE)
  482.         return(errorm);
  483.  
  484.     /* don't let the region be larger than a string can hold */
  485.     if (region.r_size >= NSTRING)
  486.         region.r_size = NSTRING - 1;
  487.     return(regtostr(value, ®ion));
  488. }
  489.  
  490.  
  491. PASCAL NEAR indent_region(f, n)    /* indent a region n tab-stops */
  492.  
  493. int f,n;    /* default flag and numeric repeat count */
  494.  
  495. {
  496.     register int inc;    /* increment to next line [sgn(n)] */
  497.     int count;
  498.  
  499.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  500.         return(rdonly());    /* we are in read only mode    */
  501.  
  502.     if (f == FALSE)
  503.         count = 1;
  504.     else
  505.         count = n;
  506.     n = reglines();
  507.  
  508.     /* loop thru indenting n lines */
  509.     inc = ((n > 0) ? 1 : -1);
  510.     while (n) {
  511.         curwp->w_doto = 0;    /* start at the beginning */
  512.  
  513.         /* shift current line using tabs */
  514.         if (!((curbp->b_mode & MDCMOD) &&
  515.              (lgetc(curwp->w_dotp, curwp->w_doto) == '#')) ) {
  516.                 linsert(count, '\t');
  517.         }
  518.  
  519.         /* advance/or back to the next line */
  520.         forwline(TRUE, inc);
  521.         n -= inc;
  522.     }
  523.  
  524.     curwp->w_doto = 0;
  525.     thisflag &= ~CFCPCN;    /* flag that this resets the goal column */
  526.     lchange(WFEDIT);    /* yes, we have made at least an edit */
  527.     return(TRUE);
  528. }
  529.  
  530. PASCAL NEAR undent_region(f, n)    /* undent a region n tab-stops */
  531.  
  532. int f,n;    /* default flag and numeric repeat count */
  533.  
  534. {
  535.     register int inc;    /* increment to next line [sgn(n)] */
  536.     int i, count;
  537.  
  538.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  539.         return(rdonly());    /* we are in read only mode    */
  540.  
  541.     if (f == FALSE)
  542.         count = 1;
  543.     else
  544.         count = n;
  545.     n = reglines();
  546.  
  547.     /* loop thru undenting n lines */
  548.     inc = ((n > 0) ? 1 : -1);
  549.     while (n) {
  550.         /* unshift current line using tabs */
  551.         for (i = 0; i < count; i++) {
  552.             curwp->w_doto = 0;    /* start at the beginning */
  553.             if ((curwp->w_dotp->l_used > 0) &&
  554.                 (lgetc(curwp->w_dotp, curwp->w_doto) == '\t')) {
  555.                 ldelete(1L, FALSE);
  556.             }
  557.         }
  558.  
  559.         /* advance/or back to the next line */
  560.         forwline(TRUE, inc);
  561.         n -= inc;
  562.     }
  563.  
  564.     thisflag &= ~CFCPCN;    /* flag that this resets the goal column */
  565.     lchange(WFEDIT);    /* yes, we have made at least an edit */
  566.     return(TRUE);
  567. }
  568.