home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / YADME10.LHA / YADME10 / src / cmd2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-19  |  54.4 KB  |  2,193 lines

  1. #include <stdio.h>
  2. /*
  3.  * CMD2.C
  4.  *
  5.  *      (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  */
  7.  
  8. #include "defs.h"
  9. #include "cb.h"
  10. #include <ctype.h>
  11. #include <workbench/startup.h>
  12. #include <workbench/workbench.h>
  13. #include <intuition/intuition.h>
  14. #include <libraries/gadtools.h>
  15. #include <clib/intuition_protos.h>
  16. #include <clib/gadtools_protos.h>
  17. #include <dos/dos.h>
  18. #include <clib/dos_protos.h>
  19.  
  20.  
  21. extern Library *GadToolsBase;
  22.  
  23. typedef struct WBStartup    WBS;
  24. typedef struct DiskObject   DISKOBJ;
  25.  
  26. #define nomemory()  {memoryfail = 1;}
  27.  
  28. #ifndef offsetof
  29. #define offsetof(sname,fname)   ((long)&((sname *)0)->fname)
  30. #endif
  31.  
  32. int kill_first_line(void);
  33. int kill_last_line(void);
  34.  
  35.  
  36. #include "rexx.h"
  37. extern int foundcmd;       /* control for implicit ARexx macro invocation   */
  38. extern int cmderr;         /* global command error flag for do_rexx()'s use */
  39.  
  40. extern int GetNextLine(cbbuf *clipbuf, char *dest, int *index, int maxlen);
  41. extern int CountLineFeeds(struct cbbuf *clipbuf);
  42.  
  43. extern char MForceTitle;
  44. extern void do_bmove();
  45.  
  46. extern WBS  *Wbs;
  47.  
  48. ED *uninit_init(ED *ep)
  49. {
  50.     FONT  *font;
  51.     BPTR lock = DupLock((BPTR)ep->dirlock);
  52.     WIN *win;
  53.     struct Gadget *gadg;
  54.     int bufsiz = offsetof(struct _ED,EndConfig) - offsetof(struct _ED, BeginConfig);
  55.     char *buf = malloc(bufsiz);
  56.  
  57.     movmem(&ep->BeginConfig, buf, bufsiz);
  58.     win = ep->Win;
  59.     font = ep->Font;
  60.     gadg = ep->PropGad;
  61.     ep->Font = NULL;
  62.     text_uninit();
  63.     text_init(Ep, NULL, NULL);
  64.     ep = Ep;
  65.     if (ep->Font)
  66.         CloseFont(ep->Font);
  67.     ep->Win = win;
  68.     ep->Font = font;
  69.     ep->PropGad = gadg;
  70.  
  71.     movmem(buf, &ep->BeginConfig, bufsiz);
  72.  
  73.     ep->Modified = 0;
  74.     ep->Line = ep->Topline = 0;
  75.     UnLock((BPTR)ep->dirlock);
  76.     ep->dirlock = (long)lock;
  77.  
  78.     free(buf);
  79.     return(ep);
  80. }
  81.  
  82. void do_remeol(void)
  83. {
  84.     Current[Clen = Ep->Column] = 0;
  85.     text_sync();
  86.     text_redisplaycurrline();
  87. }
  88.  
  89. void do_wleft(void)
  90. {
  91.     ED *ep = Ep;
  92.     int i;
  93.  
  94.     for (;;) {
  95.         i = ep->Column;
  96.         if (i == 0)
  97.             goto prevline;
  98.         --i;
  99.         while (i && Current[i] == ' ')
  100.             --i;
  101.         if (i == 0 && Current[0] == ' ') {
  102. prevline:
  103.             if (Comlinemode || ep->Line == 0) {
  104.                 i = ep->Column;
  105.                 break;
  106.             }
  107.             text_sync();
  108.             --ep->Line;
  109.             text_load();
  110.             ep->Column = Clen;
  111.             continue;
  112.         }
  113.         while (i && Current[i] != ' ')
  114.             --i;
  115.         if (Current[i] == ' ')
  116.             ++i;
  117.         break;
  118.     }
  119.     ep->Column = i;
  120.     text_sync();
  121. }
  122.  
  123. void do_wright(void)
  124. {
  125.     ED *ep = Ep;
  126.     int i;
  127.  
  128.     for (;;) {
  129.         i = ep->Column;
  130.         if (i == Clen)
  131.             goto nextline;
  132.         while (i != Clen && Current[i] != ' ')  /* skip past current word */
  133.             ++i;
  134.         while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
  135.             ++i;
  136.         if (i == Clen) {
  137. nextline:
  138.             if (Comlinemode || ep->Line == ep->Lines - 1) {
  139.                 i = ep->Column;
  140.                 break;
  141.             }
  142.             text_sync();
  143.             ++ep->Line;
  144.             text_load();
  145.             ep->Column = i = 0;
  146.             if (Current[0] != ' ')
  147.                 break;
  148.             continue;
  149.         }
  150.         break;
  151.     }
  152.     ep->Column = i;
  153.     text_sync();
  154. }
  155.  
  156. /* Changed 06/94 by Karl Lukas. Added handling of character based blocks */
  157.  
  158. void do_split(void)              /* split line in two at cursor pos */
  159. {
  160.     ubyte buf[256];
  161.     ED *ep = Ep;
  162.     RP *rp = ep->Win->RPort;
  163.     char onLastLine;
  164.     int adj_start = 0;                                   /* KL */
  165.     int adj_stop = 0;                                    /* KL */
  166.  
  167.     if (Blocktype == BLOCK_CHARACTER)
  168.     {
  169.        /* BEline will be adjusted in do_downadd() */       /* KL */
  170.        if ((ep->Line == BEline) && (BEchar >= ep->Column)) /* KL */
  171.        {                                                   /* KL */
  172.           adj_stop = 1;                                    /* KL */
  173.           BEchar -= ep->Column;                            /* KL */
  174.        }                                                   /* KL */
  175.        else if ((ep->Line == BSline) &&(ep->Column <= BSchar))
  176.        {
  177.           BSline++;
  178.          /* adj_start = 1; */
  179.           BSchar -= ep->Column;
  180.        }
  181.        else if (ep->Line == BSline - 1)
  182.           adj_start = 1;
  183.     }
  184.     strcpy(buf, Current+ep->Column);
  185.     Current[Clen = ep->Column] = '\0';
  186.     text_sync();
  187.     SetAPen(rp, ep->BGPen);
  188.     if (Nsu == 0)
  189.         RectFill(rp, COL(0), ROW(ep->Line-ep->Topline), Xbase+Xpixs-1, ROW(ep->Line-ep->Topline+1)-1);
  190.     SetAPen(rp, ep->FGPen);
  191.     text_displayseg(ep->Line - ep->Topline, 1);
  192.  
  193.     onLastLine = (ep->Line == ep->Lines-1);
  194.  
  195.     do_downadd();
  196.     if (!onLastLine)
  197.         do_insline();
  198.     strcpy(Current, buf);
  199.     Clen = strlen(Current);
  200.     if (adj_start)          /* KL */ 
  201.        BSline++;            /* KL */
  202.     if (adj_stop)           /* KL */ 
  203.        BEline++;            /* KL */
  204.     text_sync();
  205.     text_displayseg(ep->Line - ep->Topline - 1, 2);     /* Changed KL */
  206.     do_up();
  207. }
  208.  
  209. int do_join(void)
  210. {
  211.     int i = Clen, j;
  212.     ED *ep = Ep;
  213.  
  214.     if (ep->Line + 1 < ep->Lines && strlen(ep->List[ep->Line+1])+i <= 253)
  215.     {
  216.         if (i && Current[i-1] != ' ')
  217.             Current[i++] = ' ';
  218.         strcpy(Current+i, ep->List[ep->Line+1]);
  219.         for (j = i; Current[j] == ' '; ++j);
  220.         for (; i >= 0 && Current[i] == ' '; --i);
  221.         if (j > i+2)
  222.             movmem(Current+j, Current+i+2, strlen(Current+j)+1);
  223.         Clen = strlen(Current);
  224.         text_sync();
  225.         text_displayseg(ep->Line - ep->Topline, 1);
  226.         {
  227.             int l = text_lineno();
  228.             do_down();
  229.             do_deline();
  230.             if (l != text_lineno())
  231.                 do_up();
  232.         }
  233.         return(1);
  234.     }
  235.     return(0);
  236. }
  237.  
  238.  
  239. /* do_join2() command added 06/94 by Karl Lukas */
  240. /* Doesn't delete leading spaces of joined line */
  241.  
  242. int do_join2(void)
  243. {
  244.     int i = Clen, j;
  245.     ED *ep = Ep;
  246.  
  247.     if (ep->Line + 1 < ep->Lines && strlen(ep->List[ep->Line+1])+i <= 253)
  248.     {
  249.         if (Blocktype == BLOCK_CHARACTER)
  250.         {
  251.            if ((ep->Line + 1) == BSline)
  252.            {
  253.               BSline--;
  254.               BSchar += i;
  255.            }
  256.            else if ((ep->Line + 1) == BEline)
  257.            {
  258.               BEchar = BEchar + i;
  259.               BEline--;
  260.            }
  261.            else if ((ep->Line == BEline) && (BEchar == i))
  262.               BEchar--;
  263.         }
  264.         strcpy(Current+i, ep->List[ep->Line+1]);
  265.         Clen = strlen(Current);
  266.         text_sync();
  267.         if (Blocktype != BLOCK_CHARACTER)
  268.            text_displayseg(ep->Line - ep->Topline, 1);
  269.         {
  270.             int l = text_lineno();
  271.             do_down();
  272.             do_deline();
  273.             if (l != text_lineno())
  274.                 do_up();
  275.         }
  276.         if (Blocktype == BLOCK_CHARACTER)
  277.            text_displayseg(ep->Line - ep->Topline, 1);
  278.         return(1);
  279.     }
  280.     return(0);
  281. }
  282.  
  283.  
  284. void do_margin(void)
  285. {
  286.     Ep->Margin = atoi(av[1]);
  287. }
  288.  
  289. void do_wordwrap(void)
  290. {
  291.     ED *ep = Ep;
  292.  
  293.     if (av[1][1] == 'n')
  294.         ep->Wordwrap = 1;
  295.     if (av[1][1] == 'f')
  296.         ep->Wordwrap = 0;
  297.     if (av[1][0] == 't')
  298.         ep->Wordwrap = 1 - ep->Wordwrap;
  299.     if (ep->Wordwrap)
  300.         title("Wordwrap ON");
  301.     else
  302.         title("Wordwrap OFF");
  303. }
  304.  
  305. void do_setparcol(void)
  306. {
  307.     Ep->WWCol = atoi(av[1]);
  308. }
  309.  
  310.  
  311. /*
  312.  * n == -1  :   force reformat entire paragraph
  313.  * n ==  0  :   only until line equalizes (from text_write())
  314.  *
  315.  * What is a paragraph?   A paragraph ends whenever the left justification
  316.  * gets larger, or on a blank line.
  317.  */
  318.  
  319. void do_reformat(int n)
  320. {
  321.     char *str;
  322.     ED *ep = Ep;
  323.     RP *rp = ep->Win->RPort;
  324.     int nlok, lnsc, fnst, fnsc;
  325.     int column = ep->Column;
  326.     int srow   = ep->Line;
  327.     int crow   = srow;
  328.     int erow   = srow;
  329.     short dins = 0;         /* relative insert lines/delete lines   */
  330.     char moded = 0;         /* any modifications done at all?       */
  331.     char checked = 0;       /* for cursor positioning.              */
  332.  
  333.     if (ep->Margin == 0)
  334.         ep->Margin = DefaultMargin;
  335.  
  336.     ++Nsu;
  337.     for (;;) {
  338.         str = (char *)ep->List[ep->Line+1];
  339.         fnst = 0;
  340.         fnsc = firstns(Current);
  341.         nlok = (ep->Line + 1 < ep->Lines && fnsc >= (fnst=firstns(str)));
  342.         if (ep->WWCol >= 0)
  343.             fnst = fnsc = ep->WWCol;
  344.         if (nlok && str[0] == 0)
  345.             nlok = 0;
  346.         lnsc = lastns(Current);
  347.         if (lnsc < ep->Margin) {    /* space at end of line for marg-lnsc-2 letter word   */
  348.             if (nlok == 0)        /* but no more data to joinup   */
  349.                 break;            /* done */
  350.             if (ep->Margin - lnsc - 2 >= wordlen(str+fnst)) {
  351.                 ep->Column = 0;
  352.                 Clen = lastns(Current);
  353.                 if (Current[Clen])
  354.                     ++Clen;
  355.                 moded = 1;
  356.                 --dins;
  357.                 if (do_join())
  358.                     continue;
  359.                 ++dins;
  360.                 title("Error, Margin > 124");
  361.                 break;
  362.             }
  363.             if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  364.                 break;
  365.             do_down();
  366.             erow = ep->Line;
  367.             continue;
  368.         }
  369.                                 /* no space, need to split      */
  370.                                 /* find start of prev word      */
  371.         for (;;) {
  372.             int i = lnsc;
  373.             while (i && Current[i] != ' ')
  374.                 --i;
  375.             lnsc = i;
  376.             if (i >= ep->Margin) {
  377.                 while (i && Current[i] == ' ')
  378.                     --i;
  379.                 if (i < ep->Margin)
  380.                     break;
  381.                 lnsc = i;
  382.                 continue;
  383.             }
  384.             break;
  385.         }
  386.         if (lnsc) {             /* ok to split at word          */
  387.             ++lnsc;
  388.             ++dins;
  389.             ep->Column = lnsc;
  390.             do_split(); /* Split at point LNSC          */
  391.             do_down();          /* must insert proper amount?   */
  392.             {
  393.                 int indent = (nlok == 0) ? fnsc : fnst;
  394.                 if (ep->WWCol >= 0)
  395.                     indent = ep->WWCol;
  396.                 if (!checked) {
  397.                     checked = 1;
  398.                     if (lnsc <= column) {   /* if split before cursor   */
  399.                         column = column - ep->Column + indent;
  400.                         ++crow;
  401.                     }
  402.                 }
  403.                 if (Clen + indent < 253) {
  404.                     movmem(Current, Current + indent, strlen(Current)+1);
  405.                     setmem(Current, indent, ' ');
  406.                     Clen += indent;
  407.                 }
  408.             }
  409.             erow = ep->Line;
  410.             continue;
  411.         }
  412.         if (n == 0)
  413.             break;
  414.         do_down();
  415.     }
  416.     if (column < 0 || column > 200)
  417.         column = 0;
  418.     if (srow >= ep->Lines) {
  419.         srow = ep->Lines - 1;
  420.         goto ra;
  421.     }
  422.     if (dins || srow < ep->Topline || srow >= ep->Topline + Rows) {
  423. ra:
  424.         text_sync();
  425.         --Nsu;
  426.         ep->Line = crow;
  427.         ep->Column = column;
  428.         text_load();
  429.         if (!text_sync())
  430.             text_redisplay();
  431.     } else {
  432.         text_sync();
  433.         --Nsu;
  434.         ep->Line = crow;
  435.         ep->Column = column;
  436.         text_load();
  437.         if (erow != srow) {
  438.             if (!text_sync()) {
  439.                 ++erow;
  440.                 if (erow - ep->Topline > Rows)
  441.                     erow = ep->Topline + Rows;
  442.                 SetAPen(rp, ep->BGPen);
  443.                 RectFill(rp, COL(0), ROW(srow - ep->Topline), Xbase+Xpixs-1, ROW(erow - ep->Topline)-1);
  444.                 SetAPen(rp, ep->FGPen);
  445.                 text_displayseg(srow - ep->Topline, erow - srow);
  446.             }
  447.         } else {
  448.             text_sync();
  449.             if (moded)
  450.                 text_redisplaycurrline();
  451.         }
  452.     }
  453.     if (column > Clen) {
  454.         setmem(Current+Clen, column - Clen, ' ');
  455.         Current[column] = 0;
  456.     }
  457.     ep->Column = column;
  458. }
  459.  
  460. void do_tabstop(void)
  461. {
  462.     Ep->Tabstop = atoi(av[1]);
  463. }
  464.  
  465. void do_insertmode(void)
  466. {
  467.     ED *ep = Ep;
  468.  
  469.     if (av[1][0]) {
  470.         switch(av[1][1] & 0x1F) {
  471.         case 'n'&0x1F:
  472.             ep->Insertmode = 1;
  473.             break;
  474.         case 'f'&0x1F:
  475.             ep->Insertmode = 0;
  476.             break;
  477.         case 'o'&0x1F:
  478.             ep->Insertmode = 1 - ep->Insertmode;
  479.             break;
  480.         }
  481.         if (ep->Insertmode)
  482.             title("Insert mode on");
  483.         else
  484.             title("Insert mode off");
  485.     }
  486. }
  487.  
  488. void do_insline(void)
  489. {
  490.     ubyte *ptr;
  491.     ED *ep = Ep;
  492.     RP *rp = ep->Win->RPort;
  493.  
  494.     ep->Modified = 1;
  495.     text_sync();
  496.     if (makeroom(32) && (ptr = allocb(1))) {
  497.         bmovl(ep->List+ep->Line, ep->List+ep->Line+1,ep->Lines-ep->Line);
  498.         ep->List[ep->Line] = ptr;
  499.         *ptr = 0;
  500.         ++ep->Lines;
  501.         if (BEp == ep) {
  502.             if (ep->Line < BSline)
  503.                 ++BSline;
  504.             if (ep->Line <= BEline)
  505.                 ++BEline;
  506.         }
  507.     } else {
  508.         nomemory();
  509.     }
  510.     text_load();
  511.     if (Nsu == 0)
  512.         ScrollRaster(rp,0,-Ysize, COL(0), ROW(ep->Line-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  513.     text_displayseg(ep->Line - ep->Topline, 1);
  514. }
  515.  
  516. void do_deline(void)
  517. {
  518.     int delline;
  519.     ED *ep = Ep;
  520.     RP *rp = ep->Win->RPort;
  521.  
  522.     strcpy(Deline, Current);
  523.     if (ep->Lines > 1) {
  524.         ep->Modified = 1;
  525.         text_sync();
  526.  
  527.         FreeMem(ep->List[ep->Line], strlen(ep->List[ep->Line])+1);
  528.         bmovl(ep->List+ep->Line+1, ep->List+ep->Line,ep->Lines-ep->Line-1);
  529.         if (BEp == ep)
  530.         {
  531.             if (Blocktype == BLOCK_CHARACTER)
  532.             {
  533.                if (BSline == BEline && BSline == ep->Line)
  534.                {
  535.                   BEp = NULL;
  536.                   BSline = BEline = BSchar = BEchar = -1;
  537.                }
  538.                else
  539.                {
  540.                   if (ep->Line < BSline)
  541.                       --BSline;
  542.                   else if (ep->Line == BSline)
  543.                      BSchar = 0;
  544.                   if (ep->Line < BEline)
  545.                       --BEline;
  546.                   else if (ep->Line == BEline)
  547.                   {
  548.                       --BEline;
  549.                       BEchar = strlen(ep->List[BEline]);
  550.                   }
  551.                }
  552.                   
  553.             }
  554.             else
  555.             {
  556.                if (ep->Line < BSline)
  557.                    --BSline;
  558.                if (ep->Line <= BEline)
  559.                    --BEline;
  560.             }
  561.         }
  562.         delline = ep->Line;
  563.         if (ep->Line >= --ep->Lines) {
  564.             --ep->Line;
  565.             text_load();
  566.             if (ep->Line < ep->Topline) {
  567.                 if (Nsu == 0) {
  568.                     ep->Topline = ep->Line - (Rows>>1);
  569.                     if (ep->Topline < 0)
  570.                         ep->Topline = 0;
  571.                     text_redisplay();
  572.                 }
  573.                 return;
  574.             }
  575.         }
  576.         text_load();
  577.         if (Nsu == 0)
  578.             ScrollRaster(rp,0,Ysize, COL(0), ROW(delline-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  579.         text_displayseg(Rows-1, 1);
  580.     } else {
  581.         do_firstcolumn();
  582.         do_remeol();
  583.         ep->Modified = 0;
  584.     }
  585. }
  586.  
  587. void do_chfilename(void)
  588. {
  589.     text_sync();
  590.     strncpy(Ep->Name, av[1], 63);
  591.     MForceTitle = 1;
  592. }
  593.  
  594. void do_clear(void)  /* Added by Karl Lukas 06/94 */
  595. {
  596.    ED *ep = Ep;
  597.  
  598.    if (ep->Modified && getyn("Delete modified Image?") == 0)
  599.       return;
  600.  
  601.    ep = uninit_init(ep);   
  602.    set_window_params();
  603.    text_load();
  604.    text_redisplay();
  605. }
  606.  
  607.  
  608. void do_edit(void)
  609. {
  610.     FILE *fi;
  611.     BPTR oldlock;
  612.     long lines;
  613.     ubyte buf[256];
  614.     ubyte *ptr;
  615.     char failed = 1;
  616.     ED *ep = Ep;
  617.     text_sync();
  618.     if (*av[0] == 'n') {        /* newfile or insfile   */
  619.         if (ep->Modified && getyn("Delete modified Image?") == 0)
  620.             return;
  621.         ep = uninit_init(ep);
  622.         strncpy(ep->Name, av[1], 63);
  623.     } else {
  624.         ep->Modified = 1;
  625.     }
  626.     lines = ep->Lines;
  627.     oldlock = CurrentDir((BPTR)ep->dirlock);
  628.  
  629.     if (fi = fopen(av[1], "r"))
  630.     {
  631.         int len;
  632.         char oktitle = 1;
  633.  
  634.         setvbuf(fi, NULL, _IOFBF, 32768);  /* KL */
  635.  
  636.         title("Loading...");
  637.         while ((len = xefgets(fi, buf, 255)) >= 0)
  638.         {
  639.             failed = 0;
  640.             if (makeroom(256) && (ptr = allocb(len+1)))
  641.             {
  642.                 ep->List[ep->Lines++] = ptr;
  643.                 movmem(buf, ptr, len+1);
  644.             }
  645.             else
  646.             {
  647.                 set_window_params();
  648.                 nomemory();
  649.                 oktitle = 0;
  650.                 break;
  651.             }
  652.         }
  653.         set_window_params();
  654.         if (oktitle)
  655.             title("OK");
  656.         fclose(fi);
  657.     }
  658.     else 
  659.     {
  660.         title("File Not Found");
  661.         cmderr = CMD_FAILED;
  662.     }
  663.  
  664.     CurrentDir(oldlock);
  665.     if (ep->Lines != 1 && lines == 1 && ep->List[0][0] == 0)
  666.     {
  667.         ep->Modified = 0;
  668.         ep->Line = 0;
  669.         FreeMem(ep->List[0], strlen(ep->List[0])+1);
  670.         bmovl(ep->List+1, ep->List,--ep->Lines);
  671.     }
  672.     else
  673.     {
  674.         if (!failed && lines <= ep->Lines - 1)
  675.         {
  676.             long bsline, beline;
  677.             short bschar, bechar;
  678.             int oldbtype = Blocktype;
  679.             ED *bep = BEp;
  680.  
  681.             bsline = BSline;
  682.             beline = BEline;
  683.             bschar = BSchar;
  684.             bechar = BEchar;
  685.  
  686.             BEp = ep;
  687.             BSline = lines;
  688.             BEline = ep->Lines - 1;
  689.             Blocktype = BLOCK_LINE;
  690.             do_bmove();
  691.             Blocktype = oldbtype;
  692.  
  693.             if (bep && bep != ep)
  694.             {
  695.                 BSline = bsline;
  696.                 BEline = beline;
  697.                 bschar = BSchar;
  698.                 bechar = BEchar;
  699.                 BEp = bep;
  700.             }
  701.         }
  702.     }
  703.     set_window_params();
  704.     text_load();
  705.     text_redisplay();
  706. }
  707.  
  708.  
  709. /* Added by Karl Lukas 06/94 */
  710.  
  711. void do_reload(void)
  712. {
  713.    ED *ep = Ep;
  714.    char name[64];
  715.  
  716.    strcpy(name, ep->Name);  /* To avoid strcpy(ep->Name, ep->Name) in do_edit() */
  717.  
  718.    av[0] = (ubyte *)"n";
  719.    av[1] = (ubyte *)name;
  720.    do_edit();
  721. }
  722.  
  723.  
  724.  
  725. static char blockmode;
  726.  
  727. void do_appendsave(void)
  728. {
  729.     blockmode = 0;
  730.     saveit("a");
  731. }
  732.  
  733. void do_bappendsave(void)
  734. {
  735.     if (Blocktype == BLOCK_CHARACTER)
  736.     {
  737.        title("Change blocktype first");
  738.        return;
  739.     }
  740.     blockmode = 1;
  741.     saveit("a");
  742. }
  743.  
  744. void do_bsave(void)
  745. {
  746.     if (Blocktype == BLOCK_CHARACTER)
  747.     {
  748.        title("Change blocktype first");
  749.        return;
  750.     }
  751.     blockmode = 1;
  752.     do_saveas();
  753. }
  754.  
  755. void do_save(void)
  756. {
  757.     av[1] = Ep->Name;
  758.     do_saveas();
  759. }
  760.  
  761. void do_savetabs(void)
  762. {
  763.     Savetabs = (av[1][0] && av[1][1] == 'n') ? 1 : 0;
  764. }
  765.  
  766. void do_saveas(void)
  767. {
  768.     saveit("w");
  769. }
  770.  
  771. void saveit(const char *om)
  772. {
  773.     BPTR oldlock;
  774.     FILE *fi;
  775.     long i;
  776.     short j, k;
  777.     ubyte *ptr, *bp;
  778.     long xs, xe;
  779.     ubyte buf[256];
  780.     char bm;
  781.     ED *ep;
  782.  
  783.     bm = blockmode;
  784.     if (blockmode && blockok()) {
  785.         xs = BSline;
  786.         xe = BEline + 1;
  787.         ep = BEp;
  788.     } else {
  789.         xs = 0;
  790.         xe = Ep->Lines;
  791.         ep = Ep;
  792.     }
  793.     blockmode = 0;
  794.     text_sync();
  795.     oldlock = CurrentDir((BPTR)Ep->dirlock);
  796.     if (Wbs && Wdisable == 0) {     /* Write out .info file */
  797.         DISKOBJ sdo, *d;
  798.         clrmem(&sdo, sizeof(sdo));
  799.         if ((d = GetDiskObject(av[1])) == NULL) {
  800.             if (getpathto(Wbs->sm_ArgList[0].wa_Lock, Wbs->sm_ArgList[0].wa_Name, buf)) {
  801.                 sdo.do_Magic = WB_DISKMAGIC;
  802.                 sdo.do_Version = WB_DISKVERSION;
  803.                 makemygadget(&sdo.do_Gadget);
  804.                 sdo.do_Type = WBPROJECT;
  805.                 sdo.do_DefaultTool = (char *)buf;
  806.                 sdo.do_ToolTypes = NULL;
  807.                 sdo.do_CurrentX = NO_ICON_POSITION;
  808.                 sdo.do_CurrentY = NO_ICON_POSITION;
  809.                 sdo.do_DrawerData = NULL;
  810.                 sdo.do_ToolWindow = NULL;
  811.                 sdo.do_StackSize = 8192;
  812.                 PutDiskObject(av[1], &sdo);
  813.             }
  814.         } else {
  815.             FreeDiskObject(d);
  816.         }
  817.     }
  818.     if (fi = fopen(av[1], om)) {
  819.         setvbuf(fi, NULL, _IOFBF, 32768);  /* KL */
  820.         title("Saving...");
  821.         for (i = xs; i < xe; ++i) {
  822.             ptr = ep->List[i];
  823.             if (Savetabs) {
  824.                 for (bp = buf, j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
  825.                     *bp = *ptr;
  826.                     if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
  827.                         k = j;
  828.                         while (k-- >= 0 && *bp == ' ')
  829.                             --bp;
  830.                         *++bp = 9;
  831.                     } else {
  832.                         if (*bp < 32 || *bp == '\"' || *bp == '\'' || *bp == '\`' || *bp == '(')
  833.                             break;
  834.                     }
  835.                 }
  836.                 strcpy(bp, ptr);
  837.                 ptr = buf;
  838.             }
  839.             fputs(ptr, fi);
  840.             fputc('\n', fi);
  841.         }
  842.         if (fclose(fi)) {
  843. err:        Abortcommand = 1;
  844.             title("WRITE FAILED!");
  845.         } else {
  846.             ep->Modified &= bm;
  847.             title("OK");
  848.         }
  849.     } else {
  850.         title("Unable to open write file");
  851.         Abortcommand = 1;
  852.     }
  853.     CurrentDir(oldlock);
  854. }
  855.  
  856. void do_block(void)          /* block, unblock   */
  857. {
  858.     if ((Blocktype == BLOCK_CHARACTER) && (av[0][0] != 'u'))
  859.     {
  860.        title("Use BSTART/BSTOP for character blocks");
  861.        return;
  862.     }
  863.  
  864.     text_sync();
  865.  
  866.     switch(av[0][0]) {
  867.     case 'b':
  868.         if (BSline < 0) {
  869. bstart:
  870.             BEp = Ep;
  871.             BSline = Ep->Line;
  872.             title("Block Begin");
  873.         } else {
  874.             if (BEline > -1) {
  875.                 title("Block Already Marked");
  876.                 break;
  877.             }
  878.             if (BEp != Ep)
  879.                 goto bstart;
  880.             title("Block End");
  881.             BEline = Ep->Line;
  882.             if (BSline > BEline) {
  883.                 BEline = BSline;
  884.                 BSline = Ep->Line;
  885.             }
  886.             text_redrawblock(1);
  887.         }
  888.         break;
  889.     case 'u':
  890.         text_redrawblock(0);
  891.         title ("Block Unmarked");
  892.         break;
  893.     }
  894. }
  895.  
  896.  
  897. int blockok(void)
  898. {
  899.     if (BEp && BSline >= 0 && BSline <= BEline && BEline < BEp->Lines)
  900.         return(1);
  901.     BEp = NULL;
  902.     BSline = BEline = -1;
  903.     title("Block Not Specified");
  904.     return(0);
  905. }
  906.  
  907. void do_bdelete(void)
  908. {
  909.     long n;
  910.     ED *bep = BEp;
  911.     WIN *savewin = Ep->Win;
  912.  
  913.     if (Blocktype == BLOCK_CHARACTER)
  914.     {
  915.        title("Change blocktype first");
  916.        return;
  917.     }
  918.     if (blockok()) {
  919.         text_switch(bep->Win);
  920.         n = BEline - BSline + 1;
  921.         if (bep->Line >= BSline && bep->Line <= BEline)
  922.             bep->Line = BSline;
  923.         if (bep->Line > BEline)
  924.             bep->Line -= n;
  925.         freelist((char **)(bep->List + BSline), BEline - BSline + 1);
  926.         bmovl(bep->List+BEline+1,bep->List+BSline,(bep->Lines-BEline-1));
  927.         bep->Lines -= n;
  928.         bep->Modified = 1;
  929.         if (bep->Line >= bep->Lines)
  930.             bep->Line = bep->Lines - 1;
  931.         if (bep->Line < 0)
  932.             bep->Line = 0;
  933.         if (bep->Lines == 0) {
  934.             ++bep->Lines;
  935.             bep->List[0] = allocb(1);
  936.             bep->List[0][0] = 0;
  937.         }
  938.         text_load();
  939.         BEp = NULL;
  940.         BSline = BEline = -1;
  941.         if (!text_sync())
  942.             text_redisplay();
  943.         text_switch(savewin);
  944.     }
  945. }
  946.  
  947.  
  948. void do_bcopy(void)
  949. {
  950.     ubyte **list;
  951.     long lines, i;
  952.     ED *ep = Ep;
  953.  
  954.     if (Blocktype == BLOCK_CHARACTER)
  955.     {
  956.        title("Change blocktype first");
  957.        return;
  958.     }
  959.     text_sync();
  960.     if (!blockok())
  961.         return;
  962.     if (ep == BEp && ep->Line > BSline && ep->Line <= BEline) {
  963.         title("Cannot Move into self");
  964.         return;
  965.     }
  966.     lines = BEline - BSline + 1;
  967.     if (extend(ep, lines)) {
  968.         if (list = (ubyte **)allocl(lines)) {
  969.             bmovl(BEp->List+BSline,list,lines);
  970.             bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  971.             for (i = 0; i < lines; ++i) {
  972.                 ubyte *str = allocb(strlen(list[i])+1);
  973.                 if (!str) {
  974.                     nomemory();
  975.                     FreeMem(list, lines * sizeof(char *));
  976.                     freelist((char **)ep->List + Ep->Line, i);
  977.                     bmovl(ep->List+ep->Line+lines, ep->List+ep->Line, ep->Lines-ep->Line);
  978.                     return;
  979.                 }
  980.                 strcpy(str, list[i]);
  981.                 ep->List[ep->Line+i] = str;
  982.             }
  983.             FreeMem(list, lines * sizeof(char *));
  984.         }
  985.     }
  986.     if (ep == BEp && ep->Line <= BSline) {
  987.         BSline += lines;
  988.         BEline += lines;
  989.     }
  990.     ep->Modified = 1;
  991.     ep->Lines += lines;
  992.     text_load();
  993.     if (!text_sync())
  994.         text_redisplay();
  995. }
  996.  
  997.  
  998. void do_bmove(void)
  999. {
  1000.     long lines;
  1001.     ubyte **list;
  1002.     ED *ep = Ep;
  1003.  
  1004.     if (Blocktype == BLOCK_CHARACTER)
  1005.     {
  1006.        title("Change blocktype first");
  1007.        return;
  1008.     }
  1009.     text_sync();
  1010.     if (!blockok())
  1011.         return;
  1012.     if (BEp == ep && ep->Line >= BSline && ep->Line <= BEline) {
  1013.         title("Cannot Move into self");
  1014.         return;
  1015.     }
  1016.     lines = BEline - BSline + 1;
  1017.     if (!(list = (ubyte **)allocl(lines))) {
  1018.         nomemory();
  1019.         return;
  1020.     }
  1021.     BEp->Modified = ep->Modified = 1;
  1022.     bmovl(BEp->List + BSline, list, lines);
  1023.     if (ep == BEp) {
  1024.         if (ep->Line > BSline) {
  1025.             bmovl(ep->List+BEline+1, ep->List+BSline, ep->Line-BEline-1);
  1026.             bmovl(list, ep->List + ep->Line - lines, lines);
  1027.         } else {
  1028.             bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, BSline-ep->Line);
  1029.             bmovl(list, ep->List + ep->Line, lines);
  1030.         }
  1031.     } else {
  1032.         WIN *savewin = ep->Win;
  1033.         if (extend(ep, lines)) {
  1034.             bmovl(BEp->List+BEline+1, BEp->List+BSline, BEp->Lines-BEline-1);
  1035.             bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  1036.             bmovl(list, ep->List+ep->Line, lines);
  1037.             ep->Lines += lines;
  1038.             BEp->Lines -= lines;
  1039.             if (BEp->Line >= BSline && BEp->Line <= BEline)
  1040.                 BEp->Line = BSline - 1;
  1041.             if (BEp->Line > BEline)
  1042.                 BEp->Line -= lines;
  1043.             if (BEp->Line < 0)
  1044.                 BEp->Line = 0;
  1045.             BSline = BEline = -1;
  1046.             if (BEp->Lines == 0) {
  1047.                 ubyte *ptr = allocb(1);
  1048.                 BEp->List[0] = ptr;
  1049.                 *ptr = 0;
  1050.                 ++BEp->Lines;
  1051.             }
  1052.             text_load();
  1053.             text_switch(BEp->Win);
  1054.             BEp = NULL;
  1055.             ep = Ep;
  1056.             if (!ep->iconmode) {
  1057.                 if (!text_sync())
  1058.                     text_redisplay();
  1059.             }
  1060.             text_switch(savewin);
  1061.             ep = Ep;
  1062.         }
  1063.     }
  1064.     BSline = BEline = -1;
  1065.     BEp = NULL;
  1066.     FreeMem(list, lines * sizeof(char *));
  1067.     ep->Modified = 1;
  1068.     text_load();
  1069.     if (!text_sync())
  1070.         text_redisplay();
  1071. }
  1072.  
  1073.  
  1074. /*
  1075.  * IF condition trueaction, IFELSE condition trueaction falseaction
  1076.  *
  1077.  *  condition:  !condition NOT the specified condition.
  1078.  *              #          toggle number is SET
  1079.  *              top        top of file (on first line)
  1080.  *              bot        end of file (on last line)
  1081.  *              left       start of line (leftmost column)
  1082.  *              right      end of line (nothing but spaces under and to the right)
  1083.  *              modified   text has been modified
  1084.  *              insert     currently in insert mode
  1085.  *              y[<=>]#    cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  1086.  *              x[<=>]#    cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  1087.  *                          <> means 'not equal'
  1088.  *
  1089.  *              cl         char under cursor is lower case
  1090.  *              cu         char under cursor is upper case
  1091.  *              ca         char under cursor is alpha
  1092.  *              cn         char under cursor is numeric
  1093.  *              cb         char within selected block
  1094.  *              c[<=>]#    char under cursor is (combo of <,>,and =) #
  1095.  */
  1096.  
  1097. void do_if(void)
  1098. {
  1099.     char haselse = (av[0][2] == 'e');
  1100.     char iswhile = (av[0][0] == 'w');
  1101.     char istrue, notop = 0;
  1102.     char c, cx, cc;
  1103.     ubyte *buf1, *buf2;
  1104.     ubyte *ptr;
  1105.     ED *ep = Ep;
  1106.     int i, cxn, cn;
  1107.  
  1108.     buf1 = (ubyte *)malloc(256);
  1109.     buf2 = (ubyte *)malloc(256);
  1110.     if (buf1 == NULL || buf2 == NULL) {
  1111.         if (buf1) free(buf1);
  1112.         if (buf2) free(buf2);
  1113.         title("No Memory!");
  1114.         return;
  1115.     }
  1116.     breakreset();
  1117.     ptr = av[1];
  1118.     if (*ptr == '!') {
  1119.         notop = 1;
  1120.         ++ptr;
  1121.     }
  1122.     c = ptr[0];
  1123.     cn= atoi(ptr);
  1124.     cx= ptr[1];
  1125.     cxn=atoi(ptr+1);
  1126.     strcpy(buf1, av[2]);
  1127.  
  1128. loop:
  1129.     istrue = 0;
  1130.     i = 0;
  1131.     switch(c) {
  1132.     case 'x':
  1133.         i = ep->Column + 1;
  1134.     case 'y':
  1135.         if (!i)
  1136.             i = ep->Line + 1;
  1137. conditional:
  1138.         {
  1139.             int j, n;
  1140.             char any = 0;
  1141.  
  1142.             for (j = 1; ptr[j] && !isdigit(ptr[j]); ++j);
  1143.             n = atoi(ptr+j);
  1144.             for (j = 1; ptr[j]; ++j) {
  1145.                 switch(ptr[j]) {
  1146.                 case '<':
  1147.                     any = 1;
  1148.                     if (i < n)
  1149.                         istrue = 1;
  1150.                     break;
  1151.                 case '=':
  1152.                     any = 1;
  1153.                     if (i == n)
  1154.                         istrue = 1;
  1155.                     break;
  1156.                 case '>':
  1157.                     any = 1;
  1158.                     if (i > n)
  1159.                         istrue = 1;
  1160.                     break;
  1161.                 }
  1162.             }
  1163.             if (!any && i == n)  /* default is equivalence   */
  1164.                 istrue = 1;
  1165.         }
  1166.         break;
  1167.     case 't':
  1168.         istrue = ep->Line == 0;
  1169.         break;
  1170.     case 'b':
  1171.         istrue = ep->Line == ep->Lines-1;
  1172.         break;
  1173.     case 'l':
  1174.         istrue = ep->Column == 0;
  1175.         break;
  1176.     case 'r':
  1177.         istrue = ep->Column == Clen;
  1178.         break;
  1179.     case 'm':
  1180.         text_sync();
  1181.         istrue = ep->Modified != 0;
  1182.         break;
  1183.     case 'e':
  1184.         istrue = Comlinemode != 0;
  1185.         break;
  1186.     case 'i':
  1187.         istrue = ep->Insertmode != 0;
  1188.         break;
  1189.     case 'c':
  1190.         cc = Current[ep->Column];
  1191.         switch(cx) {
  1192.         case 'b':
  1193.             istrue = BEp == ep && ep->Line >= BSline && ep->Line <= BEline;
  1194.             break;
  1195.         case 'l':
  1196.             istrue = islower(cc);
  1197.             break;
  1198.         case 'u':
  1199.             istrue = isupper(cc);
  1200.             break;
  1201.         case 'a':
  1202.             istrue = isalnum(cc);
  1203.             break;
  1204.         case 'n':
  1205.             istrue = isdigit(cc);
  1206.             break;
  1207.         default:                /* c[<=>]#  */
  1208.             i = Current[ep->Column];
  1209.             goto conditional;
  1210.             break;
  1211.         }
  1212.         break;
  1213.     default:
  1214.         if (isdigit(c))
  1215.             istrue = do_toggle(cn) != 0;
  1216.         else
  1217.             title("bad conditional");
  1218.         break;
  1219.     }
  1220.     istrue ^= notop;
  1221.     if (istrue) {
  1222.         strcpy(buf2, buf1);     /* could be executed multiple times */
  1223.         if (do_command(buf2) == 0)
  1224.             goto done;
  1225.         if (iswhile) {
  1226.             if (breakcheck())
  1227.                 Abortcommand = 1;
  1228.             else
  1229.                 goto loop;
  1230.         }
  1231.     } else {
  1232.         if (haselse) {          /* only executed once */
  1233.             strcpy(buf2, av[3]);
  1234.             do_command(buf2);
  1235.         }
  1236.     }
  1237. done:
  1238.     free(buf1);
  1239.     free(buf2);
  1240. }
  1241.  
  1242.  
  1243. /*
  1244.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  1245.  */
  1246.  
  1247. int do_toggle(int n)
  1248. {
  1249.     static char tg[MAXTOGGLE];
  1250.     int i;
  1251.  
  1252.     if (n >= 0) {
  1253.         if (n >= MAXTOGGLE)
  1254.             return(0);
  1255.         return((int)tg[n]);
  1256.     }
  1257.     i = atoi(av[1]);
  1258.     if (i >= 0 && i < MAXTOGGLE) {
  1259.         switch(av[0][0]) {
  1260.         case 't':
  1261.             tg[i] = !tg[i];
  1262.             break;
  1263.         case 's':
  1264.             tg[i] = 1;
  1265.             break;
  1266.         case 'r':
  1267.             tg[i] = 0;
  1268.             break;
  1269.         }
  1270.     }
  1271. }
  1272.  
  1273.  
  1274. void do_tlate(void)
  1275. {
  1276.     ubyte *ptr = av[1];
  1277.     ED *ep = Ep;
  1278.     char c = Current[ep->Column];
  1279.  
  1280.     if (c == 0)
  1281.         c = ' ';
  1282.     if (ptr[0] == '+')
  1283.         c += atoi(ptr+1);
  1284.     else
  1285.     if (ptr[0] == '-')
  1286.         c -= atoi(ptr+1);
  1287.     else
  1288.         c = atoi(ptr);
  1289.     if (c) {
  1290.         if (Current[ep->Column] == 0) {
  1291.             Clen = ep->Column + 1;
  1292.             Current[Clen] = 0;
  1293.         }
  1294.         Current[ep->Column] = c;
  1295.         if (Nsu == 0) {
  1296.             movetocursor();
  1297.             setpen(ep->Line, ep->Column);
  1298.             Text(ep->Win->RPort, Current+ep->Column, 1);
  1299.         }
  1300.     }
  1301. }
  1302.  
  1303. /*
  1304.  *  BSOURCE
  1305.  *
  1306.  *  note that since the start and end lines are loaded immediately and the
  1307.  *  block unblock'd before execution starts, you can theoretically have
  1308.  *  another BSOURCE as part of this BSOURCE (but be carefull!).
  1309.  */
  1310.  
  1311. void do_bsource(void)
  1312. {
  1313.     ubyte buf[256];
  1314.     int i, sl, se;
  1315.  
  1316.     if (Blocktype == BLOCK_CHARACTER)
  1317.     {
  1318.        title("Change blocktype first");
  1319.        return;
  1320.     }
  1321.     if (blockok()) {
  1322.         sl = BSline;
  1323.         se = BEline + 1;
  1324.         for (i = sl; BEp && i < se && i < BEp->Lines; ++i) {
  1325.             text_sync();        /* make sure we are using latest text */
  1326.             strcpy(buf, BEp->List[i]);
  1327.             if (buf[0] != '#' && do_command(buf) == 0)
  1328.                 break;
  1329.         }
  1330.         text_redrawblock(0);
  1331.     }
  1332. }
  1333.  
  1334. /*
  1335.  *  SCANF controlstring
  1336.  *
  1337.  *  The C scanf routine.  Only one variable, a string, is allowed in the
  1338.  *  control string.
  1339.  */
  1340.  
  1341. void do_scanf(void)
  1342. {
  1343.     char buf[256];
  1344.  
  1345.     buf[0] = 0;
  1346.     sscanf(Current+Ep->Column,av[1],buf,buf,buf,buf,buf,buf,buf);
  1347.     if (String)
  1348.         free(String);
  1349.     String = (char *)malloc(strlen(buf)+1);
  1350.     strcpy(String,buf);
  1351.     title(String);
  1352. }
  1353.  
  1354. void movetocursor(void)
  1355. {
  1356.     ED *ep = Ep;
  1357.     Move(ep->Win->RPort, XTbase+(ep->Column-ep->Topcolumn)*Xsize, YTbase+(ep->Line-ep->Topline)*Ysize);
  1358. }
  1359.  
  1360. int extend(ED *ep, int lines)
  1361. {
  1362.     long extra = ep->Maxlines - ep->Lines;
  1363.     ubyte **list;
  1364.  
  1365.     if (lines > extra) {
  1366.         lines += ep->Lines;
  1367.         if (list = (ubyte **)allocl(lines)) {
  1368.             bmovl(ep->List, list, ep->Lines);
  1369.             FreeMem(ep->List, sizeof(char *) * ep->Maxlines);
  1370.             ep->Maxlines = lines;
  1371.             ep->List = list;
  1372.             return(1);
  1373.         }
  1374.         nomemory();
  1375.         return(0);
  1376.     }
  1377.     return(1);
  1378. }
  1379.  
  1380. int makeroom(int n)
  1381. {
  1382.     ED *ep = Ep;
  1383.     if (ep->Lines >= ep->Maxlines)
  1384.         return(extend(ep, n));
  1385.     return(1);
  1386. }
  1387.  
  1388. void freelist(char **list, int n)
  1389. {
  1390.     int window = 0, number = n;
  1391.  
  1392.     if (n > 2000)
  1393.        window = OpenProgressWindow("Freeing memory");
  1394.  
  1395.     while (n) {
  1396.         if (window)
  1397.            UpdateProgressWindow((number - n), number, 4);
  1398.         FreeMem(list[0], strlen(list[0])+1);
  1399.         ++list;
  1400.         --n;
  1401.     }
  1402.    if (window)
  1403.       CloseProgressWindow();
  1404.    if (FlushMem)
  1405.       Execute("C:Flush >NIL:", NULL, NULL);
  1406. }
  1407.  
  1408. void do_noflushmem(void)
  1409. {
  1410.    FlushMem = 0;
  1411.    title("Flush turned off");
  1412. }
  1413.  
  1414. void do_blocktype(void)
  1415. {
  1416.    char buf[256];
  1417.  
  1418.    switch (av[1][0])
  1419.    {
  1420.       case 'l' :
  1421.       case 'L' :
  1422.          Blocktype = BLOCK_LINE;
  1423.          text_redrawblock(0);
  1424.          title("Blocktype line");
  1425.          break;
  1426.       case 'c' :
  1427.       case 'C' :
  1428.          Blocktype = BLOCK_CHARACTER;
  1429.          text_redrawblock(0);
  1430.          title("Blocktype character");
  1431.          break;
  1432.       case 'v' :
  1433.       case 'V' :
  1434.          Blocktype = BLOCK_VERTICAL;
  1435.          text_redrawblock(0);
  1436.          title("Blocktype vertical");
  1437.          break;
  1438.       default:
  1439.          sprintf(buf, "Illegal blocktype: %s", av[1]);
  1440.          title(buf);
  1441.          break;
  1442.    }
  1443. }
  1444.  
  1445.  
  1446. void do_bstart(void)
  1447. {
  1448.  
  1449.  
  1450.    ED *ep = Ep;
  1451.  
  1452.    Blockempty = 0;
  1453.  
  1454.    Marking = 1;
  1455.    text_sync();
  1456.    switch (Blocktype)
  1457.    {
  1458.       case BLOCK_LINE:
  1459.          BEp = ep;
  1460.          BSline = ep->Line;
  1461.          if ((BSline > BEline) && (BEline >= 0))
  1462.          {
  1463.             long tmp = BSline; BSline = BEline; BEline = tmp;
  1464.          }
  1465.          if ((BSline >= 0) && (BEline >= 0))  /* There is a valid block */
  1466.             text_redrawblock(1);
  1467.          title("line block start");
  1468.          BSchar = BEchar = -1;
  1469.          break;
  1470.       case BLOCK_CHARACTER:
  1471.          BEp = ep;
  1472.          BSline = initialBSline = ep->Line;
  1473.          BSchar = initialBSchar = ep->Column;
  1474.          if ((BSline == BEline) && (BSchar == BEchar))
  1475.          {
  1476.             Blockempty = 1;
  1477.             /* Empty blocks are now allowed */
  1478.          }
  1479.          else if ((BSline > BEline) && (BEline >= 0))
  1480.          {
  1481.             short tp;
  1482.             long tmp = BSline; BSline = BEline; BEline = tmp;
  1483.             tp = BSchar; BSchar = BEchar; BEchar = tp;
  1484.          }
  1485.          else if ((BSline == BEline) && (BSchar > BEchar))
  1486.          {
  1487.             short tp = BSchar; BSchar = BEchar; BEchar = tp;
  1488.          }
  1489.          if ((BSline >= 0) && (BEline >= 0))  /* There is a valid block */
  1490.             text_redrawblock(1);
  1491.  
  1492.  
  1493.          title("character block start");
  1494.          break;
  1495.       case BLOCK_VERTICAL:
  1496.          title("Not implemented yet");
  1497.          break;
  1498.    }
  1499. }
  1500.  
  1501. void do_bend(void)
  1502. {
  1503.    ED *ep = Ep;
  1504.  
  1505.    if (BEp == ep)
  1506.    {
  1507.       text_sync();
  1508.       Blockempty = 0;
  1509.       Marking = 0;
  1510.       switch (Blocktype)
  1511.       {
  1512.          case BLOCK_LINE:
  1513.             if (BSline >= 0)
  1514.             {
  1515.                BEline = ep->Line;
  1516.                if (BSline > BEline)
  1517.                {
  1518.                   long tmp = BSline; BSline = BEline; BEline = tmp;
  1519.                }
  1520.                /* There is a valid block */
  1521.                text_redrawblock(1);
  1522.                title("block end");
  1523.                BSchar = BEchar = -1;
  1524.             }
  1525.             else
  1526.                title("Got to start block first");
  1527.             break;
  1528.          case BLOCK_CHARACTER:
  1529.             if (BSline >= 0)
  1530.             {
  1531.                BEline = ep->Line;
  1532.                BEchar = ep->Column;
  1533.                if ((BEline > initialBSline) || ((BEline == initialBSline) && (BEchar > initialBSchar)))
  1534.                {
  1535.                   BSline = initialBSline; BSchar = initialBSchar;
  1536.                }
  1537.                if ((BSline == BEline) && (BSchar == BEchar))
  1538.                {
  1539.                   Blockempty = 1;
  1540.                   /* Empty blocks are now allowed */
  1541.                }
  1542.                else if ((BSline > BEline) && (BEline >= 0)) /* bend before bstart position */
  1543.                {
  1544.                   short tp;
  1545.                   long tmp = BSline; BSline = BEline; BEline = tmp;
  1546.                   tp = BSchar; BSchar = BEchar; BEchar = tp;
  1547.                }
  1548.                else if ((BSline == BEline) && (BSchar > BEchar)) /* bend before bstart position */
  1549.                {
  1550.                   short tp = BSchar; BSchar = BEchar; BEchar = tp;
  1551.                }
  1552.                else /* bend after bstart position  at least one byte */
  1553.                {
  1554.                   if (--BEchar < 0)
  1555.                   {
  1556.                      BEline--; /* This might result in an empty block, which is legal now */
  1557.                      BEchar = strlen((char *)ep->List[BEline]);
  1558.                   }
  1559.                }
  1560.  
  1561.                if ((BEline < initialBSline) || ((BEline == initialBSline) && (BEchar < initialBSchar)))
  1562.                {
  1563.                   BEline = initialBSline; BEchar = initialBSchar;
  1564.                }
  1565.  
  1566.                if ((BSline >= 0) && (BEline >= 0))  /* There is a valid block */
  1567.                   text_redrawblock(1);
  1568.  
  1569.                title("character block end");
  1570.             }
  1571.             else
  1572.                title("Got to start block first");
  1573.  
  1574.  
  1575.             break;
  1576.          case BLOCK_VERTICAL:
  1577.             title("Not implemented yet");
  1578.             break;
  1579.       }
  1580.    }
  1581.    else
  1582.    {
  1583.       text_redrawblock(0);
  1584.       title("Got to start block first");;
  1585.    }
  1586. }
  1587.  
  1588.  
  1589. /* This only works if CountLineFeeds() was called on clipbuf */
  1590. /* clipbuf->mem may not contain anymore linefeeds            */
  1591.  
  1592. int GetNextLine(cbbuf *clipbuf, char *dest, int *index, int maxlen)
  1593. {
  1594.    char ebuf[256];
  1595.  
  1596.    int i = 0, num = clipbuf->count;
  1597.    char *source = clipbuf->mem + *index;
  1598.  
  1599.    if ((*index) >= num)
  1600.       return (-1);
  1601.  
  1602.    while (((*index + i) < num) && (source[i]))
  1603.       i++;
  1604.  
  1605.    *index = *index + i + 1;
  1606.  
  1607.    if (source[i] == '\n')
  1608.       source[i] = 0;
  1609.  
  1610.    return detab(source, dest, maxlen);
  1611. }
  1612.  
  1613.  
  1614. /* 1.9.94 Einige kleine Verbesserungen angebracht:
  1615.  *        do_paste hat irrtuemlich eine Leerzeile im Text geloescht,
  1616.  *        wenn diese unmittelbar nach dem gepasteten Text kam.
  1617.  *        Der Cursor wird nun auf die erste Poisition nach dem
  1618.  *        gepasteten Text gesetzt.
  1619.  *        Die Veraenderungen sind mit <-- gekennzeichnet
  1620.  */
  1621.  
  1622. void do_paste(void)
  1623. {
  1624.    ED *ep = Ep;
  1625.    struct IOClipReq *ior;
  1626.    struct cbbuf *clipbuf;
  1627.    int index = 0;
  1628.    int lines, len, i;
  1629.    char buf[256];
  1630.    char endbuf[256];
  1631.    char *str;
  1632.    int window = 0;
  1633.    int newcol = 0;
  1634.  
  1635.    text_sync();
  1636.    if (ior = CBOpen(0))
  1637.    {
  1638.       if (CBQueryFTXT(ior))
  1639.       {
  1640.          if (clipbuf = CBReadCHRS(ior))
  1641.          {
  1642.             ep->Modified = 1;
  1643.             if (BEp && ep->Line >= BSline && ep->Line <= BEline)
  1644.             {
  1645.                text_redrawblock(0);
  1646.             }
  1647.             lines = CountLineFeeds(clipbuf);
  1648.             if (lines > 1500)
  1649.                window = OpenProgressWindow("Pasting");
  1650.  
  1651.             if (lines && BEp && ep->Line < BSline)
  1652.             {
  1653.                BSline += lines;
  1654.                BEline += lines;
  1655.             }
  1656.             len = GetNextLine(clipbuf, buf, &index, 256);
  1657.             if (lines)
  1658.             {
  1659.                if ((lines > 1) && (ep->Column == strlen(Current)) &&
  1660.                    (ep->Column > 0) &&  /* <-- */
  1661.                    (clipbuf->mem[clipbuf->count - 1] == 0))
  1662.                   lines--;
  1663.  
  1664.                str = (char *)allocb(ep->Column + 2 + len);
  1665.                strcpy(endbuf, ep->List[ep->Line] + ep->Column);
  1666.             }
  1667.             else
  1668.             {
  1669.                str = (char *)allocb(strlen(Current) + len + 1);
  1670.                newcol = ep->Column + len;
  1671.             }
  1672.             if (str)
  1673.             {
  1674.                if (lines)
  1675.                {
  1676.                   strncpy(str, Current, ep->Column);
  1677.                   strcpy(str + ep->Column, buf);
  1678.                }
  1679.                else
  1680.                {
  1681.                   strcpy(str, Current);
  1682.                   strins(str + ep->Column, buf);
  1683.                }
  1684.                FreeMem(ep->List[ep->Line], strlen(ep->List[ep->Line])+1);
  1685.                if (strlen(str) > 255)
  1686.                {
  1687.                   strncpy(buf, str, 255);
  1688.                   buf[255] = 0;
  1689.                   FreeMem(str, strlen(str));
  1690.                   str = (char *)allocb(256);
  1691.                   strncpy(str, buf, 256);
  1692.                   title("Line truncated");
  1693.                }
  1694.                ep->List[ep->Line] = str;
  1695.                if (lines)
  1696.                {
  1697.                   extend(ep, lines);
  1698.                   bmovl(ep->List + ep->Line + 1, ep->List + ep->Line + lines + 1,
  1699.                         ep->Lines - ep->Line - 1);
  1700.                   ep->Lines += lines;
  1701.                   ep->Modified = 1;
  1702.  
  1703.                   for (i = 1; i < lines; i++)
  1704.                   {
  1705.                      len = GetNextLine(clipbuf, buf, &index, 256);
  1706.                      str = (char *)allocb(strlen(buf) + 1);
  1707.                      if (str)
  1708.                      {
  1709.                         strcpy(str, buf);
  1710.                         ep->List[ep->Line + i] = str;
  1711.                      }
  1712.                      else
  1713.                      {
  1714.                         nomemory();
  1715.                         break;
  1716.                      }
  1717.                      if (window)
  1718.                         UpdateProgressWindow(i, lines, 4);
  1719.                   }
  1720.                   len = GetNextLine(clipbuf, buf, &index, 256);
  1721.                   str = (char *)allocb(strlen(buf) + strlen(endbuf) + 1);
  1722.                   if (str)
  1723.                   {
  1724.                      if (len >= 0)
  1725.                         newcol = strlen(buf);
  1726.                      if (len >= 0)
  1727.                         strcpy(str, buf);
  1728.                      else
  1729.                         buf[0] = 0;
  1730.                      strcat(str, endbuf);
  1731.                      if (strlen(str) > 255)
  1732.                      {
  1733.                         strncpy(buf, str, 255);
  1734.                         buf[255] = 0;
  1735.                         FreeMem(str, strlen(str));
  1736.                         str = (char *)allocb(256);
  1737.                         strncpy(str, buf, 256);
  1738.                         title("Line truncated");
  1739.                      }
  1740.                      ep->List[ep->Line + lines] = str;
  1741.                   }
  1742.                   else
  1743.                      nomemory();
  1744.                   text_load();
  1745.                   text_displayseg(ep->Line - ep->Topline, Rows - (ep->Line - ep->Topline));
  1746.  
  1747.                   ep->Line += lines;
  1748.                   ep->Column = newcol;
  1749.  
  1750.                   text_load();
  1751.                   text_sync();
  1752.                }
  1753.                else
  1754.                {
  1755.                   ep->Column = newcol;
  1756.                   text_load();
  1757.                   text_displayseg(ep->Line - ep->Topline, 1);
  1758.                }
  1759.             }
  1760.             else
  1761.                nomemory();
  1762.  
  1763.             CBFreeBuf(clipbuf);
  1764.          }
  1765.          else
  1766.             title("Cannot read clipboard");
  1767.          CBReadDone(ior);
  1768.       }
  1769.       else
  1770.          title("Clipboard is empty");
  1771.       CBClose(ior);
  1772.    }
  1773.    else
  1774.       title("ERROR: Can't open clipboard device");
  1775.    if (window)
  1776.       CloseProgressWindow();
  1777. }
  1778.  
  1779. /* Counts linefeeds in clipbuf and sets them to zero */
  1780. int CountLineFeeds(struct cbbuf *clipbuf)
  1781. {
  1782.    int i;
  1783.    int count = 0;
  1784.    char *buf = clipbuf->mem;
  1785.  
  1786.    for (i = 0; i < clipbuf->count; i++)
  1787.       if (*buf++ == '\n')
  1788.       {
  1789.          *(buf - 1) = 0;
  1790.          count++;
  1791.       }
  1792.  
  1793.    return count;
  1794. }
  1795.  
  1796. void do_copy(void)
  1797. {
  1798.    ED *ep = BEp;
  1799.    struct IOClipReq *ior;
  1800.    char *str;
  1801.    int buflen;
  1802.  
  1803.    if (blockok() && ! Blockempty)
  1804.    {
  1805.       text_sync();
  1806.       if (str = block_to_str(&buflen))
  1807.       {
  1808.          if (ior = CBOpen(0L))
  1809.          {
  1810.             if (! CBWriteFTXT(ior, str))
  1811.                title("Can't write to clipboard");
  1812.             else
  1813.             {
  1814.                text_redrawblock(0);
  1815.                title("Block copied to clip");
  1816.             }
  1817.             CBClose(ior);
  1818.          }
  1819.          else
  1820.             title("Can't open clipboard");
  1821.          FreeMem(str, buflen);
  1822.       }
  1823.       else
  1824.          title("No memory - Cannot copy block");
  1825.    }
  1826.    else
  1827.       title("Gotta mark a block first");
  1828. }
  1829.  
  1830.  
  1831. /* Watch out: There MUST be a valid block for this */
  1832.  
  1833. char *block_to_str(int *buflen)
  1834. {
  1835.    ED *ep = BEp;
  1836.    int lines, i, count = 2;
  1837.    char *str, *ptr;
  1838.  
  1839.    if (Blocktype != BLOCK_LINE && Blocktype != BLOCK_CHARACTER)
  1840.       return 0;
  1841.  
  1842.    lines = BEline - BSline + 1;
  1843.  
  1844.  
  1845.    for (i = 0; i < lines; i++)
  1846.       count += (strlen(ep->List[BSline + i]) + 1);
  1847.  
  1848.    *buflen = count;
  1849.    str = (char *)allocb(count);
  1850.    if (str)
  1851.    {
  1852.       ptr = str;
  1853.       if (Blocktype == BLOCK_CHARACTER)
  1854.       {
  1855.          if (lines == 1)
  1856.          {
  1857.             strncpy(ptr, ep->List[BSline] + BSchar, BEchar - BSchar + 1);
  1858.             *(ptr + (BEchar - BSchar + 1)) = 0;
  1859.          }
  1860.          else
  1861.             strcpy(ptr, ep->List[BSline] + BSchar);
  1862.       }
  1863.       else
  1864.          strcpy(ptr, ep->List[BSline]);
  1865.       ptr += strlen(ptr);
  1866.       *ptr++ = '\n';
  1867.       if (lines > 1)
  1868.       {
  1869.          for (i = 1; i < lines; i++)
  1870.          {
  1871.             strcpy(ptr, ep->List[BSline + i]);
  1872.             ptr += strlen(ptr);
  1873.             *ptr++ = '\n';
  1874.          }
  1875.          if (Blocktype == BLOCK_CHARACTER)
  1876.          {
  1877.             i = strlen(ep->List[BEline]);
  1878.             if (i > BEchar)
  1879.             {
  1880.               ptr -= (i - BEchar);
  1881.               *ptr++ = '\n';
  1882.             }
  1883.          }
  1884.       }
  1885.       if (Blocktype == BLOCK_CHARACTER && BEchar < strlen(ep->List[BEline]))
  1886.       {
  1887.          *(--ptr) = 0;
  1888.       }
  1889.       else
  1890.          *ptr = 0;
  1891.    }
  1892.    return str;
  1893. }
  1894.  
  1895.  
  1896. /***********************************************************************************************/
  1897.  
  1898. struct Window *ProgressWnd = NULL;
  1899. struct Screen         *Scr = NULL;
  1900. APTR            VisualInfo = NULL;
  1901. UWORD offx, offy;
  1902.  
  1903. void do_progresswnd(void)
  1904. {
  1905.    ProgressWindow = atoi(av[1]);
  1906. }
  1907.  
  1908. void ProgressRender(void)
  1909. {
  1910.     offx = ProgressWnd->BorderLeft;
  1911.     offy = ProgressWnd->BorderTop;
  1912.  
  1913.  
  1914.     DrawBevelBox( ProgressWnd->RPort, offx + 9, offy + 4, 204, 15, GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE );
  1915.     DrawBevelBox( ProgressWnd->RPort, offx + 10, offy + 5, 202, 13, GT_VisualInfo, VisualInfo, TAG_DONE );
  1916. }
  1917.  
  1918. int OpenProgressWindow(char *title)
  1919. {
  1920.     UWORD offx, offy;
  1921.  
  1922.     if (! GadToolsBase)
  1923.        return 0;
  1924.     if (! ProgressWindow)
  1925.        return 0;
  1926.     if ( ! ( Scr = LockPubScreen((UBYTE * )"Workbench" )))
  1927.        return 0;
  1928.     if ( ! ( VisualInfo = GetVisualInfo( Scr, TAG_DONE )))
  1929.         return 0;
  1930.     offx = Scr->WBorLeft,offy = Scr->WBorTop + Scr->RastPort.TxHeight + 1;
  1931.  
  1932.     if ( ! ( ProgressWnd = OpenWindowTags( NULL,
  1933.                     WA_Left,          Ep->Win->LeftEdge + (Ep->Winwidth / 2) - 115,
  1934.                     WA_Top,           Ep->Win->TopEdge + (Ep->Winheight / 3) - 16,
  1935.                     WA_Width,         230,
  1936.                     WA_Height,        26 + offy,
  1937.                     WA_IDCMP,         0,
  1938.                     WA_Flags,         WFLG_DRAGBAR|WFLG_SMART_REFRESH,
  1939.                     WA_Title,         title,
  1940.                     WA_PubScreen,     Scr,
  1941.                     TAG_DONE )))
  1942.         return 0;
  1943.  
  1944.     ProgressRender();
  1945.     SetAPen(ProgressWnd->RPort, 3);
  1946.  
  1947.     return 1;
  1948. }
  1949.  
  1950. void CloseProgressWindow( void )
  1951. {
  1952.     if ( ProgressWnd        ) {
  1953.         CloseWindow( ProgressWnd );
  1954.         ProgressWnd = NULL;
  1955.     }
  1956.     if ( VisualInfo ) {
  1957.         FreeVisualInfo( VisualInfo );
  1958.         VisualInfo = NULL;
  1959.     }
  1960.     if ( Scr        ) {
  1961.         UnlockPubScreen( NULL, Scr );
  1962.         Scr = NULL;
  1963.     }
  1964. }
  1965.  
  1966. void UpdateProgressWindow(int done, int total, int step)
  1967. {
  1968.    int percent = 100 * done / total;
  1969.  
  1970.    if (step <= 0) step = 1; /* avoid division by 0 */
  1971.  
  1972.    if ((percent % step == 0) && ProgressWnd && percent >= 0 && percent <=100)
  1973.    {
  1974.       RectFill(ProgressWnd->RPort, offx + 11,
  1975.                                    offy + 6, offx + 11 + percent * 2, offy + 16);
  1976.    }
  1977. }
  1978.  
  1979. /***********************************************************************************/
  1980.  
  1981. void do_cut(void)
  1982. {
  1983.    ED *ep = BEp;
  1984.    char *str;
  1985.    char buf[256];
  1986.    WIN *savewin = Ep->Win;
  1987.    int start, stop, lines;
  1988.    int bsc = BSchar;
  1989.    int bsl = BSline;
  1990.    int bec = BEchar;
  1991.    int bel = BEline;
  1992.  
  1993.    char join1 = 0, join2 = 0;
  1994.  
  1995.    if (blockok() && ! Blockempty)
  1996.    {
  1997.       ep->Modified = 1;
  1998.       if (Blocktype == BLOCK_CHARACTER)
  1999.       {
  2000.          text_sync();
  2001.          text_switch(ep->Win);
  2002.          text_sync();
  2003.          do_copy();
  2004.  
  2005.          BSchar = bsc; BSline = bsl; BEchar = bec; BEline = bel;
  2006.          BEp = ep;
  2007.  
  2008.          if (kill_first_line())
  2009.             start = BSline;
  2010.          else
  2011.          {
  2012.             join1 = 1;
  2013.  
  2014.             start = BSline + 1;
  2015.  
  2016.             if (BSchar > 0)
  2017.                strncpy(buf, ep->List[BSline], BSchar);
  2018.             if (BEline == BSline)
  2019.                strcpy(buf + BSchar, ep->List[BSline] + BEchar + 1);
  2020.             else
  2021.                buf[BSchar] = 0;
  2022.             str = (char *)allocb(strlen(buf) + 1);
  2023.             if (str)
  2024.             {
  2025.                strcpy(str, buf);
  2026.                FreeMem(ep->List[BSline], strlen(ep->List[BSline]) + 1);
  2027.                ep->List[BSline] = str;
  2028.             }
  2029.             else
  2030.                nomemory();
  2031.          }
  2032.          if (kill_last_line())
  2033.          {
  2034.             stop = BEline;
  2035.          }
  2036.          else
  2037.          {
  2038.             stop = BEline - 1;
  2039.  
  2040.             if (BEline != BSline)
  2041.             {
  2042.                join2 = 1;
  2043.  
  2044.                strcpy(buf, ep->List[BEline] + BEchar + 1);
  2045.                str = (char *)allocb(strlen(buf) + 1);
  2046.                if (str)
  2047.                {
  2048.                   strcpy(str, buf);
  2049.                   FreeMem(ep->List[BEline], strlen(ep->List[BEline]) + 1);
  2050.                   ep->List[BEline] = str;
  2051.                }
  2052.                else
  2053.                   nomemory();
  2054.             }
  2055.          }
  2056.          lines = stop - start + 1;
  2057.  
  2058.          if (lines > 0)
  2059.          {
  2060.             int oldblocktype = Blocktype;
  2061.             Blocktype = BLOCK_LINE;
  2062.             BSline = start; BEline = stop;
  2063.             text_load();
  2064.             text_switch(savewin);
  2065.             do_bdelete();
  2066.             Blocktype = oldblocktype;
  2067.             text_load();
  2068.          }
  2069.          else
  2070.          {
  2071.             text_load();
  2072.             text_redrawblock(0);
  2073.             text_switch(savewin);
  2074.             text_load();
  2075.          }
  2076.          if (join1 && join2)
  2077.          {
  2078.             do_command("up");
  2079.             do_command("join2");
  2080.             do_command("if r last");
  2081.          }
  2082.       }
  2083.       else
  2084.       {
  2085.          do_copy();
  2086.          BEp = ep;
  2087.          BSchar = bsc; BSline = bsl; BEchar = bec; BEline = bel;
  2088.          do_bdelete();
  2089.       }
  2090.    }
  2091.    else
  2092.       title("Gotta mark a block first");
  2093. }
  2094.  
  2095.  
  2096. int kill_first_line(void)
  2097. {
  2098.    ED *ep = BEp;
  2099.  
  2100.    if (BSchar == 0)
  2101.    {
  2102.       if ((BSline == BEline) && (BEchar >= strlen(ep->List[BSline])))
  2103.          return 1;
  2104.       if (BSline != BEline)
  2105.          return 1;
  2106.    }
  2107.    return 0;
  2108. }
  2109.  
  2110. int kill_last_line(void)
  2111. {
  2112.    ED *ep = BEp;
  2113.  
  2114.    /*  if (BEchar >= strlen(ep->List[BSline])) */
  2115.    if (BEchar >= strlen(ep->List[BEline]))
  2116.    {
  2117.       if ((BSline == BEline) && (BSchar == 0))
  2118.          return 1;
  2119.       if (BSline != BEline)
  2120.          return 1;
  2121.    }
  2122.    return 0;
  2123. }
  2124.  
  2125.  
  2126. void AdjustBlock(void)
  2127. {
  2128.    ED *ep = Ep;
  2129.  
  2130.    if (BEp == ep)
  2131.    {
  2132.       text_sync();
  2133.       Blockempty = 0;
  2134.       switch (Blocktype)
  2135.       {
  2136.          case BLOCK_LINE:
  2137.             if (BSline >= 0)
  2138.             {
  2139.                BEline = ep->Line;
  2140.                if (BSline > BEline)
  2141.                {
  2142.                   long tmp = BSline; BSline = BEline; BEline = tmp;
  2143.                }
  2144.             }
  2145.             break;
  2146.          case BLOCK_CHARACTER:
  2147.             if (BSline >= 0)
  2148.             {
  2149.                BEline = ep->Line;
  2150.                BEchar = ep->Column;
  2151.                if ((BEline > initialBSline) || ((BEline == initialBSline) && (BEchar > initialBSchar)))
  2152.                {
  2153.                   BSline = initialBSline; BSchar = initialBSchar;
  2154.                }
  2155.                if ((BSline == BEline) && (BSchar == BEchar))
  2156.                {
  2157.                   Blockempty = 1;
  2158.                   /* Empty blocks are now allowed */
  2159.                }
  2160.                else if ((BSline > BEline) && (BEline >= 0)) /* bend before bstart position */
  2161.                {
  2162.                   short tp;
  2163.                   long tmp = BSline; BSline = BEline; BEline = tmp;
  2164.                   tp = BSchar; BSchar = BEchar; BEchar = tp;
  2165.                }
  2166.                else if ((BSline == BEline) && (BSchar > BEchar)) /* bend before bstart position */
  2167.                {
  2168.                   short tp = BSchar; BSchar = BEchar; BEchar = tp;
  2169.                }
  2170.                else /* bend after bstart position  at least one byte */
  2171.                {
  2172.                   if (--BEchar < 0)
  2173.                   {
  2174.                      BEline--; /* This might result in an empty block, which is legal now */
  2175.                      BEchar = strlen((char *)ep->List[BEline]);
  2176.                   }
  2177.                }
  2178.  
  2179.                if ((BEline < initialBSline) || ((BEline == initialBSline) && (BEchar < initialBSchar)))
  2180.                {
  2181.                   BEline = initialBSline; BEchar = initialBSchar;
  2182.                }
  2183.                
  2184.             }
  2185.  
  2186.             break;
  2187.          case BLOCK_VERTICAL:
  2188.             title("Not implemented yet");
  2189.             break;
  2190.       }
  2191.    }
  2192. }
  2193.