home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 198_02 / region.c < prev    next >
C/C++ Source or Header  |  1990-01-23  |  15KB  |  482 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        "edef.h"
  11.  
  12. /*
  13.  * Kill the region. Ask "getregion"
  14.  * to figure out the bounds of the region.
  15.  * Move "." to the start, and kill the characters.
  16.  * Bound to "C-W".
  17.  */
  18. killregion(f, n)
  19. {
  20.         register int    s;
  21.         REGION          region;
  22.  
  23.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  24.         return(rdonly());    /* we are in read only mode    */
  25.         if ((s=getregion(®ion)) != TRUE)
  26.                 return (s);
  27.         if ((lastflag&CFKILL) == 0)             /* This is a kill type  */
  28.                 kdelete();                      /* command, so do magic */
  29.         thisflag |= CFKILL;                     /* kill buffer stuff.   */
  30.         curwp->w_dotp = region.r_linep;
  31.         curwp->w_doto = region.r_offset;
  32.         return (ldelete(region.r_size, TRUE));
  33. }
  34.  
  35. /*
  36.  * Copy all of the characters in the
  37.  * region to the kill buffer. Don't move dot
  38.  * at all. This is a bit like a kill region followed
  39.  * by a yank. Bound to "M-W".
  40.  */
  41. copyregion(f, n)
  42. {
  43.         register LINE   *linep;
  44.         register int    loffs;
  45.         register int    s;
  46.         REGION          region;
  47.  
  48.         if ((s=getregion(®ion)) != TRUE)
  49.                 return (s);
  50.         if ((lastflag&CFKILL) == 0)             /* Kill type command.   */
  51.                 kdelete();
  52.         thisflag |= CFKILL;
  53.         linep = region.r_linep;                 /* Current line.        */
  54.         loffs = region.r_offset;                /* Current offset.      */
  55.         while (region.r_size-- > 0L) {
  56.                 if (loffs == llength(linep)) {  /* End of line.         */
  57.                         if ((s=kinsert('\n')) != TRUE)
  58.                                 return (s);
  59.                         linep = lforw(linep);
  60.                         loffs = 0;
  61.                 } else {                        /* Middle of line.      */
  62.                         if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
  63.                                 return (s);
  64.                         ++loffs;
  65.                 }
  66.         }
  67.     mlwrite("[region copied]");
  68.         return (TRUE);
  69. }
  70.  
  71. /*    Narrow-to-region (^X-<) makes all but the current region in
  72.     the current buffer invisable and unchangable
  73. */
  74.  
  75. narrow(f, n)
  76.  
  77. {
  78.         register int status;    /* return status */
  79.     BUFFER *bp;        /* buffer being narrowed */
  80.     WINDOW *wp;        /* windows to fix up pointers in as well */
  81.     REGION creg;        /* region boundry structure */
  82.  
  83.     /* find the proper buffer and make sure we aren't already narrow */
  84.     bp = curwp->w_bufp;        /* find the right buffer */
  85.     if (bp->b_flag&BFNAROW) {
  86.         mlwrite("%%This buffer is already narrowed");
  87.         return(FALSE);
  88.     }
  89.  
  90.     /* find the boundries of the current region */
  91.         if ((status=getregion(&creg)) != TRUE)
  92.                 return(status);
  93.         curwp->w_dotp = creg.r_linep;    /* only by full lines please! */
  94.         curwp->w_doto = 0;
  95.     creg.r_size += (long)creg.r_offset;
  96.     if (creg.r_size <= (long)curwp->w_dotp->l_used) {
  97.         mlwrite("%%Must narrow at least 1 full line");
  98.         return(FALSE);
  99.     }
  100.  
  101.     /* archive the top fragment */
  102.     if (bp->b_linep->l_fp != creg.r_linep) {
  103.         bp->b_topline = bp->b_linep->l_fp;
  104.         creg.r_linep->l_bp->l_fp = (LINE *)NULL;
  105.         bp->b_linep->l_fp = creg.r_linep;
  106.         creg.r_linep->l_bp = bp->b_linep;
  107.     }
  108.  
  109.     /* move forward to the end of this region
  110.        (a long number of bytes perhaps) */
  111.     while (creg.r_size > (long)32000) {
  112.         forwchar(TRUE, 32000);
  113.         creg.r_size -= (long)32000;
  114.     }
  115.     forwchar(TRUE, (int)creg.r_size);
  116.     curwp->w_doto = 0;        /* only full lines! */
  117.  
  118.     /* archive the bottom fragment */
  119.     if (bp->b_linep != curwp->w_dotp) {
  120.         bp->b_botline = curwp->w_dotp;
  121.         bp->b_botline->l_bp->l_fp = bp->b_linep;
  122.         bp->b_linep->l_bp->l_fp = (LINE *)NULL;
  123.         bp->b_linep->l_bp = bp->b_botline->l_bp;
  124.     }
  125.  
  126.     /* let all the proper windows be updated */
  127.     wp = wheadp;
  128.     while (wp) {
  129.         if (wp->w_bufp == bp) {
  130.             wp->w_linep = creg.r_linep;
  131.             wp->w_dotp = creg.r_linep;
  132.             wp->w_doto = 0;
  133.             wp->w_markp = creg.r_linep;
  134.             wp->w_marko = 0;
  135.             wp->w_flag |= (WFHARD|WFMODE);
  136.         }
  137.         wp = wp->w_wndp;
  138.     }
  139.  
  140.     /* and now remember we are narrowed */
  141.     bp->b_flag |= BFNAROW;
  142.     mlwrite("[Buffer is narrowed]");
  143.         return(TRUE);
  144. }
  145.  
  146. /*    widen-from-region (^X->) restores a narrowed region    */
  147.  
  148. widen(f, n)
  149.  
  150. {
  151.     LINE *lp;    /* temp line pointer */
  152.     BUFFER *bp;    /* buffer being narrowed */
  153.     WINDOW *wp;    /* windows to fix up pointers in as well */
  154.  
  155.     /* find the proper buffer and make sure we are narrow */
  156.     bp = curwp->w_bufp;        /* find the right buffer */
  157.     if ((bp->b_flag&BFNAROW) == 0) {
  158.         mlwrite("%%This buffer is not narrowed");
  159.         return(FALSE);
  160.     }
  161.  
  162.     /* recover the top fragment */
  163.     if (bp->b_topline != (LINE *)NULL) {
  164.         lp = bp->b_topline;
  165.         while (lp->l_fp != (LINE *)NULL)
  166.             lp = lp->l_fp;
  167.         lp->l_fp = bp->b_linep->l_fp;
  168.         lp->l_fp->l_bp = lp;
  169.         bp->b_linep->l_fp = bp->b_topline;
  170.         bp->b_topline->l_bp = bp->b_linep;
  171.         bp->b_topline = (LINE *)NULL;
  172.     }
  173.  
  174.     /* recover the bottom fragment */
  175.     if (bp->b_botline != (LINE *)NULL) {
  176.         lp = bp->b_botline;
  177.         while (lp->l_fp != (LINE *)NULL)
  178.             lp = lp->l_fp;
  179.         lp->l_fp = bp->b_linep;
  180.         bp->b_linep->l_bp->l_fp = bp->b_botline;
  181.         bp->b_botline->l_bp = bp->b_linep->l_bp;
  182.         bp->b_linep->l_bp = lp;
  183.         bp->b_botline = (LINE *)NULL;
  184.     }
  185.  
  186.     /* let all the proper windows be updated */
  187.     wp = wheadp;
  188.     while (wp) {
  189.         if (wp->w_bufp == bp)
  190.             wp->w_flag |= (WFHARD|WFMODE);
  191.         wp = wp->w_wndp;
  192.     }
  193.     /* and now remember we are not narrowed */
  194.     bp->b_flag &= (~BFNAROW);
  195.     mlwrite("[Buffer is widened]");
  196.         return(TRUE);
  197. }
  198.  
  199. /*
  200.  * Lower case region. Zap all of the upper
  201.  * case characters in the region to lower case. Use
  202.  * the region code to set the limits. Scan the buffer,
  203.  * doing the changes. Call "lchange" to ensure that
  204.  * redisplay is done in all buffers. Bound to
  205.  * "C-X C-L".
  206.  */
  207. lowerregion(f, n)
  208. {
  209.         register LINE   *linep;
  210.         register int    loffs;
  211.         register int    c;
  212.         register int    s;
  213.         REGION          region;
  214.  
  215.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  216.         return(rdonly());    /* we are in read only mode    */
  217.         if ((s=getregion(®ion)) != TRUE)
  218.                 return (s);
  219.         lchange(WFHARD);
  220.         linep = region.r_linep;
  221.         loffs = region.r_offset;
  222.         while (region.r_size-- > 0L) {
  223.                 if (loffs == llength(linep)) {
  224.                         linep = lforw(linep);
  225.                         loffs = 0;
  226.                 } else {
  227.                         c = lgetc(linep, loffs);
  228.                         if (c>='A' && c<='Z')
  229.                                 lputc(linep, loffs, c+'a'-'A');
  230.                         ++loffs;
  231.                 }
  232.         }
  233.         return (TRUE);
  234. }
  235.  
  236. /*
  237.  * Upper case region. Zap all of the lower
  238.  * case characters in the region to upper case. Use
  239.  * the region code to set the limits. Scan the buffer,
  240.  * doing the changes. Call "lchange" to ensure that
  241.  * redisplay is done in all buffers. Bound to
  242.  * "C-X C-L".
  243.  */
  244. upperregion(f, n)
  245. {
  246.         register LINE   *linep;
  247.         register int    loffs;
  248.         register int    c;
  249.         register int    s;
  250.         REGION          region;
  251.  
  252.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  253.         return(rdonly());    /* we are in read only mode    */
  254.         if ((s=getregion(®ion)) != TRUE)
  255.                 return (s);
  256.         lchange(WFHARD);
  257.         linep = region.r_linep;
  258.         loffs = region.r_offset;
  259.         while (region.r_size-- > 0L) {
  260.                 if (loffs == llength(linep)) {
  261.                         linep = lforw(linep);
  262.                         loffs = 0;
  263.                 } else {
  264.                         c = lgetc(linep, loffs);
  265.                         if (c>='a' && c<='z')
  266.                                 lputc(linep, loffs, c-'a'+'A');
  267.                         ++loffs;
  268.                 }
  269.         }
  270.         return (TRUE);
  271. }
  272.  
  273. /*
  274.  * This routine figures out the
  275.  * bounds of the region in the current window, and
  276.  * fills in the fields of the "REGION" structure pointed
  277.  * to by "rp". Because the dot and mark are usually very
  278.  * close together, we scan outward from dot looking for
  279.  * mark. This should save time. Return a standard code.
  280.  * Callers of this routine should be prepared to get
  281.  * an "ABORT" status; we might make this have the
  282.  * conform thing later.
  283.  */
  284. getregion(rp)
  285. register REGION *rp;
  286. {
  287.         register LINE   *flp;
  288.         register LINE   *blp;
  289.         long fsize;
  290.         long bsize;
  291.  
  292.         if (curwp->w_markp == NULL) {
  293.                 mlwrite("No mark set in this window");
  294.                 return (FALSE);
  295.         }
  296.         if (curwp->w_dotp == curwp->w_markp) {
  297.                 rp->r_linep = curwp->w_dotp;
  298.                 if (curwp->w_doto < curwp->w_marko) {
  299.                         rp->r_offset = curwp->w_doto;
  300.                         rp->r_size = (long)(curwp->w_marko-curwp->w_doto);
  301.                 } else {
  302.                         rp->r_offset = curwp->w_marko;
  303.                         rp->r_size = (long)(curwp->w_doto-curwp->w_marko);
  304.                 }
  305.                 return (TRUE);
  306.         }
  307.         blp = curwp->w_dotp;
  308.         bsize = (long)curwp->w_doto;
  309.         flp = curwp->w_dotp;
  310.         fsize = (long)(llength(flp)-curwp->w_doto+1);
  311.         while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
  312.                 if (flp != curbp->b_linep) {
  313.                         flp = lforw(flp);
  314.                         if (flp == curwp->w_markp) {
  315.                                 rp->r_linep = curwp->w_dotp;
  316.                                 rp->r_offset = curwp->w_doto;
  317.                                 rp->r_size = fsize+curwp->w_marko;
  318.                                 return (TRUE);
  319.                         }
  320.                         fsize += llength(flp)+1;
  321.                 }
  322.                 if (lback(blp) != curbp->b_linep) {
  323.                         blp = lback(blp);
  324.                         bsize += llength(blp)+1;
  325.                         if (blp == curwp->w_markp) {
  326.                                 rp->r_linep = blp;
  327.                                 rp->r_offset = curwp->w_marko;
  328.                                 rp->r_size = bsize - curwp->w_marko;
  329.                                 return (TRUE);
  330.                         }
  331.                 }
  332.         }
  333.         mlwrite("Bug: lost mark");
  334.         return (FALSE);
  335. }
  336.  
  337. #if    DECEDT
  338.  
  339. /*
  340.  * Kill the region to the kill buffer, and then remove the mark.
  341.  */
  342.  
  343. cutregion(f, n)
  344. {
  345.     int s;
  346.     s = killregion(f, n);
  347.     if (s == TRUE) { curwp->w_markp = NULL; curwp->w_marko = 0; }
  348.     return(s);
  349. }
  350.  
  351. /*
  352.  * Append the region to the kill buffer, and then kill it.
  353.  */
  354.  
  355. apkillregion(f, n)
  356. {
  357.     lastflag |= CFKILL;
  358.     return(killregion(f, n));
  359. }
  360.  
  361. /*
  362.  * Append all of the characters in the
  363.  * region to the kill buffer.
  364.  */
  365. apcopyregion(f, n)
  366. {
  367.     lastflag |= CFKILL;
  368.     return(copyregion(f, n));
  369. }
  370.  
  371. /*
  372.  * Change case in region. Use
  373.  * the region code to set the limits. Scan the buffer,
  374.  * doing the changes. Call "lchange" to ensure that
  375.  * redisplay is done in all buffers.
  376.  */
  377. caseregion(f, n)
  378. {
  379.         register LINE   *linep;
  380.         register int    loffs;
  381.         register int    c;
  382.         register int    s;
  383.         REGION          region;
  384.  
  385.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  386.         return(rdonly());    /* we are in read only mode    */
  387.         if ((s=getregion(®ion)) != TRUE)
  388.                 return (s);
  389.         lchange(WFHARD);
  390.         linep = region.r_linep;
  391.         loffs = region.r_offset;
  392.         while (region.r_size-- > 0L) {
  393.                 if (loffs == llength(linep)) {
  394.                         linep = lforw(linep);
  395.                         loffs = 0;
  396.                 } else {
  397.                         c = lgetc(linep, loffs);
  398.                         if (c>='a' && c<='z')
  399.                                 lputc(linep, loffs, c-'a'+'A');
  400.             else if (c>='A' && c<='Z')
  401.                 lputc(linep, loffs, c-'A'+'a');
  402.                         ++loffs;
  403.                 }
  404.         }
  405.         return (TRUE);
  406. }
  407.  
  408. /*
  409.  * Ask for a file name, and write the
  410.  * contents of the current region to that file.
  411.  *
  412.  * This function performs the details of file
  413.  * writing. Uses the file management routines in the
  414.  * "fileio.c" package. The number of lines written is
  415.  * displayed. Sadly, it looks inside a LINE; provide
  416.  * a macro for this. Most of the grief is error
  417.  * checking of some sort.
  418.  */
  419.  
  420. regionwrite(f, n)
  421. {
  422.         register LINE   *linep;
  423.         register int    s;
  424.         register int    loffs, len;
  425.         register int    nline;
  426.         REGION          region;
  427.         char            fn[NFILEN];
  428.  
  429.     if (restflag)        /* don't allow this command if restricted */
  430.         return(resterr());
  431.  
  432.     if ((s=getregion(®ion)) != TRUE)
  433.         return (s);
  434.  
  435.     if ((s=mlreply("Write file: ", fn, NFILEN)) != TRUE)
  436.         return (s);
  437.  
  438. #if    CRYPT
  439.     s = resetkey();
  440.     if (s != TRUE)
  441.         return(s);
  442. #endif
  443.  
  444.     /* turn off ALL keyboard translation in case we get a dos error */
  445.     (*term.t_kclose)();
  446.  
  447.         if ((s=ffwopen(fn)) != FIOSUC) {        /* Open writes message. */
  448.         (*term.t_kopen)();
  449.                 return (FALSE);
  450.         }
  451.     mlwrite("[Writing..]");            /* tell us were writing */
  452.         nline = 0;                              /* Number of lines.     */
  453.         linep = region.r_linep;
  454.         loffs = region.r_offset;
  455.         while (region.r_size > 0L) {
  456.         len = llength(linep) - loffs;
  457.         if (len > region.r_size) len = region.r_size;
  458.         region.r_size -= (len + 1);
  459.                 if ((s=ffputline(&linep->l_text[loffs], len)) != FIOSUC)
  460.                         break;
  461.                 ++nline;
  462.                 linep = lforw(linep);
  463.         loffs = 0;
  464.         }
  465.         if (s == FIOSUC) {                      /* No write error.      */
  466.                 s = ffclose();
  467.                 if (s == FIOSUC) {              /* No close error.      */
  468.                         if (nline == 1)
  469.                                 mlwrite("[Wrote 1 line]");
  470.                         else
  471.                                 mlwrite("[Wrote %d lines]", nline);
  472.                 }
  473.         } else                                  /* Ignore close error   */
  474.                 ffclose();                      /* if a write error.    */
  475.     (*term.t_kopen)();
  476.         if (s != FIOSUC)                        /* Some sort of error.  */
  477.                 return (FALSE);
  478.         return (TRUE);
  479. }
  480. #endif
  481.  
  482.