home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progc / ce331src.arj / REGION.C < prev    next >
C/C++ Source or Header  |  1991-03-10  |  14KB  |  590 lines

  1. /*
  2.  *    R E G I O N . C
  3.  *
  4.  *    purpose:
  5.  *        The routines in this file deal with the region, that magic space
  6.  *        between dot and mark. Some functions are commands. Some functions
  7.  *        are just for internal use.
  8.  */
  9.  
  10. #include <stdio.h>            /* Turbo C++ verison 1.0 */
  11. #include <dos.h>
  12.  
  13. #include <pdefs.h>            /* PforCe version 1.05 (includes jwg.h) */
  14. #include <pf_ansi.h>
  15.  
  16. #include "struct.h"
  17. #include "def.h"
  18. #include "protos.h"
  19.  
  20. /*
  21.  * local function prototypes
  22.  */
  23.  
  24. static int near        getregion(struct region *, int);
  25.  
  26. /**
  27.  * Get the number of lines in the current region
  28.  *    (used by the Detab/Entab/Trim commands)
  29.  *
  30.  *    Note the difference here from emacs 3.10 functionality.  I return n = 1
  31.  *    if there is no defined region, so Detab, Entab and Trim work just like
  32.  *    they did in the past, i.e., they work on the current line if given no
  33.  *    numeric argument.
  34.  */
  35. int RegionLines()
  36. {
  37.   LINE        *linep;    /* position while scanning */
  38.   int        n;        /* number of lines in this current region */
  39.   REGION    region;
  40.  
  41.     /* check for a valid region first */
  42.     if (getregion(®ion, FALSE) != TRUE)
  43.         return(1);                    /* just do the current line */
  44.  
  45.     /* start at the top of the region */
  46.     linep = region.r_linep;
  47.     region.r_size += region.r_offset;
  48.     n = 0;
  49.  
  50.     /* scan the region, counting lines */
  51.     while (region.r_size > 0L)
  52.     {
  53.         region.r_size -= llength(linep) + 1;
  54.         linep = lforw(linep);
  55.         n++;
  56.     }
  57.  
  58.     /* place us at the beginning of the region */
  59.     curwp->w_dotp = region.r_linep;
  60.     curwp->w_doto = region.r_offset;
  61.  
  62.     return(n);
  63. }
  64.  
  65. /**
  66.  * Kill the region. Ask "getregion" to figure out the bounds of the region.
  67.  * Move dot to the start, and kill the characters.
  68.  */
  69. int KillRegion(f, n)
  70.   int        f, n;
  71. {
  72.   REGION    region;
  73.  
  74.     if (curbp->b_mode & MDVIEW)     /* don't allow this command if */
  75.         return(ReadOnly());            /* we are in read only mode */
  76.     if (!getregion(®ion, TRUE))
  77.         return(FALSE);
  78.     if ((lastflag & CFKILL) == 0)    /* this is a kill type command, so do */
  79.         KDelete();                    /* magic kill buffer stuff */
  80.     thisflag |= CFKILL;
  81.     curwp->w_dotp = region.r_linep;
  82.     curwp->w_doto = region.r_offset;
  83.     return(LDelete(region.r_size, TRUE));
  84. }
  85.  
  86. /**
  87.  * Copy all of the characters in the region to the kill buffer. Don't move
  88.  * dot at all. This is a bit like a KillRegion followed by a Yank.
  89.  */
  90. int CopyRegion(f, n)
  91.   int        f, n;
  92. {
  93.   LINE        *linep;
  94.   int         loffs;
  95.   REGION    region;
  96.  
  97.     if (!getregion(®ion, TRUE))
  98.         return(FALSE);
  99.     if ((lastflag & CFKILL) == 0)        /* kill type command */
  100.         KDelete();
  101.     thisflag |= CFKILL;
  102.     linep = region.r_linep;             /* current line */
  103.     loffs = region.r_offset;            /* current offset */
  104.     while (region.r_size--)
  105.     {
  106.         if (loffs == llength(linep))    /* end of line */
  107.         {
  108.             if (!KInsert('\n'))
  109.                 return(FALSE);
  110.             linep = lforw(linep);
  111.             loffs = 0;
  112.         }
  113.         else                            /* middle of line */
  114.         {
  115.             if (!KInsert(lgetc(linep, loffs)))
  116.                 return(FALSE);
  117.             ++loffs;
  118.         }
  119.     }
  120.     MlWrite("Region copied");
  121.     return(TRUE);
  122. }
  123.  
  124. /**
  125.  * Move region. Insert the characters between mark and anchor at dot.
  126.  */
  127. int MoveRegion(f, n)
  128.   int        f, n;
  129. {
  130.   LINE        *odotp;
  131.   short        odoto;
  132.   int        status;
  133.  
  134.     if (curwp->w_anchorp == NULLLPTR)
  135.     {
  136.         MlWrite("No anchor set in this window");
  137.         return(FALSE);
  138.     }
  139.  
  140.     /*
  141.      * if you can't fix it, call it a feature
  142.      */
  143.     if (curwp->w_dotp == curwp->w_anchorp)
  144.     {
  145.         MlWrite("Can't move within same line");
  146.         PcPutC(BELL);
  147.         return(FALSE);
  148.     }
  149.  
  150.     odotp = curwp->w_dotp;
  151.     odoto = curwp->w_doto;
  152.     curwp->w_dotp = curwp->w_anchorp;
  153.     curwp->w_doto = curwp->w_anchoro;
  154.     status = KillRegion(TRUE, 1);
  155.     curwp->w_dotp = odotp;
  156.     curwp->w_doto = odoto;
  157.     if (status)
  158.         status = Yank(TRUE, 1);
  159.     return(status);
  160. }
  161.  
  162. /**
  163.  * Lower case region. Zap all of the upper case characters in the region to
  164.  * lower case. Use the region code to set the limits. Scan the buffer, doing
  165.  * the changes. Call "LChange" to ensure that redisplay is done in all buffers.
  166.  */
  167. int LowerRegion(f, n)
  168.   int        f, n;
  169. {
  170.   LINE        *linep;
  171.   int        loffs;
  172.   int        c;
  173.   REGION    region;
  174.  
  175.     if (curbp->b_mode & MDVIEW)         /* don't allow this command if */
  176.         return(ReadOnly());                /* we are in read only mode */
  177.     if (!getregion(®ion, TRUE))
  178.         return(FALSE);
  179.     LChange(WFHARD);
  180.     linep = region.r_linep;
  181.     loffs = region.r_offset;
  182.     while (region.r_size--)
  183.     {
  184.         if (loffs == llength(linep))
  185.         {
  186.             linep = lforw(linep);
  187.             loffs = 0;
  188.         }
  189.         else
  190.         {
  191.             c = lgetc(linep, loffs);
  192.             if (c >= 'A' && c <= 'Z')
  193.                 lputc(linep, loffs, (char)c ^ 0x20);
  194.             ++loffs;
  195.         }
  196.     }
  197.     return(TRUE);
  198. }
  199.  
  200. /**
  201.  * Upper case region. Zap all of the lower case characters in the region to
  202.  * upper case. Use the region code to set the limits. Scan the buffer, doing
  203.  * the changes. Call "LChange" to ensure that redisplay is done in all buffers.
  204.  */
  205. int UpperRegion(f, n)
  206.   int        f, n;
  207. {
  208.   LINE        *linep;
  209.   int        loffs;
  210.   int        c;
  211.   REGION    region;
  212.  
  213.     if (curbp->b_mode & MDVIEW)         /* don't allow this command if */
  214.         return(ReadOnly());                /* we are in read only mode */
  215.     if (!getregion(®ion, TRUE))
  216.         return(FALSE);
  217.     LChange(WFHARD);
  218.     linep = region.r_linep;
  219.     loffs = region.r_offset;
  220.     while (region.r_size--)
  221.     {
  222.         if (loffs == llength(linep))
  223.         {
  224.             linep = lforw(linep);
  225.             loffs = 0;
  226.         }
  227.         else
  228.         {
  229.             c = lgetc(linep, loffs);
  230.             if (c >= 'a' && c <= 'z')
  231.                 lputc(linep, loffs, (char)c ^ 0x20);
  232.             ++loffs;
  233.         }
  234.     }
  235.     return(TRUE);
  236. }
  237.  
  238. /**
  239.  * Make all but the current region in the current buffer invisible
  240.  * and unchangable
  241.  */
  242. int Narrow(f, n)
  243.   int        f, n;
  244. {
  245.   int        status;        /* return status */
  246.   BUFFER    *bp;        /* buffer being narrowed */
  247.   WINDOW    *wp;        /* windows to fix up pointers in as well */
  248.   REGION    region;        /* region Boundry structure */
  249. #if BMARKS
  250.   int        bmark;
  251. #endif
  252.  
  253.     /* find the proper buffer and make sure we aren't already Narrow */
  254.     bp = curwp->w_bufp;                /* find the right buffer */
  255.     if (bp->b_flag & BFNAROW)
  256.     {
  257.         MlWrite("This buffer is already narrowed");
  258.         return(FALSE);
  259.     }
  260.  
  261.     /* find the boundries of the current region */
  262.     if ((status = getregion(®ion, TRUE)) != TRUE)
  263.         return(status);
  264.     curwp->w_dotp = region.r_linep;    /* only by full lines please! */
  265.     curwp->w_doto = 0;
  266.     region.r_size += (long)region.r_offset;
  267.     if (region.r_size <= (long)curwp->w_dotp->l_used)
  268.     {
  269.         MlWrite("Must Narrow at least 1 full line");
  270.         return(FALSE);
  271.     }
  272.  
  273.     /* archive the top fragment */
  274.     if (bp->b_linep->l_fp != region.r_linep)
  275.     {
  276.         bp->b_topline = bp->b_linep->l_fp;
  277.         region.r_linep->l_bp->l_fp = NULLLPTR;
  278.         bp->b_linep->l_fp = region.r_linep;
  279.         region.r_linep->l_bp = bp->b_linep;
  280.     }
  281.  
  282.     /* move forward to the end of this region (a long number of bytes perhaps)*/
  283.     while (region.r_size > (long)32000)
  284.     {
  285.         ForwChar(TRUE, 32000);
  286.         region.r_size -= (long)32000;
  287.     }
  288.     ForwChar(TRUE, (int)region.r_size);
  289.     curwp->w_doto = 0;                /* only full lines! */
  290.  
  291.     /* archive the bottom fragment */
  292.     if (bp->b_linep != curwp->w_dotp)
  293.     {
  294.         bp->b_botline = curwp->w_dotp;
  295.         bp->b_botline->l_bp->l_fp = bp->b_linep;
  296.         bp->b_linep->l_bp->l_fp = NULLLPTR;
  297.         bp->b_linep->l_bp = bp->b_botline->l_bp;
  298.     }
  299.  
  300.     /* let all the proper windows be updated */
  301.     wp = wheadp;
  302.     while (wp)
  303.     {
  304.         if (wp->w_bufp == bp)
  305.         {
  306.             wp->w_linep = region.r_linep;
  307.             wp->w_dotp = region.r_linep;
  308.             wp->w_doto = 0;
  309.             wp->w_markp = region.r_linep;
  310.             wp->w_marko = 0;
  311.             wp->w_anchorp = region.r_linep;
  312.             wp->w_anchoro = 0;
  313.             wp->w_fcol = 0;
  314. #if BMARKS
  315.             for (bmark = 0; bmark < NBMARKS; bmark++)
  316.             {
  317.                 wp->w_bmarkp[bmark] = region.r_linep;
  318.                 wp->w_bmarko[bmark] = 0;
  319.             }
  320. #endif
  321.             wp->w_flag |= WFHARD | WFMODE;
  322.         }
  323.         wp = wp->w_wndp;
  324.     }
  325.  
  326.     /* and now remember we are narrowed */
  327.     bp->b_flag |= BFNAROW;
  328.     MlWrite("Buffer is narrowed");
  329.         return(TRUE);
  330. }
  331.  
  332. /**
  333.  * Restore a narrowed region
  334.  */
  335. int Widen(f, n)
  336.   int        f, n;
  337. {
  338.   LINE        *lp;    /* temp line pointer */
  339.   BUFFER    *bp;    /* buffer being narrowed */
  340.   WINDOW    *wp;    /* windows to fix up pointers in as well */
  341.  
  342.     /* find the proper buffer and make sure we are Narrow */
  343.     bp = curwp->w_bufp;                /* find the right buffer */
  344.     if ((bp->b_flag & BFNAROW) == 0)
  345.     {
  346.         MlWrite("This buffer is not narrowed");
  347.         return(FALSE);
  348.     }
  349.  
  350.     /* recover the top fragment */
  351.     if (bp->b_topline != NULLLPTR)
  352.     {
  353.         lp = bp->b_topline;
  354.         while (lp->l_fp != NULLLPTR)
  355.             lp = lp->l_fp;
  356.         lp->l_fp = bp->b_linep->l_fp;
  357.         lp->l_fp->l_bp = lp;
  358.         bp->b_linep->l_fp = bp->b_topline;
  359.         bp->b_topline->l_bp = bp->b_linep;
  360.         bp->b_topline = NULLLPTR;
  361.     }
  362.  
  363.     /* recover the bottom fragment */
  364.     if (bp->b_botline != NULLLPTR)
  365.     {
  366.         lp = bp->b_botline;
  367.         while (lp->l_fp != NULLLPTR)
  368.             lp = lp->l_fp;
  369.         lp->l_fp = bp->b_linep;
  370.         bp->b_linep->l_bp->l_fp = bp->b_botline;
  371.         bp->b_botline->l_bp = bp->b_linep->l_bp;
  372.         bp->b_linep->l_bp = lp;
  373.         bp->b_botline = NULLLPTR;
  374.     }
  375.  
  376.     /* let all the proper windows be updated */
  377.     wp = wheadp;
  378.     while (wp)
  379.     {
  380.         if (wp->w_bufp == bp)
  381.             wp->w_flag |= WFHARD | WFMODE;
  382.         wp = wp->w_wndp;
  383.     }
  384.  
  385.     /* and now remember we are not narrowed */
  386.     bp->b_flag &= (~BFNAROW);
  387.     MlWrite("Buffer is widened");
  388.     return(TRUE);
  389. }
  390.  
  391. /**
  392.  * Indent region one level
  393.  */
  394. int IndentRegion(f, n)
  395.   int        f, n;
  396. {
  397.   int        curline;
  398.   short        odoto;
  399.   int        nlines;
  400.   int        dirf = 1;                    /* direction flag (1=forw, -1=back) */
  401.  
  402.     if (curbp->b_mode & MDVIEW)         /* don't allow this command if */
  403.         return(ReadOnly());                /* we are in read only mode */
  404.  
  405.     curline = GetCurLine();
  406.     odoto = curwp->w_doto;
  407.  
  408.     /* swap dot and mark, plus make sure we've got a defined region */
  409.     if (!SwapMark(TRUE, 1))
  410.         return(FALSE);
  411.  
  412.     /* adjust line count and direction if dot was before mark */
  413.     nlines = curline - GetCurLine();
  414.     if (nlines < 0)
  415.     {
  416.         nlines = -nlines;
  417.         dirf = -1;
  418.     }
  419.  
  420.     /* make sure we leave the region defined when we're done */
  421.     discmd = FALSE;
  422.     SetMark(FALSE, 1);
  423.     discmd = TRUE;
  424.  
  425.     /* insert a Tab's worth at the beginning of each line in the region */
  426.     while (nlines--)
  427.     {
  428.         GotoBOL(TRUE, 1);
  429.         if (llength(curwp->w_dotp) > 0)
  430.         {
  431.             if (!stabsize)
  432.                 LInsert(1, '\t');
  433.             else
  434.                 LInsert(stabsize - (GetCurCol(FALSE) % stabsize), ' ');
  435.         }
  436.         ForwLine(TRUE, dirf);
  437.     }
  438.     curwp->w_doto = odoto;
  439.  
  440.     if (n > 1)
  441.         IndentRegion(TRUE, --n);
  442.  
  443.     return(TRUE);
  444. }
  445.  
  446. /**
  447.  * Undent region one level
  448.  */
  449. int UndentRegion(f, n)
  450.   int        f, n;
  451. {
  452.   int        curline;
  453.   short        odoto;
  454.   int        nlines;
  455.   int        dirf = 1;                    /* direction flag (1=forw, -1=back) */
  456.   int        c;
  457.   int        tsiz;                        /* num. spaces to del if not hard Tab */
  458.   LINE        *linep;
  459.  
  460.     if (curbp->b_mode & MDVIEW)         /* don't allow this command if */
  461.         return(ReadOnly());                /* we are in read only mode */
  462.  
  463.     curline = GetCurLine();
  464.     odoto = curwp->w_doto;
  465.  
  466.     /* swap dot and mark, plus make sure we've got a defined region */
  467.     if (!SwapMark(TRUE, 1))
  468.         return(FALSE);
  469.  
  470.     /* adjust line count and direction if dot was before mark */
  471.     nlines = curline - GetCurLine();
  472.     if (nlines < 0)
  473.     {
  474.         nlines = -nlines;
  475.         dirf = -1;
  476.     }
  477.  
  478.     /* make sure we leave the region defined when we're done */
  479.     discmd = FALSE;
  480.     SetMark(FALSE, 1);
  481.     discmd = TRUE;
  482.  
  483.     /* delete the first char (tabs or spaces only) on each line in the region */
  484.     while (nlines--)
  485.     {
  486.         GotoBOL(TRUE, 1);
  487.         linep = curwp->w_dotp;
  488.         c = lgetc(linep, 0);
  489.         if (llength(linep) > 0 && (c == '\t' || c == ' '))
  490.         {
  491.             if (c == '\t')                /* if a hard Tab */
  492.                 LDelete(1L, FALSE);        /*    delete the sucker */
  493.             else                        /* else we have at least one space */
  494.             {
  495.                 if (!stabsize)            /* using hard tabs */
  496.                     tsiz = tabsize;        /* max. number of spaces to delete */
  497.                 else
  498.                     tsiz = stabsize;    /* using soft tabs (spaces) */
  499.                 do
  500.                 {
  501.                     LDelete(1L, FALSE);
  502.                     --tsiz;
  503.                 } while (((c = lgetc(linep, 0)) == ' ') && tsiz);
  504.             }
  505.         }
  506.         ForwLine(TRUE, dirf);
  507.     }
  508.     curwp->w_doto = odoto;
  509.  
  510.     if (n > 1)
  511.         UndentRegion(TRUE, --n);
  512.  
  513.     return(TRUE);
  514. }
  515.  
  516. /**
  517.  * This routine figures out the bounds of the region in the current window, and
  518.  * fills in the fields of the "REGION" structure pointed to by "rp". Because
  519.  * the dot and mark are usually very close together, we scan outward from dot
  520.  * looking for mark. This should save time. Return a standard code. Callers of
  521.  * this routine should be prepared to get an "ABORT" status; we might make this
  522.  * have the conform thing later.
  523.  */
  524. static int near getregion(rp, regcmd)
  525.   REGION    *rp;
  526.   int        regcmd;
  527. {
  528.   LINE        *flp;
  529.   LINE        *blp;
  530.   long        fsize;
  531.   long        bsize;
  532.  
  533.     if (curwp->w_markp == NULLLPTR)
  534.     {
  535.         if (regcmd)
  536.             MlWrite("No mark set in this window");
  537.         return(FALSE);
  538.     }
  539.  
  540.     /* if dot and mark are on the same line */
  541.     if (curwp->w_dotp == curwp->w_markp)
  542.     {
  543.         rp->r_linep = curwp->w_dotp;
  544.         if (curwp->w_doto < curwp->w_marko)
  545.         {
  546.             rp->r_offset = curwp->w_doto;
  547.             rp->r_size = (long)(curwp->w_marko - curwp->w_doto);
  548.         }
  549.         else
  550.         {
  551.             rp->r_offset = curwp->w_marko;
  552.             rp->r_size = (long)(curwp->w_doto - curwp->w_marko);
  553.         }
  554.         return(TRUE);
  555.     }
  556.  
  557.     blp = curwp->w_dotp;
  558.     bsize = (long)curwp->w_doto;
  559.     flp = curwp->w_dotp;
  560.     fsize = (long)(llength(flp) - curwp->w_doto + 1);
  561.     while (flp != curbp->b_linep || lback(blp) != curbp->b_linep)
  562.     {
  563.         if (flp != curbp->b_linep)
  564.         {
  565.             flp = lforw(flp);
  566.             if (flp == curwp->w_markp)
  567.             {
  568.                 rp->r_linep = curwp->w_dotp;
  569.                 rp->r_offset = curwp->w_doto;
  570.                 rp->r_size = fsize + (long)curwp->w_marko;
  571.                 return(TRUE);
  572.             }
  573.             fsize += (long)(llength(flp) + 1);
  574.         }
  575.         if (lback(blp) != curbp->b_linep)
  576.         {
  577.             blp = lback(blp);
  578.             bsize += (long)(llength(blp) + 1);
  579.             if (blp == curwp->w_markp)
  580.             {
  581.                 rp->r_linep = blp;
  582.                 rp->r_offset = curwp->w_marko;
  583.                 rp->r_size = bsize - (long)curwp->w_marko;
  584.                 return(TRUE);
  585.             }
  586.         }
  587.     }
  588.     return(FALSE);
  589. }
  590.