home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / wp_dtp / xdme1820.lha / XDME / cmd.c < prev    next >
C/C++ Source or Header  |  1993-03-09  |  35KB  |  1,822 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     cmd.c
  5.  
  6.     DESCRIPTION
  7.     In this file you find all routines for programming like
  8.     IF, WHILE, REPEAT
  9.  
  10.     NOTES
  11.  
  12.     BUGS
  13.  
  14.     TODO
  15.  
  16.     EXAMPLES
  17.  
  18.     SEE ALSO
  19.  
  20.     INDEX
  21.  
  22.     HISTORY
  23.     14. Nov 1992    ada created
  24.  
  25. ******************************************************************************/
  26.  
  27. /**************************************
  28.         Includes
  29. **************************************/
  30. #include "defs.h"
  31. #define MYDEBUG     0
  32. #include "debug.h"
  33.  
  34.  
  35. /**************************************
  36.         Globale Variable
  37. **************************************/
  38. Prototype void do_if        (void);
  39. Prototype void do_repeat    (void);
  40. Prototype int  do_toggle    (int);
  41. Prototype void do_scanf     (void);
  42. Prototype void do_push        (void);
  43. Prototype void do_pop        (void);
  44. Prototype void do_swap        (void);
  45. Prototype void check_stack  (ED *);
  46.  
  47.  
  48. /**************************************
  49.       Interne Defines & Strukturen
  50. **************************************/
  51. typedef enum
  52. {
  53.     _IT_POS,
  54.     _IT_MODIFIED,
  55.     _IT_ICONMODE,
  56.     _IT_TABSTOP,
  57.     _IT_MARGIN,
  58.     _IT_INSERTMODE,
  59.     _IT_IGNORECASE,
  60.     _IT_WORDWRAP,
  61.     _IT_WWCOL,
  62.     _IT_WINDOW,
  63.     _IT_ICON,
  64.     _IT_PENS,
  65.     _IT_BLOCK,
  66.     _IT_AUTO,
  67.     _IT_SAVETABS,
  68.     _IT_ED,
  69.     _IT_DISCARD,
  70. } ItemType;
  71.  
  72. struct Item
  73. {
  74.     ItemType type;        /* _IT_xxx */
  75.     USHORT   size;        /* 1-normal, 2-special, 3-malloc'd */
  76.     ULONG    value;        /* value */
  77. };
  78.  
  79.  
  80. /**************************************
  81.         Interne Variable
  82. **************************************/
  83. static ULONG         MAX_STACK_SIZE = 0;
  84. static struct Item * ItemStack        = NULL;
  85. static USHORT         ItemStackDepth = 0;
  86.  
  87.  
  88. /**************************************
  89.        Interne Prototypes
  90. **************************************/
  91. static ItemType identify_item (char *);
  92.  
  93.  
  94. /*
  95.    IF condition trueaction, IFELSE condition trueaction falseaction
  96.  
  97.     condition:    !condition  NOT the specified condition.
  98.         #        toggle number is SET
  99.         top        top of file (on first line)
  100.         bot        end of file (on last line)
  101.         left        start of line (leftmost column)
  102.         right        end of line (nothing but spaces under and to the right)
  103.         modified    text has been modified
  104.         insert        currently in insert mode
  105.         y[<=>]#     cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  106.         x[<=>]#     cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  107.                 <> means 'not equal'
  108.  
  109.         cl        char under cursor is lower case
  110.         cu        char under cursor is upper case
  111.         ca        char under cursor is alpha
  112.         cn        char under cursor is numeric
  113.         cb        char within selected block
  114.         c[<=>]#     char under cursor is (combo of <,>,and =) #,
  115.                 where # can be a
  116.  
  117.                 ASCII-code (numeric: hex, oct, dez)
  118.                 String (enclosed in ""). The cursor must
  119.                     be on the first letter of "string".
  120.                 Character-Group: [], i.e. c=[1-9] will be true
  121.                     if cursor is on any number. c=[a-zA-DF-H]
  122.                     is a valid construct !
  123.  
  124.         block        will BLOCK fail ?
  125.         selnext     will SELECT NEXT succeed ?
  126.         selprev     will SELECT PREV succeed ?
  127.  
  128.  and especially for WHILE
  129.  
  130.         true       infinite-loop (!)
  131.  
  132. */
  133.  
  134.  
  135. void do_if (void)
  136. {
  137.     Bool    haselse = (av[0][2] == 'e'),    /* is there an ELSE ? */
  138.         iswhile = (av[0][0] == 'w'),    /* is this a WHILE ? */
  139.         istrue,                /* result of condition */
  140.         notop   = 0;            /* NOT ? */
  141.     Bool    c,
  142.         cx,
  143.         cc;
  144.     ubyte * buf1,                /* two buffers */
  145.       * buf2,
  146.       * ptr;                /* tmp ptr */
  147.     ED      * ep = Ep;
  148.     int     i,
  149.         j, /* PATCH_NULL */
  150.         n, /* PATCH_NULL */
  151.         cxn,
  152.         cn;
  153.  
  154.     buf1 = (ubyte *)malloc(MAXLINELEN);     /* get two buffers */
  155.     buf2 = (ubyte *)malloc(MAXLINELEN);
  156.  
  157.     if (buf1 == NULL || buf2 == NULL)
  158.     {
  159.     if (buf1) free(buf1);               /* :-( */
  160.     if (buf2) free(buf2);
  161.  
  162.     title ("No Memory!");
  163.     nomemory ();
  164.     return;
  165.     }
  166.  
  167.     /* prepare for Ctrl-C checking */
  168.  
  169.     breakreset ();
  170.  
  171.     ptr = av[1];
  172.  
  173.     /* check for NOT */
  174.  
  175.     if (*ptr == '!')
  176.     {
  177.     notop = 1;
  178.     ++ptr;
  179.     }
  180.  
  181.     c    = tolower(ptr[0]);
  182.     cn    = atoi ((char *)ptr);
  183.     cx    = tolower(ptr[1]);
  184.     cxn = atoi ((char *)ptr+1);
  185.  
  186.     strcpy ((char *)buf1, (char *)av[2]);
  187.  
  188. loop:
  189.     istrue = 0;
  190.     i       = 0;
  191.     j       = 1; /* PATCH_NULL */
  192.  
  193.     switch (c)
  194.     {
  195.     case '$':
  196.     case '&':
  197.         {
  198.         char   ci;
  199.         char * str;
  200.  
  201.         for (j = 1; isalnum(ptr[j]); ++j);
  202.         ci = ptr[j];
  203.         ptr[j] = 0;
  204.         str = getvar(ptr+1);
  205.         ptr[j] = ci;
  206.         i = 0;
  207.         if (str)
  208.         {
  209.             if (!is_number(str))
  210.             {
  211.             error ("%s:\nvariable %s does not contain an integer",av[1], ptr+1);
  212.             goto done;
  213.             } /* if */
  214.             i = atoi(str);
  215.             free(str);
  216.         } else
  217.         {
  218.             error ("%s:\nunknown variable %s", av[0], ptr+1);
  219.             goto done;
  220.         }
  221.         if (ci)
  222.             goto conditional;
  223.         istrue = (i != 0);
  224.         break;
  225.         }
  226.     case 'x':
  227.         i = ep->column + 1;
  228.  
  229.     case 'y':
  230.         if (!i)
  231.         i = ep->line + 1;
  232.  
  233. conditional:
  234.         {
  235.         /* int j, n; */
  236.         char any = 0;
  237.  
  238.         for (; ptr[j] != '<' && ptr[j] != '>' && ptr[j] != '=' && ptr[j]; ++j); /* j=1 deleted */
  239.         if (!ptr[j])
  240.         {
  241.             error ("%s:\nBad conditional:\n`%s'", av[0], av[1]);
  242.             goto done;
  243.         }
  244.  
  245.         for ( ; (ptr[j] == '<' || ptr[j] == '>' || ptr[j] == '=') && ptr[j]; ++j)
  246.         {
  247.             switch(ptr[j])
  248.             {
  249.             case '<':
  250.                 any |= 1;
  251.                 break;
  252.             case '=':
  253.                 any |= 2;
  254.                 break;
  255.             case '>':
  256.                 any |= 4;
  257.                 break;
  258.             }
  259.         }
  260.  
  261.         if (!ptr[j] || !any || any == 7)
  262.         {
  263.             error ("%s:\nBad conditional `%s':\nUnexp. EOL or wrong compare", av[0], av[1]);
  264.             goto done;
  265.         }
  266.  
  267.         for ( ; isspace (ptr[j]); ++j);
  268.         if (!ptr[j])
  269.         {
  270.             error ("%s:\nBad conditional `%s':\nUnexp. EOL", av[0], av[1]);
  271.             goto done;
  272.         }
  273.  
  274.  
  275.         if (ptr[j] == '"')
  276.         {
  277.             j ++;
  278.             for (n=j; ptr[j] != '"' && ptr[j]; j ++);
  279.             j -= n;
  280.  
  281.             if (ep->config.ignorecase)
  282.             n = strnicmp (Current+ep->column, &ptr[n], j);
  283.             else
  284.             n = strncmp (Current+ep->column, &ptr[n], j);
  285.         } else if (ptr[j] == '[')
  286.         {
  287.             if (any != 2 && any != 5)
  288.             {
  289.             error ("%s:\nBad conditional `%s':\ncompare with [] must be '=' or '<>'", av[0], av[1]);
  290.             goto done;
  291.             }
  292.  
  293.             j ++;
  294.             cc = Current[ep->column];
  295.  
  296.             for (n=j; ptr[j] != ']' && ptr[j]; j ++)
  297.             {
  298.             if (ptr[j] == '\\') j ++;
  299.             else if (ptr[j+1] == '-')
  300.             {
  301.                 if (!ptr[j+2] || ptr[j+2] == ']')
  302.                 {
  303.                 error ("%s:\nBad conditional `%s':\nString ended too early", av[0], av[1]);
  304.                 goto done;
  305.                 }
  306.  
  307.                 if (cc >= ptr[j] && cc <= ptr[j+2])
  308.                 {
  309.                 cc = ptr[j];
  310.                 break;
  311.                 }
  312.  
  313.                 j += 3;
  314.                 continue;
  315.             }
  316.  
  317.             if (cc == ptr[j]) break;
  318.             }
  319.  
  320.             istrue = (cc==ptr[j] && any==2) || (cc!=ptr[j] && any==5);
  321.  
  322.             break;
  323.         } else if (isdigit(ptr[j]) || ptr[j] == '+' || ptr[j] == '-')
  324.         {
  325.             n = i - atoi((char *)ptr+j);
  326.         } else
  327.         {
  328.             error ("%s:\nUnknown conditional `%s'", av[0], av[1]);
  329.             goto done;
  330.         }
  331.  
  332.         istrue = (any&1 && n<0) || (any&2 && !n) || (any&4 && n>0);
  333.         }
  334.     break;
  335.  
  336.     case 't':
  337.         if (cx == 'r')
  338.         istrue = 1;
  339.         else
  340.         istrue = ep->line == 0;
  341.     break;
  342.  
  343.     case 'b':
  344.         if (cx == 'l')
  345.         istrue = block_ok ();
  346.         else istrue = ep->line == ep->lines-1;
  347.     break;
  348.  
  349.     case 'l':
  350.         istrue = ep->column == 0;
  351.     break;
  352.  
  353.     case 'r':
  354.         istrue = ep->column == Clen;
  355.     break;
  356.  
  357.     case 'm':
  358.         text_sync ();
  359.         istrue = ep->modified != 0;
  360.     break;
  361.  
  362.     case 'e':
  363.         istrue = globalflags.Comlinemode != 0;
  364.     break;
  365.  
  366.     case 'i':
  367.         istrue = ep->config.insertmode != 0;
  368.     break;
  369.  
  370.     case 'c':
  371.         cc = Current[ep->column];
  372.  
  373.         switch(cx)
  374.         {
  375.         case 'b':
  376.             istrue = is_inblock (ep->line, -1) != 0;
  377.         break;
  378.  
  379.         case 'l':
  380.             istrue = islower (cc);
  381.         break;
  382.  
  383.         case 'u':
  384.             istrue = isupper (cc);
  385.         break;
  386.  
  387.         case 'a':
  388.             istrue = isalnum (cc);
  389.         break;
  390.  
  391.         case 'n':
  392.             istrue = isdigit (cc);
  393.         break;
  394.  
  395.         default:        /* c[<=>]#  */
  396.             i = Current[ep->column];
  397.             goto conditional;
  398.         break;
  399.         }
  400.     break;
  401.  
  402.     case 's':       /* SELNEXT/SELPREV */
  403.         switch (tolower (ptr[3]))
  404.         {
  405.         case 'n':
  406.             if (GetSucc ((struct Node *)Ep))
  407.             istrue = 1;
  408.         break;
  409.  
  410.         case 'p':
  411.             if (GetPred ((struct Node *)Ep))
  412.             istrue = 1;
  413.         break;
  414.         }
  415.     break;
  416.  
  417.     case 'g':                       /* PATCH_NULL: */
  418.         if (is_number(ptr+1))
  419.         {
  420.         cn = atoi(ptr+1);
  421.         c  = '0';
  422.         } /* if */
  423.     /* fall-through */
  424.  
  425.     default:
  426.         if (isdigit (c))
  427.         istrue = do_toggle(cn) != 0;
  428.         else
  429.         {
  430.         error ("%s:\nBad condition\n`%s'", av[0], av[1]);
  431.         }
  432.  
  433.     break;
  434.     }
  435.  
  436.     istrue ^= notop;
  437.  
  438.     if (istrue)
  439.     {
  440.     strcpy((char *)buf2, (char *)buf1); /* could be executed multiple
  441.                            times */
  442.     if (do_command((char *)buf2) == 0)
  443.         goto done;
  444.  
  445.     if (iswhile && !globalflags.Abortcommand)
  446.     {
  447.  
  448.         if (breakcheck())
  449.         {
  450.         globalflags.Abortcommand = 1;
  451.         } else if (LoopCont)
  452.         {
  453.         LoopCont = 0;        /* PATCH_NULL [14 Feb 1993] : func <-> ass */
  454.         goto loop;
  455.         } else if (LoopBreak)
  456.         {
  457.         LoopBreak = 0;        /* PATCH_NULL [14 Feb 1993] : func <-> ass */
  458.         }
  459.         else
  460.         goto loop;
  461.     }
  462.     } else
  463.     {
  464.     if (haselse)
  465.     {       /* only executed once */
  466.         strcpy((char *)buf2, (char *)av[3]);
  467.         do_command((char *)buf2);
  468.     }
  469.     }
  470.  
  471. done:
  472.     free(buf1);
  473.     free(buf2);
  474. } /* do_if */
  475.  
  476.  
  477. /*
  478.  * repeat X command
  479.  *
  480.  * (if X is not a number it can be abbr. with 2 chars)
  481.  *
  482.  * X =    N     -number of repeats
  483.  *    line  -current line # (lines begin at 1)
  484.  *    lbot  -#lines to the bottom, inc. current
  485.  *    cleft -column # (columns begin at 0)
  486.  *        (thus is also chars to the left)
  487.  *    cright-#chars to eol, including current char
  488.  *    tr    -#char positions to get to next tab stop
  489.  *    tl    -#char positions to get to next backtab stop
  490.  */
  491.  
  492. #define SC(a,b) ((a)<<8|(b))
  493.  
  494. void do_repeat (void)
  495. {
  496.     ubyte *ptr = av[1];
  497.     unsigned long n;
  498.     char *buf1, *buf2;
  499.  
  500.     if (!(buf1 = AllocMem (MAXLINELEN*2, 0)) )
  501.     {
  502.     globalflags.Abortcommand = 1;
  503.     return;
  504.     }
  505.  
  506.     buf2 = buf1 + MAXLINELEN;
  507.  
  508.     breakreset ();
  509.     strcpy (buf1, av[2]);
  510.  
  511.     switch (SC(ptr[0],ptr[1]))
  512.     {
  513.     case SC('l','i'):
  514.         n = text_lineno ();
  515.         break;
  516.  
  517.     case SC('l','b'):
  518.         n = text_lines () - text_lineno () + 1;
  519.         break;
  520.  
  521.     case SC('c','l'):
  522.         n = text_colno ();
  523.         break;
  524.  
  525.     case SC('c','r'):
  526.         n = text_cols () - text_colno ();
  527.         break;
  528.  
  529.     case SC('t','r'):
  530.         n = text_tabsize () - (text_colno () % text_tabsize ());
  531.         break;
  532.  
  533.     case SC('t','l'):
  534.         n = text_colno () % text_tabsize ();
  535.  
  536.         if (n == 0)
  537.         n = text_tabsize ();
  538.  
  539.         break;
  540.     default:
  541.         n = atoi (av[1]);
  542.         break;
  543.     }
  544.  
  545.     while (n > 0)
  546.     {
  547.     strcpy(buf2, buf1);
  548.  
  549.     if (do_command (buf2) == 0 || breakcheck ())
  550.     {
  551.         globalflags.Abortcommand = 1;
  552.         break;
  553.     }
  554.     if (LoopBreak)
  555.     {
  556.         LoopBreak = 0;        /* PATCH_NULL [14 Feb 1993] : func <-> ass */
  557.         break;
  558.     } else if (LoopCont)
  559.     {
  560.         LoopCont = 0;        /* PATCH_NULL [14 Feb 1993] : func <-> ass */
  561.     } /* if */
  562.  
  563.     --n;
  564.     }
  565.  
  566.     FreeMem (buf1, MAXLINELEN*2);
  567. } /* do_repeat */
  568.  
  569.  
  570. /*
  571.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  572.  */
  573.  
  574. ubyte bit[] =
  575. {
  576.     0x01, 0x02, 0x04, 0x08,
  577.     0x10, 0x20, 0x40, 0x80
  578. };
  579.  
  580. int do_toggle (int n)
  581. {
  582.     extern ubyte tg[MAXTOGGLE/8];
  583.     int i;
  584.  
  585.     if (n >= 0)
  586.     {
  587.     if (n >= MAXTOGGLE)
  588.         return(0);
  589.  
  590. /*printf ("Pos %d (%d/%d) %02x\n", n, n/8, n&7, tg[n/8]);*/
  591.  
  592.     return(tg[n/8] & bit[n&7]);
  593.     }
  594.  
  595.     i = atoi((char *)av[1]);
  596.  
  597.     n = i/8;
  598.     i &= 7;
  599.  
  600.     if (i >= 0 && i < MAXTOGGLE)
  601.     {
  602.     switch(av[0][0])
  603.     {
  604.         case 't':
  605.         tg[n] ^= bit[i];
  606.         break;
  607.         case 's':
  608.         tg[n] |= bit[i];
  609.         break;
  610.         case 'r':
  611.         tg[n] &= ~bit[i];
  612.         break;
  613.     }
  614.     }
  615.  
  616.     return (0);
  617. } /* do_toggle */
  618.  
  619.  
  620.  
  621. /*
  622.  *  SCANF controlstring
  623.  *
  624.  *  The C scanf routine.  Only one variable, a string, is allowed in the
  625.  *  control string.
  626.  *
  627.  *  Modified by A. Digulla to be more useful for a text-editor.
  628.  *
  629.  *   %s and %[] are still working
  630.  *
  631.  *   Additional :     (w)ord    (l)ine    (n)umber  (b)lock   (c)har
  632.  *             (t)ext    (a)lpha   (r)emark
  633.  *
  634.  *   w - get word
  635.  *   l - get line with EVERYTHING
  636.  *   b - get all that fits into isalphanum()
  637.  *   c - get single char
  638.  *   t - like line, but without preceding and trailing spaces
  639.  *   a - all that fits into isalpha()
  640.  *   r - get c-style comment
  641.  *
  642.  *   if you precede a '+' to any of these, SCANF will start at the beginning
  643.  *   to the left
  644.  */
  645.  
  646. void do_scanf (void)
  647. {
  648.     ubyte buf[MAXLINELEN], *ptr, *bptr;
  649.     SHORT t;
  650.     BOOL left;
  651.  
  652.     buf[0] = 0;
  653.     ptr = av[1];
  654.  
  655.     if (*ptr == '%')
  656.     {
  657.       ptr ++;
  658.       if (*ptr == 's' || *ptr == '[')
  659.       {
  660.            if (*ptr == 's')
  661.            {
  662.             ptr ++;
  663.             *ptr = 0;       /* Make sure there is nothing else */
  664.            } else
  665.            {
  666.             ptr ++;
  667.             if (*ptr == '~') *ptr = '^';
  668.  
  669.             while (*ptr != ']') ptr ++;
  670.             ptr ++;
  671.             *ptr = 0;       /* dito */
  672.            } /* if (*ptr == 's') */
  673.  
  674.            sscanf(Current+Ep->column,av[1],buf);
  675.       } else
  676.       {
  677.            *buf = 0;
  678.       } /* if (*ptr == 's' && *ptr == '[') */
  679.     } else
  680.     {
  681.       if (*ptr == '+')
  682.       {
  683.            left = TRUE;
  684.            ptr ++;
  685.       } else
  686.            left = FALSE;
  687.  
  688.       Clen = strlen ((char *)Current);
  689.  
  690.       switch (*ptr)
  691.       {
  692.            case ('w') :
  693.            {
  694.             t = Ep->column;
  695.  
  696.             if (t > Clen)
  697.             {
  698.              buf[0] = 0;
  699.              break;
  700.             }
  701.  
  702.             ptr = Current+t;
  703.  
  704.             if (left)
  705.             {
  706.              while (t && *ptr != ' ')
  707.              {
  708.                   ptr --;
  709.                   t --;
  710.              }
  711.             }
  712.  
  713.             while (*ptr == ' ' && t < Clen)
  714.             {
  715.              ptr ++;
  716.              t ++;
  717.             }
  718.  
  719.             if (t == Clen)
  720.             {
  721.              buf[0] = 0;
  722.              break;
  723.             }
  724.  
  725.             bptr = buf;
  726.  
  727.             while (*ptr != ' ' && *ptr)
  728.              *bptr++ = *ptr++;
  729.  
  730.             *bptr = 0;
  731.            break; } /* case ('w') */
  732.  
  733.            case ('l') :
  734.            {
  735.             if (left)
  736.             {
  737.              strncpy ((char *)buf, (char *)Current, Clen);
  738.              buf[Clen] = 0;
  739.             } else
  740.             {
  741.              strncpy ((char *)buf, (char *)Current+Ep->column,
  742.                  Clen-Ep->column);
  743.              buf[Clen - Ep->column] = 0;
  744.             }
  745.  
  746.            break; } /* case ('l') */
  747.  
  748.            case ('n') :
  749.            {
  750.             t = Ep->column;
  751.  
  752.             if (t > Clen)
  753.             {
  754.              buf[0] = 0;
  755.              break;
  756.             }
  757.  
  758.             ptr = Current+t;
  759.  
  760.             if (left)
  761.             {
  762.              while (t && isdigit(*ptr))
  763.              {
  764.                   ptr --;
  765.                   t --;
  766.              }
  767.  
  768.              if (t)
  769.              {
  770.                   ptr ++;
  771.                   t ++;
  772.              }
  773.             }
  774.  
  775.             while (*ptr == ' ' && t < Clen)
  776.             {
  777.              ptr ++;
  778.              t ++;
  779.             }
  780.  
  781.             if (t == Clen)
  782.             {
  783.              buf[0] = 0;
  784.              break;
  785.             }
  786.  
  787.             bptr = buf;
  788.  
  789.             while (isdigit(*ptr))
  790.              *bptr++ = *ptr++;
  791.  
  792.             *bptr = 0;
  793.  
  794.            break; } /* case ('n') */
  795.  
  796.            case ('b') :
  797.            {
  798.             t = Ep->column;
  799.  
  800.             if (t > Clen)
  801.             {
  802.              buf[0] = 0;
  803.              break;
  804.             }
  805.  
  806.             ptr = Current+t;
  807.  
  808.             if (left)
  809.             {
  810.              while (t && isalnum(*ptr))
  811.              {
  812.                   ptr --;
  813.                   t --;
  814.              }
  815.  
  816.              if (t)
  817.              {
  818.                   ptr ++;
  819.                   t ++;
  820.              }
  821.             }
  822.  
  823.             while (*ptr == ' ' && t < Clen)
  824.             {
  825.              ptr ++;
  826.              t ++;
  827.             }
  828.  
  829.             if (t == Clen)
  830.             {
  831.              buf[0] = 0;
  832.              break;
  833.             }
  834.  
  835.             bptr = buf;
  836.  
  837.             while (isalnum(*ptr))
  838.              *bptr++ = *ptr++;
  839.  
  840.             *bptr = 0;
  841.  
  842.            break; } /* case ('b') */
  843.  
  844.            case ('c') :
  845.            {
  846.             *buf = *(Current+Ep->column);
  847.             buf[1] = 0;
  848.  
  849.            break; } /* case ('c') */
  850.  
  851.            case ('t') :
  852.            {
  853.             if (left)
  854.             {
  855.              ptr = Current;
  856.              t = 0;
  857.             } else
  858.             {
  859.              t = Ep->column;
  860.              ptr = Current+t;
  861.             }
  862.  
  863.             if (t >= Clen || Clen == 0)
  864.             {
  865.              buf[0] = 0;
  866.              break;
  867.             }
  868.  
  869.             while (*ptr == ' ')
  870.             {
  871.              ptr ++;
  872.              t ++;
  873.             }
  874.  
  875.             if (t >= Clen)
  876.             {
  877.              buf[0] = 0;
  878.              break;
  879.             }
  880.  
  881.             strncpy ((char *)buf, (char *)ptr, Clen-t);
  882.  
  883.             ptr = buf + Clen - t - 1;
  884.  
  885.             while (*ptr == ' ')
  886.              ptr --;
  887.  
  888.             ptr[1] = 0;
  889.  
  890.            break; } /* case ('t') */
  891.  
  892.            case ('a') :
  893.            {
  894.             t = Ep->column;
  895.             ptr = Current+t;
  896.  
  897.             if (left)
  898.             {
  899.              while (isalpha(*ptr) && t)
  900.              {
  901.                   ptr --;
  902.                   t --;
  903.              }
  904.  
  905.              if (t)
  906.              {
  907.                   ptr ++;
  908.                   t ++;
  909.              }
  910.             }
  911.  
  912.             bptr = buf;
  913.  
  914.             while (isalpha(*ptr))
  915.              *bptr++ = *ptr ++;
  916.  
  917.             *bptr = 0;
  918.  
  919.            break; } /* case ('a') */
  920.  
  921.            case ('r') :
  922.            {
  923.             t = Ep->column;
  924.             ptr = Current+t;
  925.  
  926.             if (left)
  927.             {
  928.              while (t)
  929.              {
  930.                   if (*ptr == '*' && *(ptr-1) == '/')
  931.                   {
  932.                    ptr ++;
  933.                    break;
  934.                   }
  935.  
  936.                   t --;
  937.                   ptr --;
  938.              }
  939.  
  940.              if (!t)
  941.              {
  942.                   *buf = 0;
  943.                   break;
  944.              } else
  945.              {
  946.                   t ++;
  947.                   ptr ++;
  948.              }
  949.             }
  950.  
  951.             if (t > Clen)
  952.             {
  953.              *buf = 0;
  954.              break;
  955.             }
  956.  
  957.             bptr = buf;
  958.  
  959.             while (t < Clen)
  960.             {
  961.              if (*ptr == '*' && ptr[1] == '/')
  962.              {
  963.                   bptr --;
  964.                   break;
  965.              }
  966.  
  967.              *bptr++ = *ptr ++;
  968.              t ++;
  969.             }
  970.  
  971.             *bptr = 0;
  972.  
  973.            break; } /* case ('r') */
  974.  
  975.       } /* switch (*ptr) */
  976.     } /* if (*ptr == '%') */
  977.  
  978.     if (String)
  979.     free (String);
  980.  
  981.     if (String = (char *)malloc (strlen ((char *)buf)+1))
  982.     {
  983.     strcpy ((char *)String, (char *)buf);
  984.  
  985.     title (String);
  986.     }
  987. } /* do_scanf */
  988.  
  989.  
  990. /*****************************************************************************
  991.  
  992.     NAME
  993.     do_push
  994.  
  995.     PARAMETER
  996.     item
  997.  
  998.     DESCRIPTION
  999.     Pushes an item on the internal stack.
  1000.  
  1001. ******************************************************************************/
  1002.  
  1003. void do_push (void)
  1004. {
  1005.     if (ItemStackDepth == MAX_STACK_SIZE)
  1006.     {
  1007.     struct Item * stack;
  1008.  
  1009.     if (stack = AllocMem (sizeof(struct Item) * (MAX_STACK_SIZE + 32), 0))
  1010.     {
  1011.         if (MAX_STACK_SIZE)
  1012.         movmem (ItemStack, stack, sizeof(struct Item)*MAX_STACK_SIZE);
  1013.  
  1014.         MAX_STACK_SIZE += 32;
  1015.         ItemStack = stack;
  1016.     } else
  1017.     {
  1018.         error ("push:\nCannot push %s:\nStack full", av[1]);
  1019.         return;
  1020.     }
  1021.     }
  1022.  
  1023.     switch (ItemStack[ItemStackDepth].type = identify_item (av[1]))
  1024.     {
  1025.     case _IT_POS:
  1026.     {
  1027.         struct TextMarker * pos;
  1028.  
  1029.         if (pos = malloc (sizeof(struct TextMarker)))
  1030.         {
  1031.         pos->ep     = Ep;
  1032.         pos->line   = Ep->line;
  1033.         pos->column = Ep->column;
  1034.  
  1035.         ItemStack[ItemStackDepth].value = (ULONG)pos;
  1036.         ItemStack[ItemStackDepth].size    = 3;
  1037.         } else
  1038.         {
  1039. out_of_memory:
  1040.         title ("push: Out of memory error");
  1041.         globalflags.Abortcommand = 1;
  1042.         return;
  1043.         }
  1044.     } break;
  1045.  
  1046.     case _IT_MODIFIED:
  1047.         ItemStack[ItemStackDepth].value = Ep->modified;
  1048.         ItemStack[ItemStackDepth].size  = 1;
  1049.     break;
  1050.  
  1051.     case _IT_ICONMODE:
  1052.         ItemStack[ItemStackDepth].value = Ep->iconmode;
  1053.         ItemStack[ItemStackDepth].size  = 1;
  1054.     break;
  1055.  
  1056.     case _IT_TABSTOP:
  1057.         ItemStack[ItemStackDepth].value = Ep->config.tabstop;
  1058.         ItemStack[ItemStackDepth].size  = 1;
  1059.     break;
  1060.  
  1061.     case _IT_MARGIN:
  1062.         ItemStack[ItemStackDepth].value = Ep->config.margin;
  1063.         ItemStack[ItemStackDepth].size  = 1;
  1064.     break;
  1065.  
  1066.     case _IT_INSERTMODE:
  1067.         ItemStack[ItemStackDepth].value = Ep->config.insertmode;
  1068.         ItemStack[ItemStackDepth].size  = 1;
  1069.     break;
  1070.  
  1071.     case _IT_IGNORECASE:
  1072.         ItemStack[ItemStackDepth].value = Ep->config.ignorecase;
  1073.         ItemStack[ItemStackDepth].size  = 1;
  1074.     break;
  1075.  
  1076.     case _IT_WORDWRAP:
  1077.         ItemStack[ItemStackDepth].value = Ep->config.wordwrap;
  1078.         ItemStack[ItemStackDepth].size  = 1;
  1079.     break;
  1080.  
  1081.     case _IT_WWCOL:
  1082.         ItemStack[ItemStackDepth].value = Ep->config.wwcol;
  1083.         ItemStack[ItemStackDepth].size  = 1;
  1084.     break;
  1085.  
  1086.     case _IT_SAVETABS:
  1087.         ItemStack[ItemStackDepth].value = globalflags.Savetabs;
  1088.         ItemStack[ItemStackDepth].size  = 1;
  1089.     break;
  1090.  
  1091.     case _IT_ED:
  1092.         ItemStack[ItemStackDepth].value = (ULONG)Ep;
  1093.         ItemStack[ItemStackDepth].size  = 2;
  1094.     break;
  1095.  
  1096.     case _IT_WINDOW:
  1097.     {
  1098.         USHORT * array;
  1099.  
  1100.         if (array = malloc (4*sizeof(USHORT)))
  1101.         {
  1102.         if (!Ep->iconmode)
  1103.         {
  1104.             array[0] = Ep->config.winx;
  1105.             array[1] = Ep->config.winy;
  1106.             array[2] = Ep->config.winwidth;
  1107.             array[3] = Ep->config.winheight;
  1108.         } else
  1109.         {
  1110.             array[0] = Ep->win->LeftEdge;
  1111.             array[1] = Ep->win->TopEdge;
  1112.             array[2] = Ep->win->Width;
  1113.             array[3] = Ep->win->Height;
  1114.         }
  1115.  
  1116.         ItemStack[ItemStackDepth].value = (ULONG)array;
  1117.         ItemStack[ItemStackDepth].size    = 3;
  1118.         } else
  1119.         {
  1120.         goto out_of_memory;
  1121.         }
  1122.     } break;
  1123.  
  1124.     case _IT_ICON:
  1125.     {
  1126.         USHORT * array;
  1127.  
  1128.         if (array = malloc (2*sizeof(USHORT)))
  1129.         {
  1130.         if (Ep->iconmode)
  1131.         {
  1132.             array[0] = Ep->config.iwinx;
  1133.             array[1] = Ep->config.iwiny;
  1134.         } else
  1135.         {
  1136.             array[0] = Ep->win->LeftEdge;
  1137.             array[1] = Ep->win->TopEdge;
  1138.         }
  1139.  
  1140.         ItemStack[ItemStackDepth].value = (ULONG)array;
  1141.         ItemStack[ItemStackDepth].size    = 3;
  1142.         } else
  1143.         {
  1144.         goto out_of_memory;
  1145.         }
  1146.     } break;
  1147.  
  1148.     case _IT_PENS:
  1149.     {
  1150.         ULONG * array;
  1151.  
  1152.         if (array = malloc (5*sizeof(ULONG)))
  1153.         {
  1154.         array[0] = TEXT_FPEN;
  1155.         array[1] = TEXT_BPEN;
  1156.         array[2] = BLOCK_FPEN;
  1157.         array[3] = BLOCK_BPEN;
  1158.         array[4] = TITLE_BPEN;
  1159.  
  1160.         ItemStack[ItemStackDepth].value = (ULONG)array;
  1161.         ItemStack[ItemStackDepth].size    = 3;
  1162.         } else
  1163.         {
  1164.         goto out_of_memory;
  1165.         }
  1166.     } break;
  1167.  
  1168.     case _IT_BLOCK:
  1169.     {
  1170.         Block * block;
  1171.  
  1172.         if (block = malloc (sizeof(Block)))
  1173.         {
  1174.         movmem (&ActualBlock, block, sizeof (Block));
  1175.  
  1176.         ItemStack[ItemStackDepth].value = (ULONG)block;
  1177.         ItemStack[ItemStackDepth].size    = 3;
  1178.  
  1179.         if (!Ep->iconmode)
  1180.             text_redrawblock (0);
  1181.         } else
  1182.         {
  1183.         goto out_of_memory;
  1184.         }
  1185.     } break;
  1186.  
  1187.     default:
  1188.         error ("push:\nUnknown item\n`%s'", av[1]);
  1189.         return;
  1190.     break;
  1191.     }
  1192.  
  1193.     ItemStackDepth ++;
  1194.  
  1195. #if MYDEBUG
  1196.     if (globalflags.debug)
  1197.     D(bug("PUSH Stack %d\n", ItemStackDepth));
  1198. #endif
  1199. } /* do_push */
  1200.  
  1201.  
  1202. /*****************************************************************************
  1203.  
  1204.     NAME
  1205.     POP/PICK item
  1206.  
  1207.     PARAMETER
  1208.     item / AUTO / DISCARD
  1209.  
  1210.     DESCRIPTION
  1211.     Pops an item from the internal stack or (PICK) just get's the value
  1212.     of it without poping it from the stack.
  1213.  
  1214. ******************************************************************************/
  1215.  
  1216. void do_pop (void)
  1217. {
  1218.     ItemType type;
  1219.  
  1220.     if (ItemStackDepth == 0)
  1221.     {
  1222.     error ("push:\nCannot pop %s:\nStack empty", av[1]);
  1223.     return;
  1224.     }
  1225.  
  1226.     ItemStackDepth --;
  1227.  
  1228. #if MYDEBUG
  1229.     if (globalflags.debug)
  1230.     D(bug("POP Stack %d\n", ItemStackDepth));
  1231. #endif
  1232.  
  1233.     type = identify_item (av[1]);
  1234.  
  1235.     if (type == _IT_AUTO)
  1236.     type = ItemStack[ItemStackDepth].type;
  1237.  
  1238.     switch (type)
  1239.     {
  1240.     case _IT_POS:
  1241.         struct TextMarker * pos;
  1242.  
  1243.         if (ItemStack[ItemStackDepth].type != _IT_POS)
  1244.         error ("pop:\nCannot pop position\nto something else");
  1245.  
  1246.         pos = (struct TextMarker *)ItemStack[ItemStackDepth].value;
  1247.  
  1248.         text_sync ();
  1249.  
  1250.         text_cursor (1);
  1251.         switch_ed (pos->ep);
  1252.         text_cursor (0);
  1253.  
  1254.         if (IntuitionBase->ActiveWindow != Ep->win)
  1255.         {
  1256.         WindowToFront (Ep->win);
  1257.         ActivateWindow (Ep->win);
  1258.         }
  1259.  
  1260.         if (pos->line >= Ep->lines)
  1261.         Ep->line = Ep->lines - 1;
  1262.         else
  1263.         Ep->line = pos->line;
  1264.  
  1265.         Ep->column = pos->column;
  1266.  
  1267.         text_load ();
  1268.         text_adjust (FALSE);
  1269.     break;
  1270.  
  1271.     case _IT_MODIFIED:
  1272.         if (ItemStack[ItemStackDepth].size != 1)
  1273.         error ("pop:\nCannot pop a struct\nto modified");
  1274.  
  1275.         Ep->modified = ItemStack[ItemStackDepth].value;
  1276.     break;
  1277.  
  1278.     case _IT_ICONMODE:
  1279.         if (ItemStack[ItemStackDepth].size != 1)
  1280.         error ("pop:\nCannot pop a struct\nto iconmode");
  1281.  
  1282.         if (Ep->iconmode != ItemStack[ItemStackDepth].value)
  1283.         {
  1284.         if (ItemStack[ItemStackDepth].value)
  1285.             iconify ();
  1286.         else
  1287.             uniconify ();
  1288.         }
  1289.     break;
  1290.  
  1291.     case _IT_TABSTOP:
  1292.         if (ItemStack[ItemStackDepth].size != 1)
  1293.         error ("pop:\nCannot pop a struct\nto tabstop");
  1294.  
  1295.         Ep->config.tabstop = ItemStack[ItemStackDepth].value;
  1296.     break;
  1297.  
  1298.     case _IT_MARGIN:
  1299.         if (ItemStack[ItemStackDepth].size != 1)
  1300.         error ("pop:\nCannot pop a struct\nto margin");
  1301.  
  1302.         Ep->config.margin = ItemStack[ItemStackDepth].value;
  1303.     break;
  1304.  
  1305.     case _IT_INSERTMODE:
  1306.         if (ItemStack[ItemStackDepth].size != 1)
  1307.         error ("pop:\nCannot pop a struct\nto insertmode");
  1308.  
  1309.         Ep->config.insertmode = ItemStack[ItemStackDepth].value;
  1310.     break;
  1311.  
  1312.     case _IT_IGNORECASE:
  1313.         if (ItemStack[ItemStackDepth].size != 1)
  1314.         error ("pop:\nCannot pop a struct\nto ignorecase");
  1315.  
  1316.         Ep->config.ignorecase = ItemStack[ItemStackDepth].value;
  1317.     break;
  1318.  
  1319.     case _IT_WORDWRAP:
  1320.         if (ItemStack[ItemStackDepth].size != 1)
  1321.         error ("pop:\nCannot pop a struct\nto wordwrap");
  1322.  
  1323.         Ep->config.wordwrap = ItemStack[ItemStackDepth].value;
  1324.     break;
  1325.  
  1326.     case _IT_WWCOL:
  1327.         if (ItemStack[ItemStackDepth].size != 1)
  1328.         error ("pop:\nCannot pop a struct\nto wordwrapcolumn");
  1329.  
  1330.         Ep->config.wwcol = ItemStack[ItemStackDepth].value;
  1331.     break;
  1332.  
  1333.     case _IT_SAVETABS:
  1334.         if (ItemStack[ItemStackDepth].size != 1)
  1335.         error ("pop:\nCannot pop a struct\nto savetabs");
  1336.  
  1337.         globalflags.Savetabs = ItemStack[ItemStackDepth].value;
  1338.     break;
  1339.  
  1340.     case _IT_ED:
  1341.         if (ItemStack[ItemStackDepth].type != _IT_ED)
  1342.         error ("pop:\nCannot pop ed\nto something else");
  1343.  
  1344.         switch_ed ((ED *)ItemStack[ItemStackDepth].value);
  1345.     break;
  1346.  
  1347.     case _IT_WINDOW:
  1348.     {
  1349.         USHORT * array;
  1350.  
  1351.         if (ItemStack[ItemStackDepth].type != _IT_WINDOW)
  1352.         error ("pop:\nCannot pop window\nto something else");
  1353.  
  1354.  
  1355.         array = (USHORT *)ItemStack[ItemStackDepth].value;
  1356.  
  1357.         Ep->config.winx     = array[0];
  1358.         Ep->config.winy     = array[1];
  1359.         Ep->config.winwidth  = array[2];
  1360.         Ep->config.winheight = array[3];
  1361.  
  1362.         if (!Ep->iconmode)
  1363.         {
  1364.         MoveWindow (Ep->win, Ep->config.winx - Ep->win->LeftEdge,
  1365.                      Ep->config.winy - Ep->win->TopEdge);
  1366.         SizeWindow (Ep->win, Ep->config.winwidth  - Ep->win->Width,
  1367.                      Ep->config.winheight - Ep->win->Height);
  1368.         }
  1369.     } break;
  1370.  
  1371.     case _IT_ICON:
  1372.     {
  1373.         USHORT * array;
  1374.  
  1375.         if (ItemStack[ItemStackDepth].type != _IT_ICON)
  1376.         error ("pop:\nCannot pop icon\nto something else");
  1377.  
  1378.         Ep->config.iwinx      = array[0];
  1379.         Ep->config.iwiny      = array[1];
  1380.  
  1381.         if (Ep->iconmode)
  1382.         {
  1383.         MoveWindow (Ep->win, Ep->config.iwinx - Ep->win->LeftEdge,
  1384.                      Ep->config.iwiny - Ep->win->TopEdge);
  1385.         }
  1386.     } break;
  1387.  
  1388.     case _IT_PENS:
  1389.     {
  1390.         ULONG * array;
  1391.  
  1392.         if (ItemStack[ItemStackDepth].type != _IT_PENS)
  1393.         error ("pop:\nCannot pop pens\nto something else");
  1394.  
  1395.         array = (ULONG *)ItemStack[ItemStackDepth].value;
  1396.  
  1397.         TEXT_FPEN  = array[0];
  1398.         TEXT_BPEN  = array[1];
  1399.         BLOCK_FPEN = array[2];
  1400.         BLOCK_BPEN = array[3];
  1401.         TITLE_BPEN = array[4];
  1402.  
  1403.         if (!Ep->iconmode)
  1404.         text_redisplay ();
  1405.  
  1406.         globalflags.MForceTitle = 1;
  1407.     } break;
  1408.  
  1409.     case _IT_BLOCK:
  1410.     {
  1411.         Block * block;
  1412.  
  1413.         if (ItemStack[ItemStackDepth].type != _IT_BLOCK)
  1414.         error ("pop:\nCannot pop block\nto something else");
  1415.  
  1416.         block = (Block *) ItemStack[ItemStackDepth].value;
  1417.  
  1418.         movmem (block, &ActualBlock, sizeof (Block));
  1419.  
  1420.         if (!Ep->iconmode)
  1421.         text_redrawblock (1);
  1422.     } break;
  1423.  
  1424.     case _IT_DISCARD:
  1425.     break;
  1426.  
  1427.     default:
  1428.         error ("pop:\nUnknown item\n`%s'", av[1]);
  1429.     break;
  1430.     }
  1431.  
  1432.     /* free only, if POP. If PEEK, restore Depth */
  1433.     if (av[0][1] != 'i')
  1434.     {
  1435.     if (ItemStack[ItemStackDepth].size == 3)
  1436.         free ((void *)ItemStack[ItemStackDepth].value);
  1437.     } else
  1438.     ItemStackDepth ++;
  1439. } /* do_pop */
  1440.  
  1441.  
  1442. /*****************************************************************************
  1443.  
  1444.     NAME
  1445.     SWAP item
  1446.  
  1447.     PARAMETER
  1448.     item / AUTO / DISCARD
  1449.  
  1450.     DESCRIPTION
  1451.     This exchanges the actual item with the item on stack, ie. the
  1452.     topmost item from stack is poped and the actual item is pushed.
  1453.  
  1454. ******************************************************************************/
  1455.  
  1456. void do_swap (void)
  1457. {
  1458.     ItemType type;
  1459.     ULONG    value;
  1460.  
  1461.     if (ItemStackDepth == 0)
  1462.     {
  1463.     error ("push:\nCannot swap %s:\nStack empty", av[1]);
  1464.     return;
  1465.     }
  1466.  
  1467.     ItemStackDepth --;
  1468.  
  1469.     value = ItemStack[ItemStackDepth].value;
  1470.  
  1471. #if MYDEBUG
  1472.     if (globalflags.debug)
  1473.     D(bug("Stack %d\n", ItemStackDepth));
  1474. #endif
  1475.  
  1476.     type = identify_item (av[1]);
  1477.  
  1478.     if (type == _IT_AUTO)
  1479.     type = ItemStack[ItemStackDepth].type;
  1480.  
  1481.     switch (type)
  1482.     {
  1483.     case _IT_POS:
  1484.         struct TextMarker pos;
  1485.  
  1486.         if (ItemStack[ItemStackDepth].type != _IT_POS)
  1487.         error ("pop:\nCannot pop position\nto something else");
  1488.  
  1489.         pos.ep     = Ep;
  1490.         pos.line   = Ep->line;
  1491.         pos.column = Ep->column;
  1492.  
  1493.         swapmem ((void *)value, &pos, sizeof (struct TextMarker));
  1494.  
  1495.         text_sync ();
  1496.  
  1497.         text_cursor (1);
  1498.         switch_ed (pos.ep);
  1499.         text_cursor (0);
  1500.  
  1501.         if (IntuitionBase->ActiveWindow != Ep->win)
  1502.         {
  1503.         WindowToFront (Ep->win);
  1504.         ActivateWindow (Ep->win);
  1505.         }
  1506.  
  1507.         if (pos.line >= Ep->lines)
  1508.         Ep->line = Ep->lines - 1;
  1509.         else
  1510.         Ep->line = pos.line;
  1511.  
  1512.         Ep->column = pos.column;
  1513.  
  1514.         text_load ();
  1515.         text_adjust (FALSE);
  1516.     break;
  1517.  
  1518.     case _IT_MODIFIED:
  1519.         if (ItemStack[ItemStackDepth].size != 1)
  1520.         error ("pop:\nCannot pop a struct\nto modified");
  1521.  
  1522.         ItemStack[ItemStackDepth].value = Ep->modified;
  1523.         Ep->modified = value;
  1524.     break;
  1525.  
  1526.     case _IT_ICONMODE:
  1527.         warn ("Not yet");
  1528.     break;
  1529.  
  1530.     case _IT_TABSTOP:
  1531.         if (ItemStack[ItemStackDepth].size != 1)
  1532.         error ("pop:\nCannot pop a struct\nto tabstop");
  1533.  
  1534.         ItemStack[ItemStackDepth].value = Ep->config.tabstop;
  1535.         Ep->config.tabstop = value;
  1536.     break;
  1537.  
  1538.     case _IT_MARGIN:
  1539.         if (ItemStack[ItemStackDepth].size != 1)
  1540.         error ("pop:\nCannot pop a struct\nto margin");
  1541.  
  1542.         ItemStack[ItemStackDepth].value = Ep->config.margin;
  1543.         Ep->config.margin = value;
  1544.     break;
  1545.  
  1546.     case _IT_INSERTMODE:
  1547.         if (ItemStack[ItemStackDepth].size != 1)
  1548.         error ("pop:\nCannot pop a struct\nto insertmode");
  1549.  
  1550.         ItemStack[ItemStackDepth].value = Ep->config.insertmode;
  1551.         Ep->config.insertmode = value;
  1552.     break;
  1553.  
  1554.     case _IT_IGNORECASE:
  1555.         if (ItemStack[ItemStackDepth].size != 1)
  1556.         error ("pop:\nCannot pop a struct\nto ignorecase");
  1557.  
  1558.         ItemStack[ItemStackDepth].value = Ep->config.ignorecase;
  1559.         Ep->config.ignorecase = value;
  1560.     break;
  1561.  
  1562.     case _IT_WORDWRAP:
  1563.         if (ItemStack[ItemStackDepth].size != 1)
  1564.         error ("pop:\nCannot pop a struct\nto wordwrap");
  1565.  
  1566.         ItemStack[ItemStackDepth].value = Ep->config.wordwrap;
  1567.         Ep->config.wordwrap = value;
  1568.     break;
  1569.  
  1570.     case _IT_WWCOL:
  1571.         if (ItemStack[ItemStackDepth].size != 1)
  1572.         error ("pop:\nCannot pop a struct\nto wordwrapcolumn");
  1573.  
  1574.         ItemStack[ItemStackDepth].value = Ep->config.wwcol;
  1575.         Ep->config.wwcol = value;
  1576.     break;
  1577.  
  1578.     case _IT_SAVETABS:
  1579.         if (ItemStack[ItemStackDepth].size != 1)
  1580.         error ("pop:\nCannot pop a struct\nto savetabs");
  1581.  
  1582.         ItemStack[ItemStackDepth].value = globalflags.Savetabs;
  1583.         globalflags.Savetabs = value;
  1584.     break;
  1585.  
  1586.     case _IT_ED:
  1587.         if (ItemStack[ItemStackDepth].type != _IT_ED)
  1588.         error ("pop:\nCannot pop ed\nto something else");
  1589.  
  1590.         ItemStack[ItemStackDepth].value = Ep;
  1591.         switch_ed ((ED *)value);
  1592.     break;
  1593.  
  1594.     case _IT_WINDOW:
  1595.     {
  1596.         USHORT array[4];
  1597.  
  1598.         if (ItemStack[ItemStackDepth].type != _IT_WINDOW)
  1599.         error ("pop:\nCannot pop window\nto something else");
  1600.  
  1601.         if (!Ep->iconmode)
  1602.         {
  1603.         array[0] = Ep->config.winx;
  1604.         array[1] = Ep->config.winy;
  1605.         array[2] = Ep->config.winwidth;
  1606.         array[3] = Ep->config.winheight;
  1607.         } else
  1608.         {
  1609.         array[0] = Ep->win->LeftEdge;
  1610.         array[1] = Ep->win->TopEdge;
  1611.         array[2] = Ep->win->Width;
  1612.         array[3] = Ep->win->Height;
  1613.         }
  1614.  
  1615.         swapmem ((void *)value, array, sizeof(USHORT)*4);
  1616.  
  1617.         Ep->config.winx     = array[0];
  1618.         Ep->config.winy     = array[1];
  1619.         Ep->config.winwidth  = array[2];
  1620.         Ep->config.winheight = array[3];
  1621.  
  1622.         if (!Ep->iconmode)
  1623.         {
  1624.         MoveWindow (Ep->win, Ep->config.winx - Ep->win->LeftEdge,
  1625.                      Ep->config.winy - Ep->win->TopEdge);
  1626.         SizeWindow (Ep->win, Ep->config.winwidth  - Ep->win->Width,
  1627.                      Ep->config.winheight - Ep->win->Height);
  1628.         }
  1629.     } break;
  1630.  
  1631.     case _IT_ICON:
  1632.     {
  1633.         USHORT array[2];
  1634.  
  1635.         if (ItemStack[ItemStackDepth].type != _IT_ICON)
  1636.         error ("pop:\nCannot pop icon\nto something else");
  1637.  
  1638.         if (Ep->iconmode)
  1639.         {
  1640.         array[0] = Ep->config.iwinx;
  1641.         array[1] = Ep->config.iwiny;
  1642.         } else
  1643.         {
  1644.         array[0] = Ep->win->LeftEdge;
  1645.         array[1] = Ep->win->TopEdge;
  1646.         }
  1647.  
  1648.         swapmem ((void *)value, array, sizeof(USHORT)*2);
  1649.  
  1650.         Ep->config.iwinx      = array[0];
  1651.         Ep->config.iwiny      = array[1];
  1652.  
  1653.         if (Ep->iconmode)
  1654.         {
  1655.         MoveWindow (Ep->win, Ep->config.iwinx - Ep->win->LeftEdge,
  1656.                      Ep->config.iwiny - Ep->win->TopEdge);
  1657.         }
  1658.     } break;
  1659.  
  1660.     case _IT_PENS:
  1661.     {
  1662.         ULONG array[5];
  1663.  
  1664.         if (ItemStack[ItemStackDepth].type != _IT_PENS)
  1665.         error ("pop:\nCannot pop pens\nto something else");
  1666.  
  1667.         array[0] = TEXT_FPEN;
  1668.         array[1] = TEXT_BPEN;
  1669.         array[2] = BLOCK_FPEN;
  1670.         array[3] = BLOCK_BPEN;
  1671.         array[4] = TITLE_BPEN;
  1672.  
  1673.         swapmem ((void *)value, array, sizeof(ULONG)*5);
  1674.  
  1675.         TEXT_FPEN  = array[0];
  1676.         TEXT_BPEN  = array[1];
  1677.         BLOCK_FPEN = array[2];
  1678.         BLOCK_BPEN = array[3];
  1679.         TITLE_BPEN = array[4];
  1680.  
  1681.         if (!Ep->iconmode)
  1682.         text_redisplay ();
  1683.  
  1684.         globalflags.MForceTitle = 1;
  1685.     } break;
  1686.  
  1687.     case _IT_BLOCK:
  1688.     {
  1689.         Block block;
  1690.  
  1691.         if (ItemStack[ItemStackDepth].type != _IT_BLOCK)
  1692.         error ("pop:\nCannot pop block\nto something else");
  1693.  
  1694.         movmem (&ActualBlock, &block, sizeof (Block));
  1695.  
  1696.         if (!Ep->iconmode)
  1697.         text_redrawblock (0);
  1698.  
  1699.         swapmem ((void *)value, &block, sizeof (Block));
  1700.  
  1701.         movmem (&block, &ActualBlock, sizeof (Block));
  1702.  
  1703.         if (!Ep->iconmode)
  1704.         text_redrawblock (1);
  1705.     } break;
  1706.  
  1707.     default:
  1708.         error ("swap:\nUnknown item\n`%s'", av[1]);
  1709.     break;
  1710.     }
  1711.  
  1712.     ItemStackDepth ++;
  1713. } /* do_pop */
  1714.  
  1715.  
  1716. static ItemType identify_item (char * itemname)
  1717. {
  1718.     static CONST struct
  1719.     {
  1720.     char   * name;
  1721.     ItemType type;
  1722.     } items[] =
  1723.     {
  1724.     "auto",         _IT_AUTO
  1725.     "block",        _IT_BLOCK,
  1726.     "discard",      _IT_DISCARD,
  1727.     "ed",           _IT_ED,
  1728.     "icon",         _IT_ICON,
  1729.     "iconmode",     _IT_ICONMODE,
  1730.     "ignorecase",   _IT_IGNORECASE,
  1731.     "insertmode",   _IT_INSERTMODE,
  1732.     "margin",       _IT_MARGIN,
  1733.     "modified",     _IT_MODIFIED
  1734.     "pens",         _IT_PENS,
  1735.     "pos",          _IT_POS,
  1736.     "savetabs",     _IT_SAVETABS,
  1737.     "tabstop",      _IT_TABSTOP,
  1738.     "window",       _IT_WINDOW,
  1739.     "wordwrap",     _IT_WORDWRAP,
  1740.     "wwcol",        _IT_WWCOL,
  1741.     };
  1742.     short low,
  1743.       high,
  1744.       t,
  1745.       diff;
  1746.  
  1747.     low = 0;
  1748.     high = sizeof (items) / sizeof (items[0]) -1;
  1749.  
  1750.     do
  1751.     {
  1752.     t = (low + high) / 2;
  1753.  
  1754.     if (!(diff = stricmp (itemname, items[t].name)) )
  1755.         break;
  1756.     else if (diff < 0)
  1757.         high = t-1;
  1758.     else
  1759.         low = t+1;
  1760.     } while (low <= high);
  1761.  
  1762.     if (!diff)
  1763.     return (items[t].type);
  1764.  
  1765.     return (-1);
  1766. } /* identify_item */
  1767.  
  1768.  
  1769. /*****************************************************************************
  1770.  
  1771.     NAME
  1772.     check_stack
  1773.  
  1774.     PARAMETER
  1775.     ED * ep;
  1776.  
  1777.     DESCRIPTION
  1778.     Checks the stack for thing left from editor ep or if ep == NULL
  1779.     cleans the full stack.
  1780.  
  1781. ******************************************************************************/
  1782.  
  1783. void check_stack (ED * ep)
  1784. {
  1785.     short i, j;
  1786.  
  1787.     if (ep)
  1788.     {
  1789.     for (i=j=0; i<ItemStackDepth; i ++)
  1790.     {
  1791.         if (!((ItemStack[i].type == _IT_ED ||
  1792.             ItemStack[i].type == _IT_POS ||
  1793.             ItemStack[i].type == _IT_BLOCK) &&
  1794.             ep == *(ED **)ItemStack[i].value) )
  1795.             {
  1796.         if (i != j)
  1797.         {
  1798.             ItemStack[j] = ItemStack[i];
  1799.         }
  1800.  
  1801.         j ++;
  1802.         }
  1803.     }
  1804.  
  1805.     ItemStackDepth = j;
  1806.     } else
  1807.     {
  1808.     for (i=0; i<ItemStackDepth; i ++)
  1809.     {
  1810.         if (ItemStack[i].size == 3)
  1811.         free ((void *)ItemStack[i].value);
  1812.     }
  1813.  
  1814.     ItemStackDepth = 0;
  1815.     }
  1816. } /* check_stack */
  1817.  
  1818.  
  1819. /******************************************************************************
  1820. *****  ENDE cmd.c
  1821. ******************************************************************************/
  1822.