home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / texted / b084_1 / c / FOLDING < prev    next >
Text File  |  1992-09-19  |  31KB  |  889 lines

  1. /*
  2.  * The routines in this file deal with folding.
  3.  */
  4.  
  5. /*      Modifications:
  6.         11-Sep-89       Mike Burrow (INMOS)     Original.
  7.  */
  8.  
  9. #include        <stdio.h>
  10. #include        "estruct.h"
  11. #include        "etype.h"
  12. #include        "edef.h"
  13. #include        "elang.h"
  14.  
  15. /*      openfold:       Open a fold at the current dot position.
  16. */
  17.  
  18. /*{{{  PASCAL NEAR openfold(f, n)*/
  19. PASCAL NEAR openfold(f, n)
  20.  
  21. {
  22.         BUFFER *bp;              /* buffer being folded*/
  23.         WINDOW *wp;              /* windows to fix up pointers in as well */
  24.         int    i, j;
  25.         char   tmpstr[NSTRING];
  26.  
  27.         /* find the proper buffer */
  28.         bp = curwp->w_bufp;             
  29.  
  30.         if (curwp->w_dotp->l_type == LSOFOLD) {
  31.                 /* Change line types */
  32.                 curwp->w_dotp->l_type = LSOEFOLD;
  33.                 curwp->w_dotp->l_foldp->l_type = LEOEFOLD;
  34.  
  35.                 i = indx(curwp->w_dotp->l_text, FOLDSYMBOL);
  36.                 strcpy(tmpstr, BEGINFOLD);
  37.                 for (j = 0; j < strlen(FOLDSYMBOL); j ++)
  38.                         curwp->w_dotp->l_text[i + j] = tmpstr[j];
  39.  
  40.                 /* Move cursor to the beginning of next line */
  41.                 curwp->w_dotp = lforw(curwp->w_dotp);
  42.                 curwp->w_doto = curwp->w_dotp->l_lmargin;
  43.  
  44.                 /* let all the proper windows be updated */
  45.                 wp = wheadp;
  46.                 while (wp) {
  47.                         if (wp->w_bufp == bp)
  48.                                 wp->w_flag |= (WFHARD|WFMODE|WFFORCE);
  49.                         wp = wp->w_wndp;
  50.                 }
  51.                 mlwrite(TEXT218);
  52.                 /* "[Fold Opened]" */
  53.                 return(TRUE);
  54.         }
  55.         else {
  56.                 mlwrite(TEXT225);
  57.                 /* "%%Line is not a fold" */
  58.                 return(FALSE);
  59.         }
  60. }
  61. /*}}}*/
  62.  
  63.  
  64. /*      closefold:      Close the fold at the current dot position.
  65. */
  66.  
  67. /*{{{  PASCAL NEAR closefold(f, n)*/
  68. PASCAL NEAR closefold(f, n)
  69.  
  70. {
  71.         BUFFER *bp;              /* buffer being folded */
  72.         WINDOW *wp;              /* windows to fix up pointers in as well */
  73.         LINE   *lp, *lp2;        /* lines to search for fold markers */
  74.         int    i, j, foldcnt;
  75.         char   tmpstr[NSTRING];
  76.  
  77.         /* find the proper buffer */
  78.         bp = curwp->w_bufp;             
  79.  
  80.         foldcnt = 0; /* number of nested folds */
  81.  
  82.         /* search for the start of the fold, skipping nested folds */
  83.         if (curwp->w_dotp->l_type == LEOEFOLD)
  84.                 lp = curwp->w_dotp->l_foldp;
  85.         else {
  86.                 lp = curwp->w_dotp;
  87.                 while (((lp->l_type != LSOEFOLD) || (foldcnt > 0)) && 
  88.                         (lp != bp->b_linep)) {
  89.                         if ((lp->l_type == LEOFOLD) || (lp->l_type == LEOEFOLD))
  90.                                 foldcnt++;
  91.                         else if (((lp->l_type == LSOFOLD) || 
  92.                                   (lp->l_type == LSOEFOLD)) && (foldcnt > 0))
  93.                                 foldcnt--;
  94.                         lp = lp->l_bp;
  95.                 }
  96.         }
  97.  
  98.         /* close the fold */
  99.         if ((lp->l_type == LSOEFOLD) && (foldcnt == 0)) {
  100.                 lp->l_type = LSOFOLD;
  101.                 lp->l_foldp->l_type = LEOFOLD;
  102.  
  103.                 i = indx(lp->l_text, BEGINFOLD);
  104.                 strcpy(tmpstr, FOLDSYMBOL);
  105.                 for (j = 0; j < strlen(FOLDSYMBOL); j ++)
  106.                         lp->l_text[i + j] = tmpstr[j];
  107.  
  108.                 /* close any inner folds */
  109.                 lp2 = lp->l_foldp;
  110.                 while (lp2 != lp) {
  111.                         if (lp2->l_type == LSOEFOLD){
  112.                                 lp2->l_type = LSOFOLD;
  113.                                 i = indx(lp2->l_text, BEGINFOLD);
  114.                                 for (j = 0; j < strlen(FOLDSYMBOL); j ++)
  115.                                         lp2->l_text[i + j] = tmpstr[j];
  116.                         }
  117.                         else if (lp2->l_type == LEOEFOLD)
  118.                                 lp2->l_type = LEOFOLD;
  119.                         lp2 = lp2->l_bp;
  120.                 }
  121.  
  122.                 /* Move cursor to the beginning of fold line */
  123.                 curwp->w_dotp = lp;
  124.                 curwp->w_doto = loffset(curwp->w_dotp);
  125.  
  126.                 /* let all the proper windows be updated */
  127.                 wp = wheadp;
  128.                 while (wp) {
  129.                         if (wp->w_bufp == bp) {
  130.                                 wp->w_flag |= (WFHARD|WFMODE|WFFORCE);
  131.                                 /* enter all windows containing fold */
  132.                                 wp->w_linep = curwp->w_linep;
  133.                                 wp->w_dotp = curwp->w_dotp;
  134.                                 wp->w_doto = curwp->w_doto;
  135.                         }
  136.                         wp = wp->w_wndp;
  137.                 }
  138.                 mlwrite(TEXT219);
  139.                 /* "[Fold Closed]" */
  140.                 return(TRUE);
  141.         }
  142.         else {
  143.                 mlwrite(TEXT226);
  144.                 /* "%%Line is not within a fold" */
  145.                 return(FALSE);
  146.         }
  147. }
  148. /*}}}*/
  149.  
  150.  
  151. /*      enterfold:      Enter a fold at the current dot position.
  152. */
  153.  
  154. /*{{{  PASCAL NEAR enterfold(f, n)*/
  155. PASCAL NEAR enterfold(f, n)
  156.  
  157. {
  158.         BUFFER *bp;              /* buffer being entered */
  159.         WINDOW *wp;              /* windows to fix up pointers in as well */
  160.         int    wscnt;            /* whitespace count */
  161.         LINE   *lp;              /* line loop value */
  162.         int    chgflag;          /* record previous value of change flag */
  163.         int    vewflag;          /* record previous value of view flag */
  164.         int    i;
  165.  
  166.         /* find the proper buffer */
  167.         bp = curwp->w_bufp;             
  168.  
  169.         if (curwp->w_dotp->l_type == LSOFOLD) {
  170.  
  171.                 /* remove indentation and stack previous buffer values */
  172.                 if (bp->b_nfolds < NFOLDS) {
  173.  
  174.                         /* remove indentation from fold */
  175.  
  176.                         /* 1st find out how much to remove */
  177.                         wscnt = loffset(curwp->w_dotp);
  178.  
  179.                         /* and then remove them */
  180.                         if (wscnt > 0) {
  181.  
  182.                                 /* record if buffer changed yet since this will */
  183.                                 chgflag = bp->b_flag & BFCHG;
  184.                                 vewflag = bp->b_mode & MDVIEW; /* no good in view mode */
  185.                                 bp->b_mode &= ~MDVIEW;
  186.  
  187.                                 lp = curwp->w_dotp; /* save old value */
  188.  
  189.                                 curwp->w_dotp = lp->l_fp;
  190.                                 while (curwp->w_dotp != lp->l_foldp) {
  191.                                         curwp->w_doto = 0;
  192.                                         curwp->w_dotp->l_omargin = curwp->w_dotp->l_lmargin;
  193.                                         curwp->w_dotp->l_lmargin = 0;
  194.                                         /* safety 1st - but shouldn't be required */
  195.                                         if (loffset(curwp->w_dotp) >= wscnt)
  196.                                                 ldelete((long)wscnt, FALSE, FALSE, FALSE);
  197.                                                 
  198.                                         if (curwp->w_dotp->l_type == LSOFOLD)
  199.                                                 curwp->w_dotp = curwp->w_dotp->l_foldp;
  200.                                         curwp->w_dotp = curwp->w_dotp->l_fp;
  201.                                 }
  202.                                 curwp->w_dotp = lp;
  203.  
  204.                                 /* reset change flag? */
  205.                                 if (!chgflag)
  206.                                         bp->b_flag &= ~BFCHG;
  207.                                 if (vewflag) /* reset view flag */
  208.                                         bp->b_mode |= MDVIEW;
  209.                         }
  210.                         else { /* just set old margin value to zero - or problem with exit */
  211.                                 lp = curwp->w_dotp; /* save old value */
  212.                                 curwp->w_dotp = lp->l_fp;
  213.                                 while (curwp->w_dotp != lp->l_foldp) {
  214.                                         curwp->w_dotp->l_omargin = 0;
  215.                                         curwp->w_dotp->l_lmargin = 0;
  216.                                         if (curwp->w_dotp->l_type == LSOFOLD)
  217.                                                 curwp->w_dotp = curwp->w_dotp->l_foldp;
  218.                                         curwp->w_dotp = curwp->w_dotp->l_fp;
  219.                                 }
  220.                                 curwp->w_dotp = lp;
  221.                         }
  222.  
  223.                         /* stack values */
  224.                         bp->b_folds[bp->b_nfolds].f_topline = bp->b_linep->l_fp;
  225.                         bp->b_folds[bp->b_nfolds].f_botline = curwp->w_dotp->l_foldp;
  226.                         bp->b_linep->l_fp = curwp->w_dotp->l_fp;
  227.                         curwp->w_dotp->l_fp->l_bp = bp->b_linep;
  228.                         curwp->w_dotp->l_fp = (LINE *)NULL;
  229.                         bp->b_folds[bp->b_nfolds].f_botline->l_bp->l_fp = bp->b_linep;
  230.                         bp->b_linep->l_bp->l_fp = (LINE *)NULL;
  231.                         bp->b_linep->l_bp = bp->b_folds[bp->b_nfolds].f_botline->l_bp;
  232.  
  233.                         /* Move cursor to the beginning of next line */
  234.                         curwp->w_dotp = bp->b_linep->l_fp;
  235.                         curwp->w_doto = 0;
  236.  
  237.                         /* increment fold count */
  238.                         bp->b_nfolds++;
  239.  
  240.                         /* let all the proper windows be updated */
  241.                         wp = wheadp;
  242.                         while (wp) {
  243.                                 if (wp->w_bufp == bp) {
  244.                                         wp->w_flag |= (WFHARD|WFMODE|WFFORCE);
  245.                                         /* have to enter in all windows */
  246.                                         /* since buffer only valid for fold */
  247.                                         wp->w_linep = bp->b_linep->l_fp;
  248.                                         wp->w_dotp = wp->w_linep;
  249.                                         wp->w_doto = 0;
  250.                                         /* clear out marks */
  251.                                         for (i = 0; i < NMARKS; i++)
  252.                                                 wp->w_markp[i] = (LINE *)NULL;
  253.  
  254.                                 }
  255.                                 wp = wp->w_wndp;
  256.                         }
  257.                         mlwrite(TEXT220);
  258.                         /* "[Fold Entered]" */
  259.                         if (bp->b_mode & MDASAVE)
  260.                         mlwrite(TEXT238);
  261.                         /* "%%Cannot AUTOSAVE when within a fold" */
  262.                         return(TRUE);
  263.                 }
  264.                 else {
  265.                         mlwrite(TEXT227);
  266.                         /* "%% Folds too deep" */
  267.                         return(FALSE);
  268.                 }
  269.         }
  270.         else {
  271.                 mlwrite(TEXT225);
  272.                 /* "%%Line is not a fold" */
  273.                 return(FALSE);
  274.         }
  275. }
  276. /*}}}*/
  277.  
  278.  
  279. /*      exitfold:       Exit the current fold.
  280. */
  281.  
  282. /*{{{  PASCAL NEAR exitfold(f, n)*/
  283. PASCAL NEAR exitfold(f, n)
  284.  
  285. {
  286.         BUFFER *bp;              /* buffer being entered */
  287.         WINDOW *wp;              /* windows to fix up pointers in as well */
  288.         LINE   *lp;              /* line limits of entered fold */
  289.         int    i, j;
  290.         char   tmpstr[NSTRING];
  291.         LINE   *flp;
  292.         int    fos;
  293.         int    chgflag, vewflag;
  294.         int    margval;
  295.  
  296.         /* find the proper buffer */
  297.         bp = curwp->w_bufp;             
  298.  
  299.         if (bp->b_nfolds > 0) {
  300.  
  301.                 /* need foldsymbol in an array */
  302.                 strcpy(tmpstr, FOLDSYMBOL);
  303.  
  304.                 /* decrement fold count */
  305.                 bp->b_nfolds--;
  306.  
  307.                 /* close any inner folds */
  308.                 lp = bp->b_linep->l_fp;
  309.                 while (lp != bp->b_linep) {
  310.                         if (lp->l_type == LSOEFOLD) {
  311.                                 lp->l_foldp->l_type = LEOFOLD;
  312.                                 lp->l_type = LSOFOLD;
  313.                                 i = indx(lp->l_text, BEGINFOLD);
  314.                                 for (j = 0; j < strlen(FOLDSYMBOL); j ++)
  315.                                         lp->l_text[i + j] = tmpstr[j];
  316.                         }
  317.                         lp = lp->l_fp;
  318.                 }
  319.  
  320.                 /* restore previous buffer values, for top */
  321.                 lp = bp->b_folds[bp->b_nfolds].f_topline;
  322.                 while (lp->l_fp != (LINE *)NULL)
  323.                         lp = lp->l_fp;
  324.                 lp->l_fp = bp->b_linep->l_fp;
  325.                 lp->l_fp->l_bp = lp;
  326.                 bp->b_linep->l_fp = bp->b_folds[bp->b_nfolds].f_topline;
  327.                 bp->b_folds[bp->b_nfolds].f_topline->l_bp = bp->b_linep;
  328.                 
  329.                 /* and bottom */
  330.                 lp = bp->b_folds[bp->b_nfolds].f_botline;
  331.                 while (lp->l_fp != (LINE *)NULL)
  332.                         lp = lp->l_fp;
  333.                 lp->l_fp = bp->b_linep;
  334.                 bp->b_linep->l_bp->l_fp = bp->b_folds[bp->b_nfolds].f_botline;
  335.                 bp->b_folds[bp->b_nfolds].f_botline->l_bp = bp->b_linep->l_bp;
  336.                 bp->b_linep->l_bp = lp;
  337.  
  338.                 /* Move cursor to the beginning of next line */
  339.                 curwp->w_dotp = bp->b_folds[bp->b_nfolds].f_botline->l_foldp->l_fp;
  340.                 curwp->w_doto = 0;
  341.  
  342.                 /* record if buffer changed yet since this will */
  343.                 chgflag = bp->b_flag & BFCHG;
  344.                 vewflag = bp->b_mode & MDVIEW; /* no good in view mode */
  345.                 bp->b_mode &= ~MDVIEW;
  346.  
  347.                 /* restore prefix - copy in from fold line - maybe ' ' & '\t' */
  348.                 flp = bp->b_folds[bp->b_nfolds].f_botline->l_foldp;
  349.                 fos = loffset(flp);
  350.                 margval = curwp->w_dotp->l_omargin;
  351.                 while (curwp->w_dotp != bp->b_folds[bp->b_nfolds].f_botline) {
  352.                         curwp->w_doto = 0;
  353.                         for (i = 0; i < fos; i++)
  354.                                 linsert(1, flp->l_text[i], FALSE);
  355.                         curwp->w_dotp->l_lmargin = margval;
  356.                         if (curwp->w_dotp->l_type == LSOFOLD)
  357.                                 curwp->w_dotp = curwp->w_dotp->l_foldp;
  358.                         curwp->w_dotp = curwp->w_dotp->l_fp;
  359.                 }
  360.  
  361.                 /* reset change flag? */
  362.                 if (!chgflag)
  363.                         bp->b_flag &= ~BFCHG;
  364.                 if (vewflag) /* reset view flag */
  365.                         bp->b_mode |= MDVIEW;
  366.  
  367.                 /* Move cursor to the beginning of next line */
  368.                 curwp->w_dotp = bp->b_folds[bp->b_nfolds].f_botline->l_foldp;
  369.                 curwp->w_doto = loffset(curwp->w_dotp);
  370.  
  371.                 /* let all the proper windows be updated */
  372.                 wp = wheadp;
  373.                 while (wp) {
  374.                         if (wp->w_bufp == bp) {
  375.                                 wp->w_flag |= (WFHARD|WFMODE|WFFORCE);
  376.                                 /* enter all windows containing fold */
  377.                                 wp->w_linep = curwp->w_linep;
  378.                                 wp->w_dotp = curwp->w_dotp;
  379.                                 wp->w_doto = curwp->w_doto;
  380.                         }
  381.                         wp = wp->w_wndp;
  382.                 }
  383.                 mlwrite(TEXT221);
  384.                 /* "[Fold Exited]" */
  385.                 return(TRUE);
  386.         }
  387.         else {
  388.                 mlwrite(TEXT228);
  389.                 /* "%%Not within an entered fold" */
  390.                 return(FALSE);
  391.         }
  392. }
  393. /*}}}*/
  394.  
  395.  
  396. /*      exitallfolds:   Exit all folds currently entered.
  397. */
  398.  
  399. /*{{{  PASCAL NEAR exitallfolds(f, n)*/
  400. PASCAL NEAR exitallfolds(f, n)
  401. {
  402.         while (curwp->w_bufp->b_nfolds > 0)
  403.                 exitfold(f, n);
  404.         return(TRUE);
  405. }
  406. /*}}}*/
  407.  
  408.  
  409. /*      makefold:       Make a fold of the current marked region.
  410. */
  411.  
  412. /*{{{  PASCAL NEAR makefold(f, n)*/
  413. PASCAL NEAR makefold(f, n)
  414.  
  415. {
  416.         register int status;     /* return status */
  417.         BUFFER *bp;              /* buffer being folded*/
  418.         WINDOW *wp;              /* windows to fix up pointers in as well */
  419.         REGION creg;             /* region boundry structure */
  420.         char   foldstr[NSTRING]; /* Fold string to insert into buffer/file */
  421.         LINE   *topboundary;     /* Line before fold */
  422.         LINE   *botboundary;     /* Line after fold */
  423.         int    i;                /* Loop */
  424.         char   mprefix[NSTRING]; /* mark prefix */
  425.         int    lm;               /* left margin value */
  426.         LINE   *lp;              /* line pointer */
  427.         short  ltype;            /* saved line type */
  428.  
  429.         if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
  430.                 return(rdonly());       /* we are in read only mode     */
  431.  
  432.         /* find the proper buffer */
  433.         bp = curwp->w_bufp;             
  434.  
  435.         /* find the boundries of the current region */
  436.         /* remember these could be fold lines */
  437.  
  438.         /* call getrawregion first, cos this will check if we cross crease */
  439.         if ((status=getrawregion(&creg)) != TRUE)
  440.                 return(status);
  441.  
  442.         /* check if we have to indent the fold marker */
  443.         i = 0;  
  444.         lm = curwp->w_markp[0]->l_lmargin;
  445.         if (curwp->w_marko[0] > lm) {
  446.                 while (((curwp->w_markp[0]->l_text[i + lm] == ' ') ||
  447.                         (curwp->w_markp[0]->l_text[i + lm] == '\t')) &&
  448.                        (i + lm < curwp->w_marko[0])) {
  449.                                 mprefix[i] = curwp->w_markp[0]->l_text[i + lm];
  450.                                 i++;
  451.                 }
  452.         }
  453.         mprefix[i] = NULL;
  454.  
  455.         if ((status=getregion(&creg)) != TRUE)
  456.                 return(status);
  457.         curwp->w_dotp = creg.r_linep;   /* only by full lines */
  458.         curwp->w_doto = 0;
  459.         creg.r_size += (long)creg.r_offset;
  460.         if (creg.r_size <= (long)curwp->w_dotp->l_used) {
  461.                 mlwrite(TEXT222);
  462. /*                      "%%Must fold at least 1 full line" */
  463.                 return(FALSE);
  464.         }
  465.  
  466.         /* insert the mapped fold-start line at top */
  467.         /* have to insert and backup since it could already be a fold line */
  468.  
  469.         /* Unless line is normal cannot insert nl at left margin */
  470.         ltype = curwp->w_dotp->l_type;
  471.         curwp->w_dotp->l_type = LNORMAL;
  472.         curwp->w_doto = curwp->w_dotp->l_lmargin;
  473.         lnewline();
  474.  
  475.         /* Reset line type, backup and insert fold symbol */
  476.         curwp->w_dotp->l_type = ltype;
  477.         curwp->w_dotp = curwp->w_dotp->l_bp;
  478.         strcpy(foldstr, mprefix);
  479.         strcat(foldstr, FOLDSYMBOL);
  480.         linstr(foldstr);
  481.         topboundary = curwp->w_dotp;
  482.         curwp->w_dotp = curwp->w_dotp->l_fp;
  483.         curwp->w_doto = 0;
  484.  
  485.         /* move forward to the end of this region
  486.            (a long number of bytes perhaps) */
  487.         while (creg.r_size > (long)32000) {
  488.                 forwchar(TRUE, 32000);
  489.                 creg.r_size -= (long)32000;
  490.         }
  491.         forwchar(TRUE, (int)creg.r_size);
  492.         curwp->w_doto = 0;              /* only full lines! */
  493.  
  494.         /* Unless line is normal cannot insert nl at left margin */
  495.         ltype = curwp->w_dotp->l_type;
  496.         /* exception is end of open fold */
  497.         if (ltype == LEOEFOLD)
  498.                 curwp->w_doto = loffset(curwp->w_dotp);
  499.         else {
  500.                 curwp->w_dotp->l_type = LNORMAL;
  501.                 curwp->w_doto = curwp->w_dotp->l_lmargin;
  502.         }
  503.         lnewline();
  504.  
  505.         /* Reset line type, backup and insert end fold symbol */
  506.         curwp->w_dotp->l_type = ltype;
  507.         curwp->w_dotp = curwp->w_dotp->l_bp;
  508.         strcpy(foldstr, mprefix);
  509.         strcat(foldstr, ENDFOLD);
  510.         linstr(foldstr);
  511.         botboundary = curwp->w_dotp;
  512.  
  513.         /* set the fold pointers and line types */
  514.         topboundary->l_type = LSOFOLD;
  515.         topboundary->l_foldp = botboundary;
  516.         botboundary->l_type = LEOFOLD;
  517.         botboundary->l_foldp = topboundary;
  518.  
  519.         /* set left margin? */
  520.         if (i) {
  521.                 curwp->w_dotp = topboundary->l_fp;
  522.                 i += curwp->w_dotp->l_lmargin;
  523.                 while (curwp->w_dotp != botboundary) {
  524.                         if (loffset(curwp->w_dotp) < i) {
  525.                                 /* insert prefix - else problems! */
  526.                                 curwp->w_doto = curwp->w_dotp->l_lmargin;
  527.                                 linstr(mprefix);
  528.                         }
  529.                         if (curwp->w_dotp->l_lmargin < i) /* not inner fold */
  530.                                 curwp->w_dotp->l_lmargin = i;
  531.                         curwp->w_dotp = curwp->w_dotp->l_fp; /* lforw() won't find the line */  
  532.                 }
  533.         }
  534.  
  535.         /* move cursor to fold line */
  536.         curwp->w_dotp = topboundary;
  537.         curwp->w_doto = llength(curwp->w_dotp);
  538.  
  539.         /* clear out marks */
  540.         for (i = 0; i < NMARKS; i++)
  541.                 bp->b_markp[i] = (LINE *)NULL;
  542.  
  543.         /* let all the proper windows be updated */
  544.         wp = wheadp;
  545.         while (wp) {
  546.                 if (wp->w_bufp == bp)
  547.                         wp->w_flag |= (WFHARD|WFMODE);
  548.                 wp = wp->w_wndp;
  549.         }
  550.  
  551.         mlwrite(TEXT224);
  552. /*              "[Buffer folded]" */
  553.  
  554.         return(TRUE);
  555. }
  556. /*}}}*/
  557.  
  558.  
  559. /*      removefold:     Remove the fold at the current dot position.
  560. */
  561.  
  562. /*{{{  PASCAL NEAR removefold(f, n)*/
  563. PASCAL NEAR removefold(f, n)
  564. {
  565.         BUFFER *bp;              /* buffer having fold removed */
  566.         WINDOW *wp;              /* windows to fix up pointers in as well */
  567.         LINE   *lp;              /* line loop for reset of margin */
  568.         int    margval;          /* value to set margin to */
  569.  
  570.         if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
  571.                 return(rdonly());       /* we are in read only mode     */
  572.  
  573.         /* find the proper buffer */
  574.         bp = curwp->w_bufp;             
  575.  
  576.         if (curwp->w_dotp->l_type == LSOFOLD) {
  577.  
  578.                 /* set line types to normal */
  579.                 curwp->w_dotp->l_type = LNORMAL;
  580.                 curwp->w_dotp->l_foldp->l_type = LNORMAL;
  581.  
  582.                 /* set all margins to that of any outer fold */
  583.                 margval = minleftmarg(curwp->w_dotp);
  584.                 lp = curwp->w_dotp->l_fp;
  585.                 while (lp != curwp->w_dotp->l_foldp) {
  586.                         lp->l_lmargin = margval;
  587.                         lp = lforw(lp);
  588.                 }
  589.  
  590.                 /* and remove them */
  591.                 lfree(curwp->w_dotp->l_foldp);
  592.                 lfree(curwp->w_dotp);
  593.  
  594.                 /* let all the proper windows be updated */
  595.                 wp = wheadp;
  596.                 while (wp) {
  597.                         if (wp->w_bufp == bp)
  598.                                 wp->w_flag |= (WFHARD|WFMODE);
  599.                         wp = wp->w_wndp;
  600.                 }
  601.                 bp->b_flag |= BFCHG; /* flag change */
  602.                 mlwrite(TEXT223);
  603.                 /* "[Fold Removed]" */
  604.                 return(TRUE);
  605.         }
  606.         else {
  607.                 mlwrite(TEXT225);
  608.                 /* "%% Not a fold line" */
  609.                 return(FALSE);
  610.         }
  611. }
  612. /*}}}*/
  613.  
  614.  
  615. /*      delfold:        Delete the fold at the current dot position.
  616. */
  617.  
  618. /*{{{  PASCAL NEAR delfold(f, n)*/
  619. PASCAL NEAR delfold(f, n)
  620. {
  621.         BUFFER *bp;              /* buffer having fold deleted */
  622.         WINDOW *wp;              /* windows to fix up pointers in as well */
  623.         LINE   *lp;              /* lines being deleted */
  624.  
  625.         /* find the proper buffer */
  626.         bp = curwp->w_bufp;             
  627.  
  628.         if (curwp->w_dotp->l_type == LSOFOLD) {
  629.  
  630.                 /* set all line types to normal */
  631.                 lp = curwp->w_dotp;
  632.                 while (lp != curwp->w_dotp->l_foldp->l_fp) {
  633.                         lp->l_type = LNORMAL; 
  634.                         lp = lp->l_fp;
  635.                 }
  636.                 curwp->w_doto = 0;
  637.                 curwp->w_markp[0] = curwp->w_dotp->l_foldp->l_fp;
  638.                 curwp->w_marko[0] = 0;
  639.                 killregion(FALSE, 0);
  640.                 mlwrite(TEXT229);
  641.                 /* "[Fold Deleted]" */
  642.                 return(TRUE);
  643.         }
  644.         else {
  645.                 mlwrite(TEXT225);
  646.                 /* "%% Not a fold line" */
  647.                 return(FALSE);
  648.         }
  649. }
  650. /*}}}*/
  651.  
  652. /*      losequote:         remove leading quotes from a string
  653. */
  654.  
  655. /*{{{  void losequote(str)*/
  656. void losequote(str)
  657. char *str;
  658. {
  659.    char  tmp[NSTRING];
  660.    
  661.    if (*str == '"') {
  662.       strcpy(tmp,str+1);
  663.       strcpy(str,tmp);
  664.    }
  665. }
  666. /*}}}*/
  667.  
  668.  
  669. /*      setfoldmarks:      set fold marker strings for a given file extension
  670. */
  671.  
  672. /*{{{  int PASCAL NEAR setfoldmarks(f,n)*/
  673. int PASCAL NEAR setfoldmarks(f,n)
  674. int f,n;
  675. {
  676.    register int status;
  677.    char startf[NFOLD],afterf[NFOLD],endf[NFOLD],ext[NSTRING];
  678.    FOLDMARKENT *fold_ent, *old_ent;
  679.  
  680.    status = TRUE; /* MJB: 19-Oct-89 */
  681.  
  682.    if (clexec == FALSE) {
  683.       status = mlreply(TEXT233, ext, NSTRING+1);
  684. /*                      "File extension: " */
  685.       if (status != TRUE)
  686.          return(status);
  687.    }
  688.    else {
  689.       execstr = token(execstr, ext, NSTRING+1);
  690.    }
  691.    losequote(ext);
  692.  
  693.    if (clexec == FALSE) {
  694.       status = mlreply(TEXT234, &startf[0], NFOLD+1);
  695. /*                      "Start fold text: " */
  696.       if (status != TRUE)
  697.          return(status);
  698.    }
  699.    else {
  700.       execstr = token(execstr, startf, NFOLD+1);
  701.    }
  702.    losequote(startf);
  703.    
  704.    if (clexec == FALSE) {
  705.       status = mlreply(TEXT235, endf, NFOLD+1);
  706. /*                      "End fold text: " */
  707.       if (status != TRUE)
  708.          return(status);
  709.    }
  710.    else {
  711.       execstr = token(execstr, endf, NFOLD+1);
  712.    }
  713.    losequote(endf);
  714.    
  715.    if (clexec == FALSE) {
  716.       status = mlreply(TEXT236, afterf, NFOLD+1);
  717. /*                      "After fold text: " */
  718.       if (status != TRUE)
  719.          return(status);
  720.    }
  721.    else {
  722.       execstr = token(execstr, afterf, NFOLD+1);
  723.    }
  724.    losequote(afterf);
  725.    
  726.    fold_ent = foldmarktab;
  727.    old_ent = NULL;
  728.    while (fold_ent != NULL) {
  729.       if (strcmp(ext, fold_ent->fm_extension) == 0)
  730.          old_ent = fold_ent;
  731.       
  732.       fold_ent = fold_ent->fm_next;
  733.    }
  734.    
  735.    if (old_ent == NULL) {
  736.       /* Build a new fold table entry */
  737.       fold_ent = (FOLDMARKENT *)malloc(sizeof(FOLDMARKENT));
  738.       fold_ent->fm_extension  = malloc(NSTRING);
  739.       fold_ent->fm_startopen  = malloc(NFOLD);
  740.       fold_ent->fm_startclose = malloc(NFOLD);
  741.       fold_ent->fm_end        = malloc(NFOLD);
  742.  
  743.       /* link it in to the fold mark list */
  744.       fold_ent->fm_next = foldmarktab;
  745.       foldmarktab = fold_ent;
  746.    }
  747.    else {
  748.       fold_ent = old_ent;
  749.    }
  750.  
  751.    /* Copy in the strings */
  752.    strcpy(fold_ent->fm_extension,  ext);
  753.    strcpy(fold_ent->fm_startopen,  startf);
  754.    strcpy(fold_ent->fm_startclose, afterf);
  755.    strcpy(fold_ent->fm_end,        endf);
  756.    
  757.    return(status);
  758. }
  759. /*}}}*/
  760.  
  761. /* setfoldstring: create a fold table entry for a given extension
  762. */
  763.  
  764. PASCAL NEAR setfoldstring(ext,startf,endf,afterf)
  765. char *ext,*startf,*endf,*afterf;
  766. {
  767.    FOLDMARKENT *fold_ent, *old_ent;
  768.  
  769.    fold_ent = foldmarktab;
  770.    old_ent = NULL;
  771.    while (fold_ent != NULL) {
  772.       if (strcmp(ext, fold_ent->fm_extension) == 0)
  773.          old_ent = fold_ent;
  774.       
  775.       fold_ent = fold_ent->fm_next;
  776.    }
  777.    
  778.    if (old_ent == NULL) {
  779.       /* Build a new fold table entry */
  780.       fold_ent = (FOLDMARKENT *)malloc(sizeof(FOLDMARKENT));
  781.       fold_ent->fm_extension  = malloc(NSTRING);
  782.       fold_ent->fm_startopen  = malloc(NFOLD);
  783.       fold_ent->fm_startclose = malloc(NFOLD);
  784.       fold_ent->fm_end        = malloc(NFOLD);
  785.  
  786.       /* link it in to the fold mark list */
  787.       fold_ent->fm_next = foldmarktab;
  788.       foldmarktab = fold_ent;
  789.    }
  790.    else {
  791.       fold_ent = old_ent;
  792.    }
  793.  
  794.    /* Copy in the strings */
  795.    strcpy(fold_ent->fm_extension,  ext);
  796.    strcpy(fold_ent->fm_startopen,  startf);
  797.    strcpy(fold_ent->fm_startclose, afterf);
  798.    strcpy(fold_ent->fm_end,        endf);
  799. }
  800.  
  801. /* initfoldstrings: setup default fold mark strings
  802. */
  803.  
  804. PASCAL NEAR initfoldstrings()
  805. {
  806.    setfoldstring("c",   "/*{{{  ", "/*}}}*/", " */");
  807.    setfoldstring("h",   "/*{{{  ", "/*}}}*/", " */");
  808.    setfoldstring("pas", "(*{{{  ", "(*}}}*)", " *)");
  809.    setfoldstring("p",   "(*{{{  ", "(*}}}*)", " *)");
  810.    setfoldstring("bcp", "//{{{  ", "//}}}",    "");
  811.    setfoldstring("occ", "--{{{  ", "--}}}",    "");
  812.    setfoldstring("tex", "%%{{{  ", "%%}}}",    "");
  813.    setfoldstring("ps",  "%%{{{  ", "%%}}}",    "");
  814.    setfoldstring("asm", ";{{{  ",  ";}}}",     "");
  815.    setfoldstring("inc", ";{{{  ",  ";}}}",     "");
  816. }
  817.  
  818.  
  819. /*
  820.  * minleftmarg -- Find the minimum left margin value for the
  821.  *                current line. Searches back up to enclosing
  822.  *                open fold. MJB: 17-Oct-89.
  823.  */
  824. int PASCAL NEAR minleftmarg(lp)
  825. LINE    *lp;
  826. {
  827.         if (lp->l_type == LEOEFOLD)
  828.                 return(lp->l_foldp->l_lmargin);
  829.  
  830.         lp = lp->l_bp;
  831.         while ((lp != curwp->w_bufp->b_linep) &&
  832.                (lp->l_type != LSOEFOLD)) {
  833.                 if ((lp->l_type == LEOFOLD) ||
  834.                     (lp->l_type == LEOEFOLD))
  835.                         lp = lp->l_foldp;
  836.                 lp = lp->l_bp;
  837.         }
  838.         if (lp->l_type == LSOEFOLD)
  839.                 return(loffset(lp));
  840. /*              return(lp->l_lmargin); */
  841.         else
  842.                 return(0);
  843. }
  844.  
  845.  
  846. /*
  847.  * openoutfolds -- open any nested folds above the current (moved)
  848.  *                 dot position. MJB: 13-Oct-89.
  849.  */
  850. PASCAL NEAR openoutfolds()
  851. {
  852.         LINE *lp;
  853.         BUFFER *bp;
  854.         WINDOW *wp;
  855.         int    i, j;
  856.         char   tmpstr[NSTRING];
  857.  
  858.         /* find the proper buffer */
  859.         bp = curwp->w_bufp;             
  860.  
  861.         lp = curwp->w_dotp; /* start at new position */
  862.         if (lp->l_type == LEOFOLD) /* special case upon entry    */
  863.                 lp = lp->l_foldp;  /* only time this can be true */
  864.         while (lp != curwp->w_bufp->b_linep) { /* check */
  865.                 if (lp->l_type == LSOFOLD) { /* open it */
  866.                         lp->l_type = LSOEFOLD;
  867.                         lp->l_foldp->l_type = LEOEFOLD;
  868.                         i = indx(lp->l_text, FOLDSYMBOL);
  869.                         strcpy(tmpstr, BEGINFOLD);
  870.                         for (j = 0; j < strlen(FOLDSYMBOL); j ++)
  871.                                 lp->l_text[i + j] = tmpstr[j];
  872.                         }
  873.                 else if (lp->l_type == LEOFOLD) /* jump round it */
  874.                         lp = lp->l_foldp;
  875.                 lp = lp->l_bp;
  876.         }
  877.  
  878.         /* let all the proper windows be updated */
  879.         wp = wheadp;
  880.         while (wp) {
  881.                 if (wp->w_bufp == bp)
  882.                         wp->w_flag |= (WFHARD|WFMODE|WFFORCE);
  883.                 wp = wp->w_wndp;
  884.         }
  885.         return(TRUE);
  886. }
  887.  
  888.  
  889.