home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Src / cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-05  |  37.2 KB  |  1,847 lines

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