home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d01xx / d0113.lha / Dme / src / text2.c < prev    next >
C/C++ Source or Header  |  1987-11-21  |  20KB  |  1,006 lines

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