home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 389.lha / dme_v1.40 / src / cmd2.c < prev    next >
C/C++ Source or Header  |  1990-07-03  |  23KB  |  1,180 lines

  1.  
  2. /*
  3.  * CMD2.C
  4.  *
  5.  *    (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  */
  7.  
  8. #include "defs.h"
  9. #include <workbench/startup.h>
  10. #include <workbench/workbench.h>
  11.  
  12. typedef struct WBStartup    WBS;
  13. typedef struct DiskObject   DISKOBJ;
  14.  
  15. extern void *GetDiskObject();
  16.  
  17. #define nomemory()  {memoryfail = 1;}
  18.  
  19. #if AREXX
  20. #include "rexx.h"
  21. extern int foundcmd;       /* control for implicit ARexx macro invocation   */
  22. extern int cmderr;       /* global command error flag for do_rexx()'s use */
  23. #endif
  24.  
  25. extern char MForceTitle;
  26. extern void do_bmove();
  27.  
  28. extern WBS  *Wbs;
  29.  
  30. ED *
  31. uninit_init(ep)
  32. ED *ep;
  33. {
  34.     FONT  *font;
  35.     BPTR lock = DupLock((BPTR)ep->dirlock);
  36.     WIN *win;
  37.     int bufsiz = offsetof(_ED,EndConfig) - offsetof(_ED, BeginConfig);
  38.     char *buf = malloc(bufsiz);
  39.  
  40.     movmem(&ep->BeginConfig, buf, bufsiz);
  41.     win = ep->Win;
  42.     font = ep->Font;
  43.     ep->Font = NULL;
  44.     text_uninit();
  45.     text_init(Ep, NULL, NULL);
  46.     ep = Ep;
  47.     if (ep->Font)
  48.     CloseFont(ep->Font);
  49.     ep->Win = win;
  50.     ep->Font = font;
  51.  
  52.     movmem(buf, &ep->BeginConfig, bufsiz);
  53.  
  54.     ep->Modified = 0;
  55.     ep->Line = ep->Topline = 0;
  56.     UnLock((BPTR)ep->dirlock);
  57.     ep->dirlock = (long)lock;
  58.  
  59.     free(buf);
  60.     return(ep);
  61. }
  62.  
  63. void
  64. do_remeol()
  65. {
  66.     Current[Clen = Ep->Column] = 0;
  67.     text_sync();
  68.     text_redisplaycurrline();
  69. }
  70.  
  71. void
  72. do_wleft()
  73. {
  74.     ED *ep = Ep;
  75.     int i;
  76.  
  77.     for (;;) {
  78.     i = ep->Column;
  79.     if (i == 0)
  80.         goto prevline;
  81.     --i;
  82.     while (i && Current[i] == ' ')
  83.         --i;
  84.     if (i == 0 && Current[0] == ' ') {
  85. prevline:
  86.         if (Comlinemode || ep->Line == 0) {
  87.         i = ep->Column;
  88.         break;
  89.         }
  90.         text_sync();
  91.         --ep->Line;
  92.         text_load();
  93.         ep->Column = Clen;
  94.         continue;
  95.     }
  96.     while (i && Current[i] != ' ')
  97.         --i;
  98.     if (Current[i] == ' ')
  99.         ++i;
  100.     break;
  101.     }
  102.     ep->Column = i;
  103.     text_sync();
  104. }
  105.  
  106. void
  107. do_wright()
  108. {
  109.     ED *ep = Ep;
  110.     int i;
  111.  
  112.     for (;;) {
  113.     i = ep->Column;
  114.     if (i == Clen)
  115.         goto nextline;
  116.     while (i != Clen && Current[i] != ' ')  /* skip past current word */
  117.         ++i;
  118.     while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
  119.         ++i;
  120.     if (i == Clen) {
  121. nextline:
  122.         if (Comlinemode || ep->Line == ep->Lines - 1) {
  123.         i = ep->Column;
  124.         break;
  125.         }
  126.         text_sync();
  127.         ++ep->Line;
  128.         text_load();
  129.         ep->Column = i = 0;
  130.         if (Current[0] != ' ')
  131.         break;
  132.         continue;
  133.     }
  134.     break;
  135.     }
  136.     ep->Column = i;
  137.     text_sync();
  138. }
  139.  
  140. void
  141. do_split()              /* split line in two at cursor pos */
  142. {
  143.     ubyte buf[256];
  144.     ED *ep = Ep;
  145.     RP *rp = ep->Win->RPort;
  146.  
  147.     strcpy(buf, Current+ep->Column);
  148.     Current[Clen = ep->Column] = '\0';
  149.     text_sync();
  150.     SetAPen(rp, ep->BGPen);
  151.     if (Nsu == 0)
  152.     RectFill(rp, COL(0), ROW(ep->Line-ep->Topline), Xbase+Xpixs, ROW(ep->Line-ep->Topline+1)-1);
  153.     SetAPen(rp, ep->FGPen);
  154.     text_displayseg(ep->Line - ep->Topline, 1);
  155.     do_downadd();
  156.     do_insline();
  157.     strcpy(Current, buf);
  158.     Clen = strlen(Current);
  159.     text_sync();
  160.     text_displayseg(ep->Line - ep->Topline, 1);
  161.     do_up();
  162. }
  163.  
  164. do_join()
  165. {
  166.     int i = Clen, j;
  167.     ED *ep = Ep;
  168.  
  169.     if (ep->Line + 1 < ep->Lines && strlen(ep->List[ep->Line+1])+i <= 253) {
  170.     if (i && Current[i-1] != ' ')
  171.         Current[i++] = ' ';
  172.     strcpy(Current+i, ep->List[ep->Line+1]);
  173.     for (j = i; Current[j] == ' '; ++j);
  174.     for (; i >= 0 && Current[i] == ' '; --i);
  175.     if (j > i+2)
  176.         movmem(Current+j, Current+i+2, strlen(Current+j)+1);
  177.     Clen = strlen(Current);
  178.     text_sync();
  179.     text_displayseg(ep->Line - ep->Topline, 1);
  180.     do_down();
  181.     do_deline();
  182.     do_up();
  183.     return(1);
  184.     }
  185.     return(0);
  186. }
  187.  
  188. void
  189. do_margin()
  190. {
  191.     Ep->Margin = atoi(av[1]);
  192. }
  193.  
  194. void
  195. do_wordwrap()
  196. {
  197.     ED *ep = Ep;
  198.  
  199.     if (av[1][1] == 'n')
  200.     ep->Wordwrap = 1;
  201.     if (av[1][1] == 'f')
  202.     ep->Wordwrap = 0;
  203.     if (av[1][0] == 't')
  204.     ep->Wordwrap = 1 - ep->Wordwrap;
  205.     if (ep->Wordwrap)
  206.     title("Wordwrap ON");
  207.     else
  208.     title("Wordwrap OFF");
  209. }
  210.  
  211. void
  212. do_setparcol()
  213. {
  214.     Ep->WWCol = atoi(av[1]);
  215. }
  216.  
  217. /*
  218.  * n == -1  :    force reformat entire paragraph
  219.  * n ==  0  :    only until line equalizes (from text_write())
  220.  *
  221.  * What is a paragraph?   A paragraph ends whenever the left justification
  222.  * gets larger, or on a blank line.
  223.  */
  224.  
  225. void
  226. do_reformat(n)
  227. {
  228.     char *str;
  229.     ED *ep = Ep;
  230.     RP *rp = ep->Win->RPort;
  231.     int nlok, lnsc, fnst, fnsc;
  232.     int column = ep->Column;
  233.     int srow   = ep->Line;
  234.     int crow   = srow;
  235.     int erow   = srow;
  236.     short dins = 0;        /* relative insert lines/delete lines   */
  237.     char moded = 0;        /* any modifications done at all?        */
  238.     char checked = 0;        /* for cursor positioning.            */
  239.  
  240.     if (ep->Margin == 0)
  241.     ep->Margin = 75;
  242.  
  243.     ++Nsu;
  244.     for (;;) {
  245.     str = (char *)ep->List[ep->Line+1];
  246.     fnst = 0;
  247.     fnsc = firstns(Current);
  248.     nlok = (ep->Line + 1 < ep->Lines && fnsc >= (fnst=firstns(str)));
  249.     if (ep->WWCol >= 0)
  250.         fnst = fnsc = ep->WWCol;
  251.     if (nlok && str[0] == 0)
  252.         nlok = 0;
  253.     lnsc = lastns(Current);
  254.     if (lnsc < ep->Margin) {    /* space at end of line for marg-lnsc-2 letter word   */
  255.         if (nlok == 0)        /* but no more data to joinup   */
  256.         break;          /* done */
  257.         if (ep->Margin - lnsc - 2 >= wordlen(str+fnst)) {
  258.         ep->Column = 0;
  259.         Clen = lastns(Current);
  260.         if (Current[Clen])
  261.             ++Clen;
  262.         moded = 1;
  263.         --dins;
  264.         if (do_join())
  265.             continue;
  266.         ++dins;
  267.         title("Error, Margin > 124");
  268.         break;
  269.         }
  270.         if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  271.         break;
  272.         do_down();
  273.         erow = ep->Line;
  274.         continue;
  275.     }
  276.                 /* no space, need to split    */
  277.                 /* find start of prev word    */
  278.     for (;;) {
  279.         int i = lnsc;
  280.         while (i && Current[i] != ' ')
  281.         --i;
  282.         lnsc = i;
  283.         if (i >= ep->Margin) {
  284.         while (i && Current[i] == ' ')
  285.             --i;
  286.         if (i < ep->Margin)
  287.             break;
  288.         lnsc = i;
  289.         continue;
  290.         }
  291.         break;
  292.     }
  293.     if (lnsc) {             /* ok to split at word          */
  294.         ++lnsc;
  295.         ++dins;
  296.         ep->Column = lnsc;
  297.         do_split(); /* Split at point LNSC          */
  298.         do_down();          /* must insert proper amount?   */
  299.         {
  300.         int indent = (nlok == 0) ? fnsc : fnst;
  301.         if (ep->WWCol >= 0)
  302.             indent = ep->WWCol;
  303.         if (!checked) {
  304.             checked = 1;
  305.             if (lnsc <= column) {   /* if split before cursor   */
  306.             column = column - ep->Column + indent;
  307.             ++crow;
  308.             }
  309.         }
  310.         if (Clen + indent < 253) {
  311.             movmem(Current, Current + indent, strlen(Current)+1);
  312.             setmem(Current, indent, ' ');
  313.             Clen += indent;
  314.         }
  315.         }
  316.         erow = ep->Line;
  317.         continue;
  318.     }
  319.     if (n == 0)
  320.         break;
  321.     do_down();
  322.     }
  323.     if (column < 0 || column > 200)
  324.     column = 0;
  325.     if (srow >= ep->Lines) {
  326.     srow = ep->Lines - 1;
  327.     goto ra;
  328.     }
  329.     if (dins || srow < ep->Topline || srow >= ep->Topline + Rows) {
  330. ra:
  331.     text_sync();
  332.     --Nsu;
  333.     ep->Line = crow;
  334.     ep->Column = column;
  335.     text_load();
  336.     if (!text_sync())
  337.         text_redisplay();
  338.     } else {
  339.     text_sync();
  340.     --Nsu;
  341.     ep->Line = crow;
  342.     ep->Column = column;
  343.     text_load();
  344.     if (erow != srow) {
  345.         if (!text_sync()) {
  346.         ++erow;
  347.         if (erow - ep->Topline > Rows)
  348.             erow = ep->Topline + Rows;
  349.         SetAPen(rp, ep->BGPen);
  350.         RectFill(rp, COL(0), ROW(srow - ep->Topline), Xbase+Xpixs, ROW(erow - ep->Topline)-1);
  351.         SetAPen(rp, ep->FGPen);
  352.         text_displayseg(srow - ep->Topline, erow - srow);
  353.         }
  354.     } else {
  355.         text_sync();
  356.         if (moded)
  357.         text_redisplaycurrline();
  358.     }
  359.     }
  360.     if (column > Clen) {
  361.     setmem(Current+Clen, column - Clen, ' ');
  362.     Current[column] = 0;
  363.     }
  364.     ep->Column = column;
  365. }
  366.  
  367. void
  368. do_tabstop()
  369. {
  370.     Ep->Tabstop = atoi(av[1]);
  371. }
  372.  
  373. void
  374. do_insertmode()
  375. {
  376.     ED *ep = Ep;
  377.  
  378.     if (av[1][0]) {
  379.     switch(av[1][1] & 0x1F) {
  380.     case 'n'&0x1F:
  381.         ep->Insertmode = 1;
  382.         break;
  383.     case 'f'&0x1F:
  384.         ep->Insertmode = 0;
  385.         break;
  386.     case 'o'&0x1F:
  387.         ep->Insertmode = 1 - ep->Insertmode;
  388.         break;
  389.     }
  390.     if (ep->Insertmode)
  391.         title("Insert mode on");
  392.     else
  393.         title("Insert mode off");
  394.     }
  395. }
  396.  
  397. void
  398. do_insline()
  399. {
  400.     ubyte *ptr;
  401.     ED *ep = Ep;
  402.     RP *rp = ep->Win->RPort;
  403.  
  404.     ep->Modified = 1;
  405.     text_sync();
  406.     if (makeroom(32) && (ptr = allocb(1))) {
  407.     bmovl(ep->List+ep->Line, ep->List+ep->Line+1,ep->Lines-ep->Line);
  408.     ep->List[ep->Line] = ptr;
  409.     *ptr = 0;
  410.     ++ep->Lines;
  411.     if (BEp == ep) {
  412.         if (ep->Line < BSline)
  413.         ++BSline;
  414.         if (ep->Line <= BEline)
  415.         ++BEline;
  416.     }
  417.     } else {
  418.     nomemory();
  419.     }
  420.     text_load();
  421.     if (Nsu == 0)
  422.     ScrollRaster(rp,0,-Ysize, COL(0), ROW(ep->Line-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  423.     text_displayseg(ep->Line - ep->Topline, 1);
  424. }
  425.  
  426. void
  427. do_deline()
  428. {
  429.     int delline;
  430.     ED *ep = Ep;
  431.     RP *rp = ep->Win->RPort;
  432.  
  433.     if (ep->Lines > 1) {
  434.     ep->Modified = 1;
  435.     text_sync();
  436.  
  437.     FreeMem(ep->List[ep->Line], strlen(ep->List[ep->Line])+1);
  438.     bmovl(ep->List+ep->Line+1, ep->List+ep->Line,ep->Lines-ep->Line-1);
  439.     if (BEp == ep) {
  440.         if (ep->Line < BSline)
  441.         --BSline;
  442.         if (ep->Line <= BEline)
  443.         --BEline;
  444.     }
  445.     delline = ep->Line;
  446.     if (ep->Line >= --ep->Lines) {
  447.         --ep->Line;
  448.         text_load();
  449.         if (ep->Line < ep->Topline) {
  450.         if (Nsu == 0) {
  451.             ep->Topline = ep->Line - (Rows>>1);
  452.             if (ep->Topline < 0)
  453.             ep->Topline = 0;
  454.             text_redisplay();
  455.         }
  456.         return;
  457.         }
  458.     }
  459.     text_load();
  460.     if (Nsu == 0)
  461.         ScrollRaster(rp,0,Ysize, COL(0), ROW(delline-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  462.     text_displayseg(Rows-1, 1);
  463.     } else {
  464.     do_firstcolumn();
  465.     do_remeol();
  466.     ep->Modified = 0;
  467.     }
  468. }
  469.  
  470. void
  471. do_chfilename()
  472. {
  473.     text_sync();
  474.     strncpy(Ep->Name, av[1], 63);
  475.     MForceTitle = 1;
  476. }
  477.  
  478. void
  479. do_edit()
  480. {
  481.     FILE *fi;
  482.     BPTR oldlock;
  483.     long lines;
  484.     ubyte buf[256];
  485.     ubyte *ptr;
  486.     char failed = 1;
  487.     ED *ep = Ep;
  488.  
  489.     text_sync();
  490.     if (*av[0] == 'n') {        /* newfile or insfile   */
  491.     if (ep->Modified && getyn("Delete modified Image?") == 0)
  492.         return;
  493.     ep = uninit_init(ep);
  494.     strncpy(ep->Name, av[1], 63);
  495.     } else {
  496.     ep->Modified = 1;
  497.     }
  498.     lines = ep->Lines;
  499.     oldlock = CurrentDir((BPTR)ep->dirlock);
  500.     if (fi = fopen(av[1], "r")) {
  501.     int len;
  502.     char oktitle = 1;
  503.  
  504.     title("Loading...");
  505.     while ((len = xefgets(fi, buf, 255)) >= 0) {
  506.         failed = 0;
  507.         if (makeroom(256) && (ptr = allocb(len+1))) {
  508.         ep->List[ep->Lines++] = ptr;
  509.         movmem(buf, ptr, len+1);
  510.         } else {
  511.         set_window_params();
  512.         nomemory();
  513.         oktitle = 0;
  514.         break;
  515.         }
  516.     }
  517.     set_window_params();
  518.     if (oktitle)
  519.         title("OK");
  520.     } else {
  521.     title("File Not Found");
  522. #if AREXX
  523.     cmderr = CMD_FAILED;
  524. #endif
  525.     }
  526.     fclose(fi);
  527.     CurrentDir(oldlock);
  528.     if (ep->Lines != 1 && lines == 1 && ep->List[0][0] == 0) {
  529.     ep->Modified = 0;
  530.     ep->Line = 0;
  531.     FreeMem(ep->List[0], strlen(ep->List[0])+1);
  532.     bmovl(ep->List+1, ep->List,--ep->Lines);
  533.     } else {
  534.     if (!failed && lines <= ep->Lines - 1) {
  535.         BEp = ep;
  536.         BSline = lines;
  537.         BEline = ep->Lines - 1;
  538.         do_bmove();
  539.     }
  540.     }
  541.     set_window_params();
  542.     text_load();
  543.     text_redisplay();
  544. }
  545.  
  546.  
  547. static char blockmode;
  548.  
  549. void
  550. do_bsave()
  551. {
  552.     blockmode = 1;
  553.     do_saveas();
  554. }
  555.  
  556. void
  557. do_save()
  558. {
  559.     av[1] = Ep->Name;
  560.     do_saveas();
  561. }
  562.  
  563. void
  564. do_savetabs()
  565. {
  566.     Savetabs = (av[1][0] && av[1][1] == 'n') ? 1 : 0;
  567. }
  568.  
  569. void
  570. do_saveas()
  571. {
  572.     BPTR oldlock;
  573.     FILE *fi;
  574.     long i;
  575.     short j, k;
  576.     ubyte *ptr, *bp;
  577.     long xs, xe;
  578.     ubyte buf[256];
  579.     char bm;
  580.     ED *ep;
  581.  
  582.     bm = blockmode;
  583.     if (blockmode && blockok()) {
  584.     xs = BSline;
  585.     xe = BEline + 1;
  586.     ep = BEp;
  587.     } else {
  588.     xs = 0;
  589.     xe = Ep->Lines;
  590.     ep = Ep;
  591.     }
  592.     blockmode = 0;
  593.     text_sync();
  594.     oldlock = CurrentDir((BPTR)Ep->dirlock);
  595.     if (Wbs && Wdisable == 0) {     /* Write out .info file */
  596.     DISKOBJ sdo, *d;
  597.     clrmem(&sdo, sizeof(sdo));
  598.     if ((d = GetDiskObject(av[1])) == NULL) {
  599.         if (getpathto(Wbs->sm_ArgList[0].wa_Name, buf)) {
  600.         sdo.do_Magic = WB_DISKMAGIC;
  601.         sdo.do_Version = WB_DISKVERSION;
  602.         makemygadget(&sdo.do_Gadget);
  603.         sdo.do_Type = WBPROJECT;
  604.         sdo.do_DefaultTool = (char *)buf;
  605.         sdo.do_ToolTypes = NULL;
  606.         sdo.do_CurrentX = NO_ICON_POSITION;
  607.         sdo.do_CurrentY = NO_ICON_POSITION;
  608.         sdo.do_DrawerData = NULL;
  609.         sdo.do_ToolWindow = NULL;
  610.         sdo.do_StackSize = 8192;
  611.         PutDiskObject(av[1], &sdo);
  612.         }
  613.     } else {
  614.         FreeDiskObject(d);
  615.     }
  616.     }
  617.     if (fi = fopen(av[1], "w")) {
  618.     title("Saving...");
  619.     for (i = xs; i < xe; ++i) {
  620.         ptr = ep->List[i];
  621.         if (Savetabs) {
  622.         for (bp = buf, j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
  623.             *bp = *ptr;
  624.             if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
  625.             k = j;
  626.             while (k-- >= 0 && *bp == ' ')
  627.                 --bp;
  628.             *++bp = 9;
  629.             } else {
  630.             if (*bp < 32 || *bp == '\"' || *bp == '\'' || *bp == '\`' || *bp == '(')
  631.                 break;
  632.             }
  633.         }
  634.         strcpy(bp, ptr);
  635.         ptr = buf;
  636.         }
  637.         fputs(ptr, fi);
  638.         fputc('\n', fi);
  639.     }
  640.     if (fclose(fi)) {
  641. err:        Abortcommand = 1;
  642.         title("WRITE FAILED!");
  643.     } else {
  644.         ep->Modified &= bm;
  645.         title("OK");
  646.     }
  647.     } else {
  648.     title("Unable to open write file");
  649.     Abortcommand = 1;
  650.     }
  651.     CurrentDir(oldlock);
  652. }
  653.  
  654. void
  655. do_block()          /* block, unblock   */
  656. {
  657.     text_sync();
  658.  
  659.     switch(av[0][0]) {
  660.     case 'b':
  661.     if (BSline < 0) {
  662. bstart:
  663.         BEp = Ep;
  664.         BSline = Ep->Line;
  665.         title("Block Begin");
  666.     } else {
  667.         if (BEline > -1) {
  668.         title("Block Already Marked");
  669.         break;
  670.         }
  671.         if (BEp != Ep)
  672.         goto bstart;
  673.         title("Block End");
  674.         BEline = Ep->Line;
  675.         if (BSline > BEline) {
  676.         BEline = BSline;
  677.         BSline = Ep->Line;
  678.         }
  679.         text_redrawblock(1);
  680.     }
  681.     break;
  682.     case 'u':
  683.     text_redrawblock(0);
  684.     title ("Block Unmarked");
  685.     break;
  686.     }
  687. }
  688.  
  689.  
  690. blockok()
  691. {
  692.     if (BEp && BSline >= 0 && BSline <= BEline && BEline < BEp->Lines)
  693.     return(1);
  694.     BEp = NULL;
  695.     BSline = BEline = -1;
  696.     title("Block Not Specified");
  697.     return(0);
  698. }
  699.  
  700. void
  701. do_bdelete()
  702. {
  703.     long n;
  704.     ED *bep = BEp;
  705.     WIN *savewin = Ep->Win;
  706.  
  707.     if (blockok()) {
  708.     text_switch(bep->Win);
  709.     n = BEline - BSline + 1;
  710.     if (bep->Line >= BSline && bep->Line <= BEline)
  711.         bep->Line = BSline;
  712.     if (bep->Line > BEline)
  713.         bep->Line -= n;
  714.     freelist(bep->List + BSline, BEline - BSline + 1);
  715.     bmovl(bep->List+BEline+1,bep->List+BSline,(bep->Lines-BEline-1));
  716.     bep->Lines -= n;
  717.     bep->Modified = 1;
  718.     if (bep->Line >= bep->Lines)
  719.         bep->Line = bep->Lines - 1;
  720.     if (bep->Line < 0)
  721.         bep->Line = 0;
  722.     if (bep->Lines == 0) {
  723.         ++bep->Lines;
  724.         bep->List[0] = allocb(1);
  725.         bep->List[0][0] = 0;
  726.     }
  727.     text_load();
  728.     BEp = NULL;
  729.     BSline = BEline = -1;
  730.     if (!text_sync())
  731.         text_redisplay();
  732.     text_switch(savewin);
  733.     }
  734. }
  735.  
  736. void
  737. do_bcopy()
  738. {
  739.     ubyte **list;
  740.     long lines, i;
  741.     ED *ep = Ep;
  742.  
  743.     text_sync();
  744.     if (!blockok())
  745.     return;
  746.     if (ep == BEp && ep->Line > BSline && ep->Line <= BEline) {
  747.     title("Cannot Move into self");
  748.     return;
  749.     }
  750.     lines = BEline - BSline + 1;
  751.     if (extend(ep, lines)) {
  752.     if (list = (ubyte **)allocl(lines)) {
  753.         bmovl(BEp->List+BSline,list,lines);
  754.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  755.         for (i = 0; i < lines; ++i) {
  756.         ubyte *str = allocb(strlen(list[i])+1);
  757.         if (!str) {
  758.             nomemory();
  759.             FreeMem(list, lines * sizeof(char *));
  760.             freelist(ep->List + Ep->Line, i);
  761.             bmovl(ep->List+ep->Line+lines, ep->List+ep->Line, ep->Lines-ep->Line);
  762.             return;
  763.         }
  764.         strcpy(str, list[i]);
  765.         ep->List[ep->Line+i] = str;
  766.         }
  767.         FreeMem(list, lines * sizeof(char *));
  768.     }
  769.     }
  770.     if (ep == BEp && ep->Line <= BSline) {
  771.     BSline += lines;
  772.     BEline += lines;
  773.     }
  774.     ep->Modified = 1;
  775.     ep->Lines += lines;
  776.     text_load();
  777.     if (!text_sync())
  778.     text_redisplay();
  779. }
  780.  
  781.  
  782. void
  783. do_bmove()
  784. {
  785.     long lines;
  786.     ubyte **list;
  787.     ED *ep = Ep;
  788.  
  789.     text_sync();
  790.     if (!blockok())
  791.     return;
  792.     if (BEp == ep && ep->Line >= BSline && ep->Line <= BEline) {
  793.     title("Cannot Move into self");
  794.     return;
  795.     }
  796.     lines = BEline - BSline + 1;
  797.     if (!(list = (ubyte **)allocl(lines))) {
  798.     nomemory();
  799.     return;
  800.     }
  801.     BEp->Modified = ep->Modified = 1;
  802.     bmovl(BEp->List + BSline, list, lines);
  803.     if (ep == BEp) {
  804.     if (ep->Line > BSline) {
  805.         bmovl(ep->List+BEline+1, ep->List+BSline, ep->Line-BEline-1);
  806.         bmovl(list, ep->List + ep->Line - lines, lines);
  807.     } else {
  808.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, BSline-ep->Line);
  809.         bmovl(list, ep->List + ep->Line, lines);
  810.     }
  811.     } else {
  812.     WIN *savewin = ep->Win;
  813.     if (extend(ep, lines)) {
  814.         bmovl(BEp->List+BEline+1, BEp->List+BSline, BEp->Lines-BEline-1);
  815.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  816.         bmovl(list, ep->List+ep->Line, lines);
  817.         ep->Lines += lines;
  818.         BEp->Lines -= lines;
  819.         if (BEp->Line >= BSline && BEp->Line <= BEline)
  820.         BEp->Line = BSline - 1;
  821.         if (BEp->Line > BEline)
  822.         BEp->Line -= lines;
  823.         if (BEp->Line < 0)
  824.         BEp->Line = 0;
  825.         BSline = BEline = -1;
  826.         if (BEp->Lines == 0) {
  827.         ubyte *ptr = allocb(1);
  828.         BEp->List[0] = ptr;
  829.         *ptr = 0;
  830.         ++BEp->Lines;
  831.         }
  832.         text_load();
  833.         text_switch(BEp->Win);
  834.         BEp = NULL;
  835.         ep = Ep;
  836.         if (!ep->iconmode) {
  837.         if (!text_sync())
  838.             text_redisplay();
  839.         }
  840.         text_switch(savewin);
  841.         ep = Ep;
  842.     }
  843.     }
  844.     BSline = BEline = -1;
  845.     BEp = NULL;
  846.     FreeMem(list, lines * sizeof(char *));
  847.     ep->Modified = 1;
  848.     text_load();
  849.     if (!text_sync())
  850.     text_redisplay();
  851. }
  852.  
  853.  
  854. /*
  855.  * IF condition trueaction, IFELSE condition trueaction falseaction
  856.  *
  857.  *  condition:    !condition NOT the specified condition.
  858.  *        #       toggle number is SET
  859.  *        top       top of file (on first line)
  860.  *        bot       end of file (on last line)
  861.  *        left       start of line (leftmost column)
  862.  *        right       end of line (nothing but spaces under and to the right)
  863.  *        modified   text has been modified
  864.  *        insert       currently in insert mode
  865.  *        y[<=>]#    cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  866.  *        x[<=>]#    cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  867.  *                <> means 'not equal'
  868.  *
  869.  *        cl       char under cursor is lower case
  870.  *        cu       char under cursor is upper case
  871.  *        ca       char under cursor is alpha
  872.  *        cn       char under cursor is numeric
  873.  *        cb       char within selected block
  874.  *        c[<=>]#    char under cursor is (combo of <,>,and =) #
  875.  */
  876.  
  877. void
  878. do_if()
  879. {
  880.     char haselse = (av[0][2] == 'e');
  881.     char iswhile = (av[0][0] == 'w');
  882.     char istrue, notop = 0;
  883.     char c, cx, cc;
  884.     ubyte *buf1, *buf2;
  885.     ubyte *ptr;
  886.     ED *ep = Ep;
  887.     int i, cxn, cn;
  888.  
  889.     buf1 = (ubyte *)malloc(256);
  890.     buf2 = (ubyte *)malloc(256);
  891.     if (buf1 == NULL || buf2 == NULL) {
  892.     if (buf1) free(buf1);
  893.     if (buf2) free(buf2);
  894.     title("No Memory!");
  895.     return;
  896.     }
  897.     breakreset();
  898.     ptr = av[1];
  899.     if (*ptr == '!') {
  900.     notop = 1;
  901.     ++ptr;
  902.     }
  903.     c = ptr[0];
  904.     cn= atoi(ptr);
  905.     cx= ptr[1];
  906.     cxn=atoi(ptr+1);
  907.     strcpy(buf1, av[2]);
  908.  
  909. loop:
  910.     istrue = 0;
  911.     i = 0;
  912.     switch(c) {
  913.     case 'x':
  914.     i = ep->Column + 1;
  915.     case 'y':
  916.     if (!i)
  917.         i = ep->Line + 1;
  918. conditional:
  919.     {
  920.         int j, n;
  921.         char any = 0;
  922.  
  923.         for (j = 1; ptr[j] && (ptr[j]<'0'||ptr[j]>'9'); ++j);
  924.         n = atoi(ptr+j);
  925.         for (j = 1; ptr[j]; ++j) {
  926.         switch(ptr[j]) {
  927.         case '<':
  928.             any = 1;
  929.             if (i < n)
  930.             istrue = 1;
  931.             break;
  932.         case '=':
  933.             any = 1;
  934.             if (i == n)
  935.             istrue = 1;
  936.             break;
  937.         case '>':
  938.             any = 1;
  939.             if (i > n)
  940.             istrue = 1;
  941.             break;
  942.         }
  943.         }
  944.         if (!any && i == n)  /* default is equivalence   */
  945.         istrue = 1;
  946.     }
  947.     break;
  948.     case 't':
  949.     istrue = ep->Line == 0;
  950.     break;
  951.     case 'b':
  952.     istrue = ep->Line == ep->Lines-1;
  953.     break;
  954.     case 'l':
  955.     istrue = ep->Column == 0;
  956.     break;
  957.     case 'r':
  958.     istrue = ep->Column == Clen;
  959.     break;
  960.     case 'm':
  961.     text_sync();
  962.     istrue = ep->Modified != 0;
  963.     break;
  964.     case 'e':
  965.     istrue = Comlinemode != 0;
  966.     break;
  967.     case 'i':
  968.     istrue = ep->Insertmode != 0;
  969.     break;
  970.     case 'c':
  971.     cc = Current[ep->Column];
  972.     switch(cx) {
  973.     case 'b':
  974.         istrue = BEp == ep && ep->Line >= BSline && ep->Line <= BEline;
  975.         break;
  976.     case 'l':
  977.         istrue = cc >= 'a' && cc <= 'z';
  978.         break;
  979.     case 'u':
  980.         istrue = cc >= 'A' && cc <= 'Z';
  981.         break;
  982.     case 'a':
  983.         istrue = (cc>='a'&&cc<='z')||(cc>='A'&&cc<='Z')||(cc>='0'&&cc<='9');
  984.         break;
  985.     case 'n':
  986.         istrue = (cc >= '0' && cc <= '9');
  987.         break;
  988.     default:        /* c[<=>]#  */
  989.         i = Current[ep->Column];
  990.         goto conditional;
  991.         break;
  992.     }
  993.     break;
  994.     default:
  995.     if (c >= '0' && c <= '9')
  996.         istrue = do_toggle(cn) != 0;
  997.     else
  998.         title("bad conditional");
  999.     break;
  1000.     }
  1001.     istrue ^= notop;
  1002.     if (istrue) {
  1003.     strcpy(buf2, buf1);     /* could be executed multiple times */
  1004.     if (do_command(buf2) == 0)
  1005.         goto done;
  1006.     if (iswhile) {
  1007.         if (breakcheck())
  1008.         Abortcommand = 1;
  1009.         else
  1010.         goto loop;
  1011.     }
  1012.     } else {
  1013.     if (haselse) {          /* only executed once */
  1014.         strcpy(buf2, av[3]);
  1015.         do_command(buf2);
  1016.     }
  1017.     }
  1018. done:
  1019.     free(buf1);
  1020.     free(buf2);
  1021. }
  1022.  
  1023.  
  1024. /*
  1025.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  1026.  */
  1027.  
  1028. do_toggle(n)
  1029. {
  1030.     static char tg[MAXTOGGLE];
  1031.     int i;
  1032.  
  1033.     if (n >= 0) {
  1034.     if (n >= MAXTOGGLE)
  1035.         return(0);
  1036.     return((int)tg[n]);
  1037.     }
  1038.     i = atoi(av[1]);
  1039.     if (i >= 0 && i < MAXTOGGLE) {
  1040.     switch(av[0][0]) {
  1041.     case 't':
  1042.         tg[i] = !tg[i];
  1043.         break;
  1044.     case 's':
  1045.         tg[i] = 1;
  1046.         break;
  1047.     case 'r':
  1048.         tg[i] = 0;
  1049.         break;
  1050.     }
  1051.     }
  1052. }
  1053.  
  1054.  
  1055. void
  1056. do_tlate()
  1057. {
  1058.     ubyte *ptr = av[1];
  1059.     ED *ep = Ep;
  1060.     char c = Current[ep->Column];
  1061.  
  1062.     if (c == 0)
  1063.     c = ' ';
  1064.     if (ptr[0] == '+')
  1065.     c += atoi(ptr+1);
  1066.     else
  1067.     if (ptr[0] == '-')
  1068.     c -= atoi(ptr+1);
  1069.     else
  1070.     c = atoi(ptr);
  1071.     if (c) {
  1072.     if (Current[ep->Column] == 0) {
  1073.         Clen = ep->Column + 1;
  1074.         Current[Clen] = 0;
  1075.     }
  1076.     Current[ep->Column] = c;
  1077.     if (Nsu == 0) {
  1078.         movetocursor();
  1079.         setpen(ep->Line);
  1080.         Text(ep->Win->RPort, Current+ep->Column, 1);
  1081.     }
  1082.     }
  1083. }
  1084.  
  1085. /*
  1086.  *  BSOURCE
  1087.  *
  1088.  *  note that since the start and end lines are loaded immediately and the
  1089.  *  block unblock'd before execution starts, you can theoretically have
  1090.  *  another BSOURCE as part of this BSOURCE (but be carefull!).
  1091.  */
  1092.  
  1093. void
  1094. do_bsource()
  1095. {
  1096.     ubyte buf[256];
  1097.     int i, sl, se;
  1098.  
  1099.     if (blockok()) {
  1100.     sl = BSline;
  1101.     se = BEline + 1;
  1102.     for (i = sl; BEp && i < se && i < BEp->Lines; ++i) {
  1103.         text_sync();        /* make sure we are using latest text */
  1104.         strcpy(buf, BEp->List[i]);
  1105.         if (do_command(buf) == 0)
  1106.         break;
  1107.     }
  1108.     text_redrawblock(0);
  1109.     }
  1110. }
  1111.  
  1112. /*
  1113.  *  SCANF controlstring
  1114.  *
  1115.  *  The C scanf routine.  Only one variable, a string, is allowed in the
  1116.  *  control string.
  1117.  */
  1118.  
  1119. void
  1120. do_scanf()
  1121. {
  1122.     char buf[256];
  1123.  
  1124.     buf[0] = 0;
  1125.     sscanf(Current+Ep->Column,av[1],buf,buf,buf,buf,buf,buf,buf);
  1126.     if (String)
  1127.     free(String);
  1128.     String = (char *)malloc(strlen(buf)+1);
  1129.     strcpy(String,buf);
  1130.     title(String);
  1131. }
  1132.  
  1133. void
  1134. movetocursor()
  1135. {
  1136.     ED *ep = Ep;
  1137.     Move(ep->Win->RPort, XTbase+(ep->Column-ep->Topcolumn)*Xsize, YTbase+(ep->Line-ep->Topline)*Ysize);
  1138. }
  1139.  
  1140. extend(ep, lines)
  1141. ED *ep;
  1142. {
  1143.     long extra = ep->Maxlines - ep->Lines;
  1144.     ubyte **list;
  1145.  
  1146.     if (lines > extra) {
  1147.     lines += ep->Lines;
  1148.     if (list = (ubyte **)allocl(lines)) {
  1149.         bmovl(ep->List, list, ep->Lines);
  1150.         FreeMem(ep->List, sizeof(char *) * ep->Maxlines);
  1151.         ep->Maxlines = lines;
  1152.         ep->List = list;
  1153.         return(1);
  1154.     }
  1155.     nomemory();
  1156.     return(0);
  1157.     }
  1158.     return(1);
  1159. }
  1160.  
  1161. makeroom(n)
  1162. {
  1163.     ED *ep = Ep;
  1164.     if (ep->Lines >= ep->Maxlines)
  1165.     return(extend(ep, n));
  1166.     return(1);
  1167. }
  1168.  
  1169. void
  1170. freelist(list, n)
  1171. char **list;
  1172. {
  1173.     while (n) {
  1174.     FreeMem(list[0], strlen(list[0])+1);
  1175.     ++list;
  1176.     --n;
  1177.     }
  1178. }
  1179.  
  1180.