home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / wp_dtp / xdme1820.lha / XDME / edit.c < prev    next >
C/C++ Source or Header  |  1993-03-06  |  23KB  |  1,229 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     edit.c
  5.  
  6.     DESCRIPTION
  7.     Everything for editing like DEL, BS, INDENT, DELINE, INSLINE, ...
  8.  
  9.     NOTES
  10.  
  11.     BUGS
  12.  
  13.     TODO
  14.  
  15.     EXAMPLES
  16.  
  17.     SEE ALSO
  18.  
  19.     INDEX
  20.  
  21.     HISTORY
  22.     14. Nov 1992    ada created
  23.  
  24. ******************************************************************************/
  25.  
  26. /**************************************
  27.         Includes
  28. **************************************/
  29. #include "defs.h"
  30. #include "clipboard.h"
  31. #define MYDEBUG     0
  32. #include <debug.h>
  33.  
  34.  
  35. /**************************************
  36.         Globale Variable
  37. **************************************/
  38.  
  39.  
  40. /**************************************
  41.       Interne Defines & Strukturen
  42. **************************************/
  43.  
  44.  
  45. /**************************************
  46.         Interne Variable
  47. **************************************/
  48.  
  49.  
  50. /**************************************
  51.        Interne Prototypes
  52. **************************************/
  53. Prototype void do_bs         (void);
  54. Prototype void do_del         (void);
  55. Prototype void do_remeol     (void);
  56. Prototype void do_split      (void);
  57. Prototype int  do_join         (void);
  58. Prototype void do_reformat   (int);
  59. Prototype void do_insertmode (void);
  60. Prototype void do_insline    (void);
  61. Prototype void do_deline     (void);
  62. Prototype void do_tlate      (void);
  63. Prototype void do_justify    (void);
  64. Prototype void do_unjustify  (void);
  65. Prototype void do_indent     (void);
  66. Prototype void do_inslines   (void);
  67. Prototype void do_delete     (void);
  68. Prototype void do_delines    (void);
  69. Prototype void do_undeline   (void);
  70. Prototype void do_space      (void);
  71. Prototype void do_clipins    (void);
  72. Prototype void do_return     (void);
  73.  
  74.  
  75. void do_bs (void)
  76. {
  77.     ED     * ep  = Ep;
  78.     RP     * rp  = ep->win->RPort;
  79.     short  i,
  80.        col = ep->column;
  81.     Column right;
  82.     Bool   is_bs = (av[0][0] == 'b');
  83.  
  84.     if ((Current[col] && !is_bs) || (col && is_bs))
  85.     {
  86.     if (is_bs)
  87.     {
  88.         movmem (Current + col, Current + col - 1, Clen - col + 1);
  89.  
  90.         col --;
  91.         ep->column --;
  92.  
  93.     } else
  94.         movmem (Current + col + 1, Current + col, Clen - col);
  95.  
  96.     Clen --;
  97.  
  98.     i = ep->line;
  99.     right = ep->topcolumn + Columns;
  100.  
  101.     if (!Nsu) {                         /* PATCH_NULL [09-Dec-92] : line added */
  102.         if (col < ep->topcolumn)
  103.         {
  104.         text_adjust (FALSE);
  105.         } else
  106.         {
  107.         if (is_inblock (i, right))
  108.         {
  109.             SetAPen (rp, BLOCK_FPEN);
  110.             SetBPen (rp, BLOCK_BPEN);
  111.         } else
  112.         {
  113.             SetAPen (rp, TEXT_FPEN);
  114.             SetBPen (rp, TEXT_BPEN);
  115.         }
  116.  
  117.         SetWrMsk (rp, BLOCK_MASK);
  118.  
  119.         i -= ep->topline;
  120.  
  121.         ScrollRaster(rp, Xsize, 0,
  122.             COL(col - ep->topcolumn),
  123.             ROW(i),
  124.             Xpixs,
  125.             ROW(i + 1) - 1
  126.         );
  127.  
  128.         if (Clen >= right)
  129.         {
  130.             right --;
  131.  
  132.             Move (rp, COLT(right - ep->topcolumn), ROWT(i));
  133.             Text (rp, Current + right, 1);
  134.         }
  135.         }
  136.     } /* if !Nsu */             /* PATCH_NULL [09-Dec-92] : line added */
  137.  
  138.     if (!globalflags.Comlinemode && ep->config.wordwrap)
  139.         do_reformat(0);
  140.     } else
  141.     {
  142.     globalflags.Abortcommand = 1;
  143.     }
  144. } /* do_bs */
  145.  
  146.  
  147. void do_remeol (void)
  148. {
  149.     Current[Clen = Ep->column] = 0;
  150.  
  151.     text_sync ();
  152.     text_redisplaycurrline ();
  153. } /* do_remeol */
  154.  
  155.  
  156. void do_split (void)              /* split line in two at cursor pos */
  157. {
  158.     ubyte buf[MAXLINELEN];
  159.     ED    * ep           = Ep;
  160.     RP    * rp           = ep->win->RPort;
  161.     char  onLastLine;
  162.  
  163.     strcpy ((char *)buf, (char *)Current+ep->column);
  164.     Current[Clen = ep->column] = '\0';
  165.  
  166.     text_sync ();
  167.  
  168.     SetAPen (rp, TEXT_BPEN);
  169.     SetWrMsk (rp, -1);
  170.  
  171.     if (!Nsu)
  172.     RectFill (rp, COL(0), ROW(ep->line-ep->topline),
  173.            Xpixs, ROW(ep->line-ep->topline+1)-1);
  174.  
  175.     SetAPen (rp, TEXT_FPEN);
  176.  
  177.     text_displayseg (ep->line - ep->topline, 1);
  178.  
  179.     onLastLine = (ep->line == ep->lines-1);
  180.     do_downadd ();
  181.  
  182.     if (!onLastLine)
  183.     do_insline ();
  184.  
  185.     strcpy ((char *)Current, (char *)buf);
  186.     Clen = strlen ((char *)Current);
  187.  
  188.     text_sync ();
  189.     text_displayseg (ep->line - ep->topline, 1);
  190.  
  191.     do_up ();
  192. } /* do_split */
  193.  
  194.  
  195. int do_join (void)
  196. {
  197.     int   i = Clen, j;
  198.     ED * ep = Ep;
  199.  
  200.     /* Check if there is a line below and the length of both lines */
  201.     if (ep->line + 1 < ep->lines &&
  202.         LINELEN(ep,ep->line+1)+i <= MAXLINELEN-2)
  203.     {
  204.     /* Add a space */
  205.     if (i && Current[i-1] != ' ')
  206.         Current[i++] = ' ';
  207.  
  208.     /* Copy the line */
  209.     strcpy((char *)Current+i, GETTEXT(ep,ep->line+1));
  210.  
  211.     /* Find first nonspace */
  212.     for (j = i; Current[j] == ' '; ++j);
  213.     /* Find last space */
  214.     for (; i >= 0 && Current[i] == ' '; --i);
  215.  
  216.     /* Too many spaces ? */
  217.     if (j > i+2)
  218.         movmem (Current+j, Current+i+2, strlen((char *)Current+j)+1);
  219.  
  220.     /* new length */
  221.     Clen = strlen ((char *)Current);
  222.  
  223.     /* redisplay */
  224.     text_sync ();
  225.     text_displayseg (ep->line - ep->topline, 1);
  226.  
  227.     i = text_lineno ();
  228.  
  229.     do_down ();
  230.     do_deline ();
  231.  
  232.     if (i != text_lineno ())
  233.         do_up ();
  234.  
  235.     return(1);
  236.     }
  237.  
  238.     return(0);
  239. } /* do_join */
  240.  
  241.  
  242. /*
  243.  * n == -1  :    force reformat entire paragraph
  244.  * n ==  0  :    only until line equalizes (from text_write())
  245.  *
  246.  * What is a paragraph?   A paragraph ends whenever the left justification
  247.  * gets larger, or on a blank line.
  248.  */
  249.  
  250. void do_reformat (int n)
  251. {
  252.     char * str;
  253.     ED     * ep = Ep;
  254.     RP     * rp = ep->win->RPort;
  255.     int    nlok;   /* Next Line ok ? */
  256.     int    lnsc;   /* LastNS of Current */
  257.     int    fnst;   /* FirstNS of next Line */
  258.     int    fnsc;    /* FirstNS of Current */
  259.     int    column  = ep->column;
  260.     int    srow    = ep->line;
  261.     int    crow    = srow;
  262.     int    erow    = srow;
  263.     short  dins    = 0;     /* relative insert lines/delete lines    */
  264.     char   moded   = 0;     /* any modifications done at all?    */
  265.     char   checked = 0;     /* for cursor positioning.        */
  266.  
  267.     if (ep->config.margin == 0)
  268.     ep->config.margin = 75;
  269.  
  270.     Nsu ++;
  271.  
  272.     for (;;)
  273.     {
  274.     str = GETTEXT(ep,ep->line+1);
  275.     fnst = 0;
  276.     fnsc = firstns((char *)Current);
  277.     nlok = (ep->line + 1 < ep->lines && fnsc >= (fnst=firstns(str)));
  278.     if (ep->config.wwcol >= 0)
  279.         fnst = fnsc = ep->config.wwcol;
  280.     if (nlok && str[0] == 0)
  281.         nlok = 0;
  282.     lnsc = lastns((char *)Current);
  283.     if (lnsc < ep->config.margin)
  284.     {    /* space at end of line for marg-lnsc-2 letter word   */
  285.         if (nlok == 0)        /* but no more data to joinup   */
  286.         break;          /* done */
  287.         if (ep->config.margin - lnsc - 2 >= wordlen(str+fnst))
  288.         {
  289.         ep->column = 0;
  290.         Clen = lastns((char *)Current);
  291.         if (Current[Clen])
  292.             ++Clen;
  293.         moded = 1;
  294.         --dins;
  295.         if (do_join())
  296.             continue;
  297.         ++dins;
  298.  
  299.         error ("reformat:\nMargin too big");
  300.         break;
  301.         }
  302.         if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  303.         break;
  304.         do_down ();
  305.         erow = ep->line;
  306.         continue;
  307.     }
  308.                 /* no space, need to split    */
  309.                 /* find start of prev word    */
  310.     for (;;)
  311.     {
  312.         int i = lnsc;
  313.         while (i && Current[i] != ' ')
  314.         --i;
  315.         lnsc = i;
  316.         if (i >= ep->config.margin)
  317.         {
  318.         while (i && Current[i] == ' ')
  319.             --i;
  320.         if (i < ep->config.margin)
  321.             break;
  322.         lnsc = i;
  323.         } else
  324.         break;
  325.     }
  326.  
  327.     /* Word too long */
  328.     if (wordlen((char *)Current+lnsc) >= ep->config.margin)
  329.     {
  330.         error ("reformat:\nWord too long");
  331.         break;
  332.     }
  333.  
  334.     if (lnsc)
  335.     {          /* ok to split at word          */
  336.         ++lnsc;
  337.         ++dins;
  338.         ep->column = lnsc;
  339.         do_split (); /* Split at point LNSC          */
  340.         do_down ();          /* must insert proper amount?   */
  341.         {
  342.         int indent = (nlok == 0) ? fnsc : fnst;
  343.         if (ep->config.wwcol >= 0)
  344.             indent = ep->config.wwcol;
  345.         if (!checked)
  346.         {
  347.             checked = 1;
  348.             if (lnsc <= column)
  349.             {    /* if split before cursor   */
  350.             column = column - ep->column + indent;
  351.             ++crow;
  352.             }
  353.         }
  354.         if (Clen + indent < 253)
  355.         {
  356.             movmem(Current, Current + indent,
  357.                 strlen((char *)Current)+1);
  358.             setmem(Current, indent, ' ');
  359.             Clen += indent;
  360.         }
  361.         }
  362.         erow = ep->line;
  363.         continue;
  364.     }
  365.  
  366.     if (n == 0)
  367.         break;
  368.  
  369.     do_down ();
  370.     }
  371.  
  372.     if (column < 0 || column > 200)
  373.     column = 0;
  374.     if (srow >= ep->lines)
  375.     {
  376.     srow = ep->lines - 1;
  377.     goto ra;
  378.     }
  379.     if (dins || srow < ep->topline || srow >= ep->topline + Lines)
  380.     {
  381. ra:
  382.     text_sync ();
  383.  
  384.     Nsu --;
  385.  
  386.     ep->line = crow;
  387.     ep->column = column;
  388.     text_load ();
  389.  
  390.     text_adjust (TRUE);
  391.     } else
  392.     {
  393.     text_sync ();
  394.  
  395.     Nsu --;
  396.  
  397.     ep->line = crow;
  398.     ep->column = column;
  399.  
  400.     text_load ();
  401.  
  402.     if (erow != srow)
  403.     {
  404.         if (!text_adjust (FALSE))
  405.         {
  406.         erow ++;
  407.  
  408.         if (erow - ep->topline > Lines)
  409.             erow = ep->topline + Lines;
  410.  
  411.         SetAPen(rp, TEXT_BPEN);
  412.         SetWrMsk (rp, -1);
  413.  
  414.         RectFill(rp, COL(0), ROW(srow - ep->topline),
  415.             Xpixs, ROW(erow - ep->topline)-1);
  416.  
  417.         SetAPen(rp, TEXT_FPEN);
  418.  
  419.         text_displayseg(srow - ep->topline, erow - srow);
  420.         }
  421.     } else
  422.     {
  423.         text_sync ();
  424.  
  425.         if (moded)
  426.         text_redisplaycurrline ();
  427.     }
  428.     }
  429.     if (column > Clen)
  430.     {
  431.     setmem(Current+Clen, column - Clen, ' ');
  432.     Current[column] = 0;
  433.     }
  434.     ep->column = column;
  435. } /* do_reformat */
  436.  
  437.  
  438. void do_insline (void)
  439. {
  440.     ubyte *ptr;
  441.     ED *ep = Ep;
  442.  
  443.     ep->modified = 1;
  444.  
  445.     text_sync ();
  446.  
  447.     if (makeroom (32))
  448.     {
  449.     ptr = allocline (1);
  450.  
  451.     bmovl(ep->list+ep->line, ep->list+ep->line+1,ep->lines-ep->line);
  452.     GETTEXT(ep,ep->line) = ptr;
  453.  
  454.     ep->lines ++;
  455.  
  456.     if (ActualBlock.ep == ep)
  457.     {
  458.         if (ep->line <= ActualBlock.start_line)
  459.         ActualBlock.start_line ++;
  460.         if (ep->line <= ActualBlock.end_line)
  461.         ActualBlock.end_line ++;
  462.     }
  463.     } else
  464.     {
  465.     nomemory ();
  466.     }
  467.  
  468.     text_load ();
  469.  
  470.     if (Nsu == 0)
  471.     {
  472.     scroll_display (0, -1, 0, ep->line, MAXLINELEN, ep->topline+Lines);
  473.     text_displayseg (ep->line - ep->topline, 1);
  474.     }
  475. } /* do_insline */
  476.  
  477.  
  478. void do_deline (void)
  479. {
  480.     int delline, eline;
  481.     ED *ep = Ep;
  482.  
  483.     /* store line for later UNDO */
  484.     strcpy ((char *)Deline, (char *)Current);
  485.  
  486.     if (ep->lines > 1)
  487.     {
  488.     ep->modified = 1;
  489.  
  490.     text_sync ();
  491.  
  492.     /* remove line */
  493.     freeline (GETTEXT(ep,ep->line));
  494.     bmovl (ep->list+ep->line+1, ep->list+ep->line, ep->lines-ep->line-1);
  495.  
  496.     /* adjust block */
  497.     if (ActualBlock.ep == ep)
  498.     {
  499.         if (ep->line < ActualBlock.start_line)
  500.         ActualBlock.start_line --;
  501.  
  502.         if (ep->line <= ActualBlock.end_line)
  503.         ActualBlock.end_line --;
  504.     }
  505.  
  506.     /* remember line we deleted */
  507.     delline = ep->line;
  508.  
  509.     /* line was last one */
  510.     if (ep->line >= --ep->lines)
  511.     {
  512.         /* move up one line */
  513.         --ep->line;
  514.  
  515.         /* get the line into current */
  516.         text_load ();
  517.  
  518.         /* line now below topline ? */
  519.         if (ep->line < ep->topline)
  520.         {
  521.         /* update screen if allowed */
  522.         if (!Nsu)
  523.         {
  524.             /* find new position */
  525.             ep->topline = ep->line - (Lines>>1);
  526.  
  527.             if (ep->topline < 0)
  528.             ep->topline = 0;
  529.  
  530.             text_redisplay ();
  531.         }
  532.  
  533.         return;
  534.         }
  535.     }
  536.  
  537.     /* get line */
  538.     text_load ();
  539.  
  540.     /* update display */
  541.     if (!Nsu)
  542.     {
  543.         eline = ep->topline + Lines - 1;
  544.  
  545.         if (ep->lines < eline)
  546.         eline = ep->lines +1;
  547.  
  548.         scroll_display (0, 1, ep->topcolumn, delline,
  549.                   ep->topcolumn+Columns-1, eline);
  550.     }
  551.     } else
  552.     {
  553.     /* no more lines in the text */
  554.     do_firstcolumn ();
  555.     do_remeol ();
  556.     ep->modified = 0;
  557.     }
  558. } /* do_deline */
  559.  
  560.  
  561. void do_tlate (void)
  562. {
  563.     ubyte * ptr = av[1];
  564.     ED      * ep    = Ep;
  565.     ubyte   c    = Current[ep->column];
  566.  
  567.     if (c == 0)
  568.     c = ' ';
  569.  
  570.     switch (*ptr)
  571.     {
  572.     case '+':
  573.         c += strtol ((char *)ptr+1, NULL, 0);
  574.         break;
  575.  
  576.     case '-':
  577.         c -= strtol ((char *)ptr+1, NULL, 0);
  578.         break;
  579.  
  580.     case '"':
  581.         c = ptr[1];
  582.         break;
  583.  
  584.     case 'u':
  585.     case 'U':
  586.         c = toupper (c);
  587.         break;
  588.  
  589.     case 'l':
  590.     case 'L':
  591.         c = tolower (c);
  592.         break;
  593.  
  594.     default:
  595.         c = strtol ((char *)ptr, NULL, 0);
  596.     }
  597.  
  598.     if (c)
  599.     {
  600.     if (Current[ep->column] == 0)
  601.     {
  602.         Clen = ep->column + 1;
  603.         Current[Clen] = 0;
  604.     }
  605.  
  606.     Current[ep->column] = c;
  607.  
  608.     if (!Nsu)
  609.     {
  610.         LINE * text_line;
  611.  
  612.         /* get the actual line */
  613.  
  614.         text_line = GETLINE(ep,ep->line);
  615.  
  616.         /* if the char fits into the line, just copy it (ie. avoid
  617.            text_sync(). Else call text_sync() */
  618.  
  619.         if (ep->column < LENGTH(text_line))
  620.         (CONTENTS(text_line))[ep->column] = c;
  621.         else
  622.         text_sync ();
  623.  
  624.         /* Delete the character on screen. First, find the color
  625.            we need for this operation, then draw over it */
  626.  
  627.         if (is_inblock (ep->line, ep->column) & BP_INSIDE)
  628.         SetAPen (ep->win->RPort, BLOCK_BPEN);
  629.         else
  630.         SetAPen (ep->win->RPort, TEXT_BPEN);
  631.  
  632.         SetWrMsk (ep->win->RPort, -1);
  633.         RectFill (ep->win->RPort, COL(ep->column), ROW(ep->line),
  634.                 COL(ep->column+1)-1, ROW(ep->line+1)-1);
  635.  
  636.         /* redraw that character */
  637.  
  638.         redraw_textlineseg (ep->line, ep->column, ep->column + 1);
  639.     }
  640.     }
  641. } /* do_tlate */
  642.  
  643.  
  644. void do_justify (void)
  645. {
  646.     ED *ep = Ep;
  647.     short firstnb, lastnb, i, n, fill, c, sp;
  648.     short changed = FALSE;
  649.  
  650.     switch(av[1][0])
  651.     {
  652.     case 'c':
  653.     break;
  654.  
  655.     case 'f':
  656.         firstnb = firstns((char *)Current);
  657.         lastnb = lastns((char *)Current);
  658.         if (firstnb < lastnb && ep->config.margin < MAXLINELEN-1)
  659.         {
  660.         n = 0;
  661.         i = firstnb;
  662.         while (i <= lastnb)
  663.         {
  664.             while ((c = Current[i]) && c != ' ')
  665.             i++;
  666.             if (i <= lastnb)
  667.             {
  668.             n++;
  669.             while (Current[i] == ' ')
  670.                 i++;
  671.             }
  672.         }
  673.         fill = ep->config.margin - lastnb - 1;
  674.         i = firstnb;
  675.         Current[lastnb + 1] = 0;
  676.         if (n > 0 && fill > 0)
  677.             changed = TRUE;
  678.         while (n > 0 && fill > 0 && Current[i])
  679.         {
  680.             while ((c = Current[i]) && c != ' ')
  681.             i++;
  682.             sp = fill / n;
  683.             movmem (&Current[i], &Current[i + sp],
  684.                 strlen((char *)&Current[i]) + 1);
  685.             memset ((char *)&Current[i], ' ', sp);
  686.             while (Current[i] == ' ')
  687.             i++;
  688.             fill -= sp;
  689.             n--;
  690.         }
  691.         }
  692.     break;
  693.  
  694.     default:
  695.     break;
  696.     }
  697.  
  698.     if (changed)
  699.     {
  700.     text_sync ();
  701.     text_redisplaycurrline ();
  702.     }
  703. } /* do_justify */
  704.  
  705.  
  706. void do_unjustify (void)
  707. {
  708.     short i, j, waswhite = FALSE;
  709.     ubyte c;
  710.  
  711.     for (i = 0; Current[i] == ' '; i++);
  712.  
  713.     for (j = i; Current[i]; i++)
  714.     {
  715.     c = Current[j] = Current[i];
  716.  
  717.     if (c != ' ' || !waswhite)
  718.         j++;
  719.  
  720.     waswhite = (c == ' ');
  721.     }
  722.  
  723.     Current[j] = 0;
  724.  
  725.     if (i != j)
  726.     {
  727.     text_sync ();
  728.     text_redisplaycurrline ();
  729.     }
  730. } /* do_unjustify */
  731.  
  732.  
  733. void do_indent (void)
  734. {
  735.     Line   start,
  736.        end;
  737.     Column column;
  738.     int    indent,
  739.        dir,
  740.        align,
  741.        len,
  742.        curr_indent,
  743.        leading,
  744.        trailing,
  745.        t;
  746.     char * ptr;
  747.     RP     * rp;
  748.     LINE * linelist;
  749.  
  750.     /* decode range */
  751.     ptr = av[1];
  752.  
  753.     start = end = -1;
  754.  
  755.     while (*ptr)
  756.     {
  757.     if (*ptr == '.')
  758.     {
  759.         start = end = Ep->line;
  760.         break;
  761.     } else if (isdigit(*ptr))
  762.     {
  763.         if (start == -1)
  764.         start = atoi (ptr);
  765.         else end = atoi (ptr);
  766.  
  767.         while (isdigit(*ptr)) ptr ++;
  768.  
  769.         ptr --;
  770.     } else if (*ptr == '$')
  771.     {
  772.         if (start == -1)
  773.         start = get_pong (*ptr - '0');
  774.         else
  775.         end = get_pong (*ptr - '0');
  776.     } else if (*ptr == 'b')
  777.     {
  778.         if (!block_ok())
  779.         {
  780.         error ("indent block:\nNo block specified");
  781.         return ;
  782.         }
  783.  
  784.         if (!ptr[1])
  785.         {
  786.         start = ActualBlock.start_line;
  787.         end = ActualBlock.end_line;
  788.         } else
  789.         {
  790.         ptr ++;
  791.  
  792.         if (*ptr == 's')
  793.             indent = ActualBlock.start_line;
  794.         else
  795.             indent = ActualBlock.end_line;
  796.  
  797.         if (start == -1)
  798.             start = indent;
  799.         else
  800.             end = indent;
  801.         }
  802.     } else if (*ptr == 't')
  803.     {
  804.         start = 1;
  805.         end = Ep->lines;
  806.     } else if (*ptr == '_')
  807.     {
  808.         if (start == -1)
  809.         start = Ep->lines;
  810.         else
  811.         end = Ep->lines;
  812.     }
  813.  
  814.     ptr ++;
  815.     } /* while (*ptr) */
  816.  
  817.     if (start == -1)
  818.     {
  819.     error ("indent:\ncannot evaluate start-line");
  820.     return ;
  821.     }
  822.  
  823.     if (end == -1) end = start;
  824.  
  825.     if (start > end)
  826.     {
  827.     start ^= end;        /* Swap ! 8-O */
  828.     end   ^= start;
  829.     start ^= end;
  830.     }
  831.  
  832.     /* Now find out how to indent */
  833.  
  834.     ptr = av[2];
  835.  
  836.     dir = 1;        /* indent, i.e. insert spaces */
  837.     align = 0;        /* just insert `indent' spaces */
  838.     indent = -1;
  839.     column = 0;
  840.  
  841.     while (*ptr)
  842.     {
  843.     if (*ptr == '-')
  844.         dir = -1;        /* outdent line, i.e. delete spaces */
  845.     else if (*ptr == '.')
  846.         align = 1;        /* align line to a multiple of `indent' */
  847.     else if (*ptr == 't')
  848.         indent = Ep->config.tabstop;
  849.     else if (isdigit(*ptr))
  850.     {
  851.         indent = atoi (ptr);
  852.  
  853.         while (isdigit(*ptr)) ptr++;
  854.         ptr --;
  855.     } else if (*ptr == 'c')
  856.         column = Ep->column;
  857.  
  858.     ptr ++;
  859.     } /* while (*ptr) */
  860.  
  861.     if (indent == -1)
  862.     {
  863.     error ("indent:\nCannot evaluate indent-amount");
  864.     return ;
  865.     }
  866.  
  867.     text_sync ();
  868.  
  869.     /* Note : If the line contains less spaces than indent specifies and
  870.        the user wants to outdent, the line is left-aligned, i.e. no chars
  871.        except spaces are deleted ! This is also true for indent, i.e. no
  872.        chars are moved over the right border (MAXLINELEN chars). */
  873.  
  874.     linelist = Ep->list + start;
  875.  
  876.     for (t=start; t <= end; t ++, linelist ++)
  877.     {
  878.     strcpy (Current, linelist[0]);
  879.     Clen = strlen (Current);
  880.  
  881.     if (Clen <= column) continue;
  882.  
  883.     ptr = Current + column;
  884.  
  885.     while (*ptr == ' ') ptr ++;
  886.  
  887.     if (!*ptr) continue;          /* Empty line */
  888.  
  889.     leading  = (int)ptr - (int)Current;
  890.     trailing = MAXLINELEN-1 - Clen;
  891.  
  892.     /* Should I align the line to a multiple of indent or just
  893.         insert/delete indent spaces ? */
  894.     if (align)
  895.     {
  896.         /* use appropriate difference */
  897.         if (dir > 0)
  898.         curr_indent = indent - (leading % indent);
  899.         else
  900.         {
  901.         curr_indent = leading % indent;
  902.  
  903.         if (!curr_indent)
  904.             curr_indent = indent;
  905.         }
  906.     } else curr_indent = indent;
  907.  
  908.     len = strlen (ptr) + 1;
  909.  
  910.     if (dir > 0)
  911.     {
  912.         if (trailing < curr_indent)
  913.         curr_indent = trailing;
  914.  
  915.         if (!curr_indent) continue;
  916.  
  917.         movmem (ptr, ptr+curr_indent, len);
  918.         setmem (ptr, curr_indent, ' ');
  919.     } else
  920.     {
  921.         if (leading < curr_indent)
  922.         curr_indent = leading;
  923.  
  924.         if (!curr_indent) continue;
  925.  
  926.         movmem (ptr, ptr-curr_indent, len);
  927.     }
  928.  
  929.     Clen = strlen (Current);
  930.     len  = strlen (linelist[0]);
  931.  
  932. #ifdef DEBUG
  933. printf ("Old len %d  New Len %d     BlenOld %d  BlenNew %d\n",
  934.     len, Clen, ((len + 8) & ~7), ((Clen + 8) & ~7));
  935. #endif
  936.  
  937.     /* Find out if we have to allocate new memory */
  938.     /* Clen is total length in bytes while len is only strlen() */
  939.     /* TODO: Ain't work yet */
  940.     /*if ((((Clen + 8) & ~7) != ((len + 8) & ~7)))
  941.     {*/
  942.         ptr = allocline (Clen + 1);
  943.  
  944.         if (!ptr)
  945.         {
  946.         nomemory ();
  947.         globalflags.Abortcommand = 1;
  948.         break;
  949.         }
  950.  
  951.         freeline (linelist[0]);
  952.         linelist[0] = ptr;
  953.     /*}*/
  954.  
  955.     strcpy (ptr, Current);
  956.     } /* for (t = start; t <= end; t ++, linelist ++) */
  957.  
  958.     Ep->modified = 1;
  959.  
  960.     text_load ();
  961.  
  962.     /* Don't display if there is nothing to display */
  963.     if (end < Ep->topline)
  964.     return;
  965.  
  966.     if (start < Ep->topline)
  967.     {
  968.     start = 0;
  969.     t = end - Ep->topline +1;
  970.     } else
  971.     {
  972.     t = end - start +1;
  973.     start -= Ep->topline;
  974.  
  975.     if (start >= Lines)
  976.         return;
  977.     }
  978.  
  979.     if (t > Lines)
  980.     t = Lines;
  981.  
  982.     if (!Nsu)
  983.     {
  984.     rp = Ep->win->RPort;
  985.  
  986.     end = start + t-1;
  987.  
  988.     /* only clear area, if there is a line outside the block */
  989.     if (!is_inblock (start, -1) || !is_inblock (end, -1))
  990.     {
  991.         SetAPen (rp, TEXT_BPEN);
  992.         SetWrMsk (rp, BLOCK_MASK);
  993.         RectFill (rp, Xbase, ROW(start), Xpixs, ROW(start+t)-1);
  994.     }
  995.  
  996.     if (!text_sync ())
  997.         text_displayseg (start, t);
  998.     }
  999. } /* do_indent */
  1000.  
  1001.  
  1002. void do_inslines (void)
  1003. {
  1004.      int lines = atoi (av[1]);
  1005.  
  1006.      if (lines <= 0) return;
  1007.  
  1008.      while (lines)
  1009.      {
  1010.       do_insline ();
  1011.       lines --;
  1012.      }
  1013.  
  1014. } /* do_inslines */
  1015.  
  1016.  
  1017. void do_delete (void)
  1018. {
  1019.     char * ptr, * hptr;
  1020.  
  1021.     hptr = ptr = Current + Ep->column;
  1022.  
  1023.     if (*hptr == ' ')
  1024.     while (*hptr == ' ') hptr ++;
  1025.     else while (*hptr != ' ') hptr ++;
  1026.  
  1027.     strcpy (ptr, hptr);
  1028.  
  1029.     text_sync ();
  1030.     text_redisplaycurrline ();
  1031. } /* do_delete */
  1032.  
  1033.  
  1034. void do_delines (void)
  1035. {
  1036.      int t;
  1037.  
  1038.      t = atoi (av[1]);
  1039.  
  1040.      for ( ; t >= 0; t--)
  1041.       do_deline ();
  1042. } /* do_delines */
  1043.  
  1044.  
  1045. /*
  1046.  *  Commands submitted by Markus Wenzel
  1047.  */
  1048.  
  1049. void do_undeline (void)
  1050. {
  1051.    do_insline ();
  1052.    text_load ();
  1053.  
  1054.    strcpy((char *)Current, (char *)Deline);
  1055.  
  1056.    text_sync ();
  1057.    text_displayseg (Ep->line - Ep->topline, 1);
  1058. } /* do_undeline */
  1059.  
  1060.  
  1061. void do_clipins (void)
  1062. {
  1063.     struct IOClipReq * ior;
  1064.     struct cbbuf * buf;
  1065.  
  1066.     if (!(ior = CBOpen (0)) )
  1067.     return;
  1068.  
  1069.     if (CBQueryFTXT (ior))
  1070.     {
  1071.     buf = CBReadCHRS (ior);
  1072.  
  1073.     if (buf)
  1074.     {
  1075.         text_write ((ubyte *)buf->mem);
  1076.         CBFreeBuf (buf);
  1077.     }
  1078.  
  1079.     CBReadDone (ior);
  1080.     }
  1081.  
  1082.     CBClose (ior);
  1083. } /* do_clipins */
  1084.  
  1085.  
  1086. void do_space (void)
  1087. {
  1088.     ED * ep = Ep;
  1089.     int  insmode = ep->config.insertmode;
  1090.  
  1091.     ep->config.insertmode = 1;
  1092.     text_write (" ");
  1093.     ep->config.insertmode = insmode;
  1094. } /* do_space */
  1095.  
  1096.  
  1097. void do_return (void)
  1098. {
  1099.     char   buf[MAXLINELEN];
  1100.     char * partial;
  1101.  
  1102.     if (globalflags.Comlinemode)
  1103.     {
  1104.     strcpy (buf, (char *)Current);
  1105.  
  1106.     partial = esc_partial;    /* PATCH_NULL: P -> esc_p */
  1107.     esc_partial = NULL;    /* PATCH_NULL: P -> esc_p */
  1108.  
  1109.     escapecomlinemode ();
  1110.  
  1111.     if (partial)
  1112.     {
  1113.         if (do_command (buf))
  1114.         do_command (partial);
  1115.  
  1116.         free(partial);
  1117.     } else
  1118.         do_command (buf);
  1119.     } else
  1120.     {
  1121.     if (Ep->config.autoindent)
  1122.     {   /* If user want's autoindent */
  1123.         short  indent;  /* how much */
  1124.         short  line;    /* Line-no. */
  1125.         char * ptr;     /* pointer to Ep->list[line] */
  1126.  
  1127.         text_sync ();   /* store actual line */
  1128.  
  1129.         /* Start with current line */
  1130.         indent = 0;
  1131.         ptr = (char *)Current;
  1132.  
  1133.         /* Find 1. nonspace ... */
  1134.         while (isspace (*ptr))
  1135.         {
  1136.         ptr ++;
  1137.         indent ++;
  1138.         }
  1139.  
  1140.         /* ... but not '\0'. In this case the line is empty and
  1141.            indent is therefore 0 */
  1142.         if (!*ptr)
  1143.         indent = 0;
  1144.  
  1145.         /* Try on, if indent is zero, line is empty and there are more
  1146.            lines on top */
  1147.         if (!indent && !*ptr && Ep->line)
  1148.         {
  1149.         line = Ep->line - 1;
  1150.  
  1151.         /* Until 1. line */
  1152.         while (line)
  1153.         {
  1154.             /* Try every line */
  1155.             ptr = GETTEXT(Ep,line);
  1156.             indent = 0;
  1157.  
  1158.             while (isspace (*ptr))
  1159.             {
  1160.             ptr ++;
  1161.             indent ++;
  1162.             }
  1163.  
  1164.             if (indent || *ptr)
  1165.             break;
  1166.  
  1167.             line --;
  1168.         }
  1169.         }
  1170.  
  1171.         /* Not at last position in line ? then we have to split and
  1172.            indent the rest */
  1173.         if (Ep->column != Clen)
  1174.         {
  1175.         /* Split line, move to next line but shouldn't show this */
  1176.         do_split ();
  1177.         do_down ();
  1178.  
  1179.         /* Indent new line */
  1180.         if (indent > Ep->column)
  1181.             indent -= indent - Ep->column;
  1182.  
  1183.         if (indent > 0)
  1184.         {
  1185.             movmem (Current, Current+indent, Clen+1);
  1186.             setmem (Current, indent, ' ');
  1187.             Clen += indent;
  1188.             Ep->column = indent;
  1189.         } else
  1190.             Ep->column = 0;
  1191.  
  1192.         Current[Clen] = 0;
  1193.  
  1194.         /* and position cursor */
  1195.         text_sync ();
  1196.  
  1197.         /* Show result */
  1198.         text_redisplaycurrline ();
  1199.         } else
  1200.         {
  1201.         if (Ep->line != Ep->lines-1)
  1202.         {
  1203.             do_down ();
  1204.             do_insline ();
  1205.  
  1206.             Ep->column = indent;
  1207.             text_sync ();
  1208.         } else
  1209.         {
  1210.             do_split ();
  1211.             Ep->column = indent;
  1212.             text_sync ();
  1213.             do_down ();
  1214.         }
  1215.         }
  1216.     } else
  1217.     {
  1218.         Ep->column = 0;
  1219.         text_sync ();
  1220.         do_downadd ();
  1221.     }
  1222.     } /* !Comlinemode */
  1223. } /* do_return */
  1224.  
  1225.  
  1226. /******************************************************************************
  1227. *****  ENDE edit.c
  1228. ******************************************************************************/
  1229.