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