home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff153.lzh / Dme / src / cmd2.c < prev    next >
C/C++ Source or Header  |  1987-06-15  |  23KB  |  1,138 lines

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