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

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     $Id: cursor.c 1.3 1994/09/09 12:31:30 digulla Exp digulla $
  5.  
  6.     DESCRIPTION
  7.     All routines that only move the cursor.
  8.  
  9.     HISTORY
  10.     04. Oct 1992    ada created
  11.     30-11-94 b_noll some changes to SLINE behaviour ...
  12.     $Log: cursor.c $
  13.  * Revision 1.3  1994/09/09  12:31:30  digulla
  14.  * added new style Prototypes, DEFCMD and DEFHELP
  15.  *
  16.  * Revision 1.2  1994/08/19  14:08:28  digulla
  17.  * fixed SetWrMsk()
  18.  * removed dead assignments
  19.  *
  20.  * Revision 1.1  1994/08/09  15:55:36  digulla
  21.  * Initial revision
  22.  *
  23.  
  24. ******************************************************************************/
  25.  
  26. /**************************************
  27.         Includes
  28. **************************************/
  29. #include <defs.h>
  30.  
  31.  
  32. /**************************************
  33.         Globale Variable
  34. **************************************/
  35.  
  36.  
  37. /**************************************
  38.       Interne Defines & Strukturen
  39. **************************************/
  40.  
  41.  
  42. /**************************************
  43.         Interne Variable
  44. **************************************/
  45. static struct TextMarker marker[PINGDEPTH];
  46.  
  47. /* TODO: replace define by function for infinite history */
  48.  
  49. #define MaxHistoLines        40
  50.  
  51. /* HistoBuff is filled [0..NumHistoLines-1], NumHistoLines is in
  52.    [0..MaxHistoLines], HistoLine is in [0..NumHistoLines]. If NumHistoLines
  53.    is 0, then the HistoryBuffer is empty. */
  54.  
  55. Prototype char    * HistoBuff[];
  56. Prototype WORD      NumHistoLines;
  57. Prototype WORD      HistoLine;
  58.  
  59. char * HistoBuff[MaxHistoLines];
  60. WORD   NumHistoLines;
  61. WORD   HistoLine;
  62.  
  63.  
  64. /**************************************
  65.        Interne Prototypes
  66. **************************************/
  67.  
  68.  
  69. /*DEFHELP #cmd movement UP -cursor up. If in commandline, move to previous line of commandline-history */
  70.  
  71. DEFUSERCMD("up", 0, CF_VWM|CF_COK, void, do_up, (void),)
  72. {
  73.     ED * ep = Ep;
  74.  
  75.     if (!GETF_COMLINEMODE(ep))
  76.     {
  77.     if (ep->line)
  78.     {
  79.  
  80.         text_sync ();
  81.         ep->line --;
  82.         text_load ();
  83.  
  84.         if (Ep->line < Ep->topline)
  85.         ScrollAndUpdate (0, -1);
  86.     } else
  87.     {
  88.         SETF_ABORTCOMMAND(ep,1);
  89.     }
  90.     } else
  91.     {
  92.     if (HistoLine)
  93.     {
  94.         HistoLine --;
  95.  
  96.         strcpy (Current, HistoBuff[HistoLine]);
  97.  
  98.         ep->column = Clen = strlen (Current);
  99.         ep->topcolumn = ep->column - Columns + 1;
  100.  
  101.         if (ep->topcolumn < 0)
  102.         ep->topcolumn = 0;
  103.  
  104.         text_redisplaycurrline ();
  105.     }
  106.     }
  107. } /* do_up */
  108.  
  109.  
  110. /*DEFHELP #cmd movement SCROLLDOWN - Scroll down without moving cursor */
  111.  
  112. DEFUSERCMD("scrolldown", 0, CF_VWM, void, do_scrolldown, (void),)
  113. {
  114.     ED * ep = Ep;
  115.  
  116.     if (ep->topline + Lines < ep->lines)
  117.     {
  118.     text_sync ();
  119.  
  120.     ep->line ++;
  121.  
  122.     text_load ();
  123.  
  124.     ScrollAndUpdate (0, 1);
  125.     } else
  126.     SETF_ABORTCOMMAND(Ep,1);
  127. } /* do_scrolldown */
  128.  
  129.  
  130. /*DEFHELP #cmd movement SCROLLUP - Scroll up without moving cursor */
  131.  
  132. DEFUSERCMD("scrollup", 0, CF_VWM, void, do_scrollup, (void),)
  133. {
  134.     ED * ep = Ep;
  135.  
  136.     if (ep->topline)
  137.     {
  138.     text_sync ();
  139.  
  140.     ep->line --;
  141.  
  142.     text_load ();
  143.  
  144.     ScrollAndUpdate (0, -1);
  145.     } else
  146.     SETF_ABORTCOMMAND(Ep,1);
  147. } /* do_scrollup */
  148.  
  149.  
  150. /*DEFHELP #cmd movement DOWN - cursor down. If in commandline move to next line of commandline-history */
  151.  
  152. DEFUSERCMD("down", 0, CF_VWM|CF_COK, void, do_down, (void),)
  153. {
  154.     ED * ep = Ep;
  155.  
  156.     if (!GETF_COMLINEMODE(Ep))
  157.     {
  158.     if (ep->line + 1 < ep->lines)
  159.     {
  160.         text_sync ();
  161.         ep->line ++;
  162.         text_load ();
  163.  
  164.         if (ep->line - ep->topline >= Lines)
  165.         ScrollAndUpdate (0, 1);
  166.     } else
  167.         SETF_ABORTCOMMAND(Ep,1);
  168.     } else
  169.     { /* Comlinemode */
  170.     if (HistoLine < NumHistoLines)
  171.     {
  172.         HistoLine ++;
  173.  
  174.         if (HistoLine != NumHistoLines)
  175.         strcpy (Current, HistoBuff[HistoLine]);
  176.         else
  177.         *Current = 0;
  178.  
  179.         ep->column = Clen = strlen (Current);
  180.         ep->topcolumn = ep->column - Columns + 1;
  181.  
  182.         if (ep->topcolumn < 0)
  183.         ep->topcolumn = 0;
  184.  
  185.         text_redisplaycurrline ();
  186.     }
  187.     } /* if (!Comlinemode) */
  188. } /* do_down */
  189.  
  190.  
  191. /*DEFHELP #cmd movement PAGEDOWN - pagedown a partial page (see PAGESET) */
  192. /*DEFHELP #cmd movement PAGELEFT - page to the left as requested by StyleGuide. */
  193. /*DEFHELP #cmd movement PAGERIGHT - dito to the right */
  194. /*DEFHELP #cmd movement PAGEUP - pageup a partial page (see PAGESET) */
  195. /*DEFHELP #cmd prefs PAGESET n -@{B}n@{UB} PERCENT (0 to 100). page step size relative to the current number of rows in the window. */
  196.  
  197. DEFUSERCMD("pagedown",  0, CF_VWM,        void, do_page, (void),;)
  198. DEFUSERCMD("pageleft",  0, CF_VWM,        void, do_page, (void),;)
  199. DEFUSERCMD("pageright", 0, CF_VWM,        void, do_page, (void),;)
  200. DEFUSERCMD("pageup",    0, CF_VWM,        void, do_page, (void),;)
  201. DEFUSERCMD("pageset",   1, CF_VWM|CF_ICO, void, do_page, (void),)
  202. {
  203.     ED     * ep = Ep;
  204.     Column nx = 0, t;
  205.     Line   ny = 0;
  206.  
  207.     switch(av[0][4])
  208.     {
  209.     case 'u':
  210.         if (!ep->topline && !ep->line) return;
  211.  
  212.         if (!GETF_NICEPAGING(ep) && ep->line != ep->topline)
  213.         {
  214.         text_sync ();
  215.  
  216.         ep->line = ep->topline;
  217.  
  218.         text_load ();
  219.         return;
  220.         }
  221.  
  222.         ny = Lines * PageJump / 100;
  223.  
  224.         text_sync ();
  225.  
  226.         ep->line -= ny;
  227.  
  228.         if (ep->line < 0)
  229.         ep-> line = 0;
  230.  
  231.         text_load ();
  232.  
  233.         if (ep->topline < ny)
  234.         ny = -ep->topline;
  235.         else
  236.         ny = -ny;
  237.  
  238.         break;
  239.  
  240.     case 'd':
  241.         if (ep->topline + Lines >= ep->lines && ep->line == ep->lines -1)
  242.         return;
  243.  
  244.         text_sync ();
  245.  
  246.         if (!GETF_NICEPAGING(ep) && ep->line != ep->topline + Lines -1)
  247.         ep->line = ep->topline + Lines -1;
  248.         else
  249.         {
  250.         ny = Lines * PageJump / 100;
  251.  
  252.         ep->line += ny;
  253.  
  254.         /* don't advance further if the last line is already visible */
  255.         if (ep->topline+Lines >= ep->lines)
  256.             ny = 0;
  257.         }
  258.  
  259.         if (ep->line >= ep->lines)
  260.         ep->line = ep->lines - 1;
  261.  
  262.         text_load ();
  263.  
  264.         break;
  265.  
  266.     case 'l':
  267.         if (!ep->topcolumn && !ep->column) return;
  268.  
  269.         t = firstns (Current);
  270.  
  271.         if (!GETF_NICEPAGING(ep))
  272.         {
  273.         if (ep->column != ep->topcolumn)
  274.         {
  275.             if (t > ep->topcolumn && ep->column != t)
  276.             ep->column = t;
  277.             else
  278.             ep->column = ep->topcolumn;
  279.  
  280.             text_sync ();
  281.             return;
  282.         }
  283.         }
  284.         else
  285.         {
  286.         if (t > ep->topcolumn && ep->column != t)
  287.         {
  288.             ep->column = t;
  289.  
  290.             text_sync ();
  291.             return;
  292.         }
  293.         else if (!t && !ep->topcolumn)
  294.         {
  295.             if (ep->column)
  296.             {
  297.             ep->column = 0;
  298.             text_sync ();
  299.             }
  300.  
  301.             return;
  302.         }
  303.         }
  304.  
  305.         nx = Columns * PageJump / 100;
  306.  
  307.         if (ep->topcolumn < nx)
  308.         nx = ep->topcolumn;
  309.  
  310.         if (t < ep->column && t > ep->column - nx)
  311.         ep->column = t;
  312.         else
  313.         {
  314.         if (t == ep->column && !ep->topcolumn)
  315.             ep->column = 0;
  316.         else
  317.             ep->column -= nx;
  318.         }
  319.  
  320.         nx = -nx;
  321.  
  322.         break;
  323.  
  324.     case 'r':
  325.         if (ep->topcolumn + Columns >= MAXLINELEN &&
  326.             ep->column == MAXLINELEN-1)
  327.         return;
  328.  
  329.         t = LINELEN(ep,ep->line);
  330.  
  331.         if (!GETF_NICEPAGING(ep))
  332.         {
  333.         if (ep->column != ep->topcolumn + Columns -1)
  334.         {
  335.             if (t < ep->topcolumn + Columns && t > ep->column)
  336.             ep->column = t;
  337.             else
  338.             ep->column = ep->topcolumn + Columns -1;
  339.  
  340.             if (ep->column >= MAXLINELEN)
  341.             ep->column = MAXLINELEN - 1;
  342.  
  343.             text_sync ();
  344.             return;
  345.         }
  346.         }
  347.         else /* nicepaging */
  348.         {
  349.         if (t > ep->column && t < ep->topcolumn + Columns)
  350.         {
  351.             ep->column = t;
  352.  
  353.             text_sync ();
  354.             return;
  355.         }
  356.         }
  357.  
  358.         nx = Columns * PageJump / 100;
  359.  
  360.         if (t > ep->column && t < ep->column + nx)
  361.         ep->column = t;
  362.         else
  363.         ep->column += nx;
  364.  
  365.         if (ep->column >= MAXLINELEN)
  366.         ep->column = MAXLINELEN-1;
  367.  
  368.         if (ep->topcolumn+nx > ep->column)
  369.         nx = (ep->column - Columns/2) - ep->topcolumn;
  370.  
  371.         if (ep->column > Clen)
  372.         {
  373.         memset (Current+Clen, ' ', ep->column-Clen);
  374.         Current[Clen = ep->column] = 0;
  375.         }
  376.  
  377.         break;
  378.  
  379.     case 's':
  380.         PageJump = atoi ((char *)av[1]);
  381.  
  382.         if (PageJump > 100)
  383.         PageJump = 100;
  384.         else if (PageJump < 1)
  385.         PageJump = 1;
  386.  
  387.         break;
  388.     }
  389.  
  390.     if (!Nsu && (nx || ny))
  391.     ScrollAndUpdate (nx, ny);
  392.  
  393. } /* do_page */
  394.  
  395.  
  396. /*DEFHELP #cmd textedit,movement DOWNADD - cursor down. If at bottom of text, add a line. */
  397.  
  398. DEFUSERCMD("downadd", 0, 0, void, do_downadd, (void),)
  399. {
  400.     ED      * ep = Ep;
  401.     UBYTE * ptr;
  402.  
  403.     if (ep->line + 1 == ep->lines)
  404.     {
  405.     SETF_MODIFIED (ep, 1);
  406.  
  407.     if (makeroom (32))
  408.     {
  409.         ptr = allocline (1);
  410.  
  411.         SETLINE(ep,ep->lines,ptr);
  412.         ep->lines ++;
  413.  
  414.         if (GETF_SLINE (ep))
  415.         //ep->column = 0;
  416.         do_firstcolumn(); /* 30-11-94 */
  417.     } else
  418.     {
  419.         nomemory ();
  420.     }
  421.     }
  422.  
  423.     do_down ();
  424. } /* do_downadd */
  425.  
  426.  
  427. /*DEFHELP #cmd movement LEFT - cursor left */
  428.  
  429. DEFUSERCMD("left", 0, CF_VWM|CF_COK, void, do_left, (void),)
  430. {
  431.     ED * ep = Ep;
  432.  
  433.     if (ep->column)
  434.     {
  435.     ep->column --;
  436.  
  437.     if (ep->column < ep->topcolumn)
  438.         text_adjust (FALSE);
  439.     }
  440.     else if (GETF_SLINE (ep)) /* do wrap */
  441.     {
  442.     Line cl = ep->line;
  443.     do_up ();
  444.     if (cl != ep->line)  /* 07-12-94 */
  445.         do_lastcolumn(); /* 30-11-94 */
  446.     //ep->column = lastns (Current);
  447.     }
  448.     else
  449.     SETF_ABORTCOMMAND(ep,1);
  450. } /* do_left */
  451.  
  452.  
  453. /*DEFHELP #cmd movement RIGHT - cursor right */
  454.  
  455. DEFUSERCMD("right", 0, CF_VWM|CF_COK, void, do_right, (void),)
  456. {
  457.     ED * ep = Ep;
  458.  
  459.     if (ep->column != MAXLINELEN-1)
  460.     {
  461.     if (Current[ep->column] == 0)
  462.     {
  463.         if (GETF_SLINE (ep)) /* do wrap */
  464.         {
  465.         Line cl = ep->line;
  466.         //ep->column = 0;
  467.         do_down ();
  468.         if (cl != ep->line)  /* 07-12-94 */
  469.             do_firstcolumn(); /* 30-11-94 */
  470.         return;
  471.         }
  472.  
  473.         Current[ep->column] = ' ';
  474.         Current[ep->column+1]= '\0';
  475.  
  476.         Clen ++;
  477.     }
  478.  
  479.     ep->column ++;
  480.  
  481.     if (ep->column - ep->topcolumn >= Columns)
  482.         text_adjust (FALSE);
  483.     }
  484.     else if (GETF_SLINE (ep)) /* do wrap */
  485.     {
  486.     Line cl = ep->line;
  487.     //ep->column = 0;
  488.     do_down ();
  489.     if (cl != ep->line)  /* 07-12-94 */
  490.         do_firstcolumn(); /* 30-11-94 */
  491.     }
  492.     else
  493.     SETF_ABORTCOMMAND(Ep,1);
  494. } /* do_right */
  495.  
  496.  
  497. /*DEFHELP #cmd movement TAB - forward tab */
  498.  
  499. DEFUSERCMD("tab", 0, CF_VWM|CF_COK, void, do_tab, (void),)
  500. {
  501.     WORD  n;
  502.     ED    * ep = Ep;
  503.  
  504.     /* TODO */
  505.     for (n=ep->config.tabstop-(ep->column % ep->config.tabstop); n>0; n--)
  506.     do_right ();
  507. } /* do_tab */
  508.  
  509.  
  510. /*DEFHELP #cmd movement BACKTAB - backward tab */
  511.  
  512. DEFUSERCMD("backtab", 0, CF_VWM|CF_COK, void, do_backtab, (void),)
  513. {
  514.     WORD  n;
  515.     ED    * ep = Ep;
  516.  
  517.     n = ep->column % ep->config.tabstop;
  518.     if (!n)
  519.     n = ep->config.tabstop;
  520.  
  521.     /* TODO */
  522.     for (; n > 0; --n)
  523.     do_left ();
  524. } /* do_backtab */
  525.  
  526.  
  527. /*DEFHELP #cmd movement TOP - Move to Top of File */
  528.  
  529. DEFUSERCMD("top", 0, CF_VWM, void, do_top, (void),)
  530. {
  531.     text_sync ();
  532.  
  533.     Ep->line = 0;
  534.  
  535.     text_load ();
  536.     text_adjust (FALSE);
  537. } /* do_top */
  538.  
  539.  
  540. /*DEFHELP #cmd movement BOTTOM - Move to Bottom of File */
  541.  
  542. DEFUSERCMD("bottom", 0, CF_VWM, void, do_bottom, (void),)
  543. {
  544.     text_sync ();
  545.  
  546.     Ep->line = Ep->lines - 1;
  547.  
  548.     text_load ();
  549.     text_adjust (FALSE);
  550. } /* do_bottom */
  551.  
  552.  
  553. /*DEFHELP #cmd movement FIRST - move to column 1 */
  554.  
  555. DEFUSERCMD("first", 0, CF_VWM|CF_COK, void, do_firstcolumn, (void),)
  556. {
  557.     if (Ep->column)
  558.     {
  559.     Ep->column = 0;
  560.     text_adjust (FALSE);
  561.     }
  562. } /* do_firstcolumn */
  563.  
  564.  
  565. /*DEFHELP #cmd movement FIRSTNB - Move to first non-blank in line. */
  566.  
  567. DEFUSERCMD("firstnb", 0, CF_VWM|CF_COK, void, do_firstnb, (void),)
  568. {
  569.     for (Ep->column = 0; Current[Ep->column] == ' '; Ep->column ++);
  570.  
  571.     if (Current[Ep->column] == 0)
  572.     Ep->column = 0;
  573.  
  574.     text_adjust (FALSE);
  575. } /* do_firstnb */
  576.  
  577.  
  578. /*DEFHELP #cmd movement LAST - move one beyond the last non-space in a line. */
  579.  
  580. DEFUSERCMD("last", 0, CF_VWM|CF_COK, void, do_lastcolumn, (void),)
  581. {
  582.     WORD  i;
  583.  
  584.     text_sync ();
  585.  
  586.     i = (GETF_COMLINEMODE(Ep)) ? Clen : LINELEN(Ep,Ep->line);
  587.  
  588.     if (i != Ep->column)
  589.     {
  590.     Ep->column = i;
  591.     text_adjust (FALSE);
  592.     }
  593. } /* do_lastcolumn */
  594.  
  595.  
  596. /*DEFHELP #cmd movement GOTO dest - Goto to a position in the text. */
  597.  
  598. DEFUSERCMD("goto", 1, CF_VWM, void, do_goto, (void),)
  599. {
  600.     Line   line;
  601.     Column col;
  602.     long   i;
  603.     char * ptr = (char *)av[1];
  604.  
  605.     i     = 0;
  606.     line = -1;
  607.     col  = -1;
  608.  
  609.     switch (*ptr)
  610.     {
  611.     case 'b':
  612.     case 's':
  613.        if (ActualBlock.type != BT_NONE && Ep == ActualBlock.ep)
  614.        {
  615.            line = ActualBlock.start_line;
  616.  
  617.            if (ActualBlock.type != BT_LINE)
  618.            col = ActualBlock.start_column;
  619.        }
  620.     break;
  621.  
  622.     case 'e':
  623.         if (ActualBlock.type != BT_NONE && Ep == ActualBlock.ep)
  624.         {
  625.         line = ActualBlock.end_line;
  626.  
  627.         if (ActualBlock.type != BT_LINE)
  628.             col = ActualBlock.end_column;
  629.         }
  630.     break;
  631.  
  632.     case '+':
  633.         i = 1;
  634.  
  635.     case '-':
  636.         line = Ep->line;
  637.  
  638.     default:
  639.         line += atoi(ptr+i);
  640.     } /* switch (*ptr) */
  641.  
  642.     if (line >= Ep->lines)
  643.     line = Ep->lines - 1;
  644.  
  645.     if (line < 0)
  646.     line = 0;
  647.  
  648.     text_sync ();
  649.  
  650.     Ep->line = line;
  651.     if (col != -1)
  652.     Ep->column = col;
  653.  
  654.     text_load ();
  655.     text_adjust (FALSE);
  656. } /* do_goto */
  657.  
  658.  
  659. /*DEFHELP #cmd movement SCREENTOP - Move cursor to the top of the screen */
  660.  
  661. DEFUSERCMD("screentop", 0, CF_VWM, void, do_screentop, (void),)
  662. {
  663.     text_sync ();
  664.  
  665.     Ep->line = Ep->topline;
  666.  
  667.     text_load ();
  668.     text_adjust (FALSE);
  669. } /* do_screentop */
  670.  
  671.  
  672. /*DEFHELP #cmd movement SCREENBOTTOM - Move cursor to the bottom of the screen. */
  673.  
  674. DEFUSERCMD("screenbottom", 0, CF_VWM, void, do_screenbottom, (void),)
  675. {
  676.     text_sync ();
  677.  
  678.     Ep->line = Ep->topline + Lines - 1;
  679.  
  680.     if (Ep->line < 0 || Ep->line >= Ep->lines)
  681.     Ep->line = Ep->lines - 1;
  682.  
  683.     text_load ();
  684.     text_adjust (FALSE);
  685. } /* do_screenbottom */
  686.  
  687.  
  688. /*DEFHELP #cmd movement WLEFT - move to beginning of previous word. If in the middle of a word, move to beginning of current word. */
  689.  
  690. DEFUSERCMD("wleft", 0, CF_VWM|CF_COK, void, do_wleft, (void),)
  691. {
  692.     ED * ep = Ep;
  693.     int  i;
  694.  
  695.     for (;;)
  696.     {
  697.     i = ep->column;
  698.  
  699.     if (i == 0)
  700.         goto prevline;
  701.  
  702.     i --;
  703.  
  704.     while (i && Current[i] == ' ')
  705.         i --;
  706.  
  707.     if (i == 0 && Current[0] == ' ')
  708.     {
  709. prevline:
  710.         if (GETF_COMLINEMODE(Ep) || ep->line == 0)
  711.         {
  712.         i = ep->column;
  713.         break;
  714.         }
  715.  
  716.         text_sync ();
  717.  
  718.         ep->line --;
  719.  
  720.         text_load ();
  721.  
  722.         ep->column = Clen;
  723.         continue;
  724.     } /* while !SOL && isspace(Current[i]) */
  725.  
  726.     while (i && Current[i] != ' ')
  727.         i --;
  728.  
  729.     if (Current[i] == ' ')
  730.         i ++;
  731.  
  732.     break;
  733.     } /* forever */
  734.  
  735.     ep->column = i;
  736.  
  737.     text_adjust (FALSE);
  738. } /* do_wleft */
  739.  
  740.  
  741. /*DEFHELP #cmd movement WRIGHT - move to beginning of next word */
  742.  
  743. DEFUSERCMD("wright", 0, CF_VWM|CF_COK, void, do_wright, (void),)
  744. {
  745.     ED * ep = Ep;
  746.     int  i;
  747.  
  748.     for (;;)
  749.     {
  750.     i = ep->column;
  751.  
  752.     if (i == Clen)
  753.         goto nextline;
  754.  
  755.     while (i != Clen && Current[i] != ' ')  /* skip past current word */
  756.         i ++;
  757.  
  758.     while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
  759.         i ++;
  760.  
  761.     if (i == Clen)
  762.     {
  763. nextline:
  764.         if (GETF_COMLINEMODE(Ep) || ep->line == ep->lines - 1)
  765.         {
  766.         i = ep->column;
  767.         break;
  768.         }
  769.  
  770.         text_sync ();
  771.  
  772.         ep->line ++;
  773.  
  774.         text_load ();
  775.  
  776.         ep->column = i = 0;
  777.  
  778.         if (Current[0] != ' ')
  779.         break;
  780.  
  781.         continue;
  782.     }
  783.  
  784.     break;
  785.     } /* forever */
  786.  
  787.     ep->column = i;
  788.  
  789.     text_adjust (FALSE);
  790. } /* do_wright() */
  791.  
  792.  
  793. /*DEFHELP #cmd movement COL n - Move cursor to column @{B}n@{UB} or @{B}n@{UB} characters left (@{B}-n@{UB}) or right (@{B}+n@{UB}) */
  794.  
  795. DEFUSERCMD("col", 1, CF_VWM|CF_COK, void, do_col, (void),)
  796. {
  797.     int    col;
  798.     char * ptr = (char *)av[1];
  799.  
  800.     switch(*ptr)
  801.     {
  802.     case '+':
  803.         col = text_colno() + atoi(ptr + 1);
  804.         if (col >= MAXLINELEN)
  805.         col = MAXLINELEN-1;
  806.     break;
  807.  
  808.     case '-':
  809.         col = text_colno() + atoi(ptr);
  810.         if (col < 0)
  811.         col = 0;
  812.     break;
  813.  
  814.     default:
  815.         col = atoi(ptr) - 1;
  816.     break;
  817.     }
  818.  
  819.     if (col > MAXLINELEN-1 || col < 0)
  820.     {
  821.     SETF_ABORTCOMMAND(Ep,1);
  822.     return;
  823.     }
  824.  
  825.     while (Clen < col)
  826.     Current[Clen ++] = ' ';
  827.  
  828.     Current[Clen] = 0;
  829.  
  830.     Ep->column = col;
  831.  
  832.     text_adjust (FALSE);
  833. } /* do_col */
  834.  
  835.  
  836. /*DEFHELP #cmd movement SCROLLLEFT - Scroll left without moving cursor */
  837. /*DEFHELP #cmd movement SCROLLRIGHT - Scroll right without moving cursor */
  838.  
  839. DEFUSERCMD("scrollleft",  0, CF_VWM, void, do_scroll, (int dir),;)
  840. DEFUSERCMD("scrollright", 0, CF_VWM, void, do_scroll, (int dir),)
  841. {
  842.     ED     * ep = Ep;
  843.     UWORD step      = 4;
  844.  
  845.     if (Nsu)
  846.     return;
  847.  
  848.     if (dir == -1)
  849.     if (av[0][6] == 'l')
  850.         dir = SCROLL_LEFT;
  851.     else
  852.         dir = SCROLL_RIGHT;
  853.  
  854.     if (dir == SCROLL_LEFT)
  855.     {
  856.     if (!ep->topcolumn)
  857.     {
  858.         SETF_ABORTCOMMAND(Ep,1);
  859.         return;
  860.     }
  861.  
  862.     if (ep->topcolumn < step)
  863.         step = ep->topcolumn;
  864.     } else if (dir == SCROLL_RIGHT)
  865.     {
  866.     if ((ep->topcolumn + Columns) >= MAXLINELEN)
  867.     {
  868.         SETF_ABORTCOMMAND(Ep,1);
  869.         return;
  870.     }
  871.  
  872.     if ((ep->topcolumn + Columns + step) >= MAXLINELEN)
  873.         step = MAXLINELEN - (ep->topcolumn + Columns);
  874.     }
  875.  
  876.     if (dir == SCROLL_LEFT)
  877.     {
  878.     /* ep->topcolumn -= step; */
  879.     ep->column    -= step;
  880.     } else
  881.     {
  882.     UWORD end;
  883.  
  884.     /* fill Current with spaces */
  885.     end = ep->column + step;
  886.  
  887.     for ( ; Clen<end; Clen++)
  888.         Current[Clen] = ' ';
  889.  
  890.     Current[Clen] = 0;
  891.  
  892.     /* ep->topcolumn += step; */
  893.     ep->column    += step;
  894.     }
  895.  
  896.     ScrollAndUpdate (step, 0);
  897.     /* scroll_display ((dir == SCROLL_LEFT ? -step : step), 0,
  898.         ep->topcolumn, ep->topline,
  899.         ep->topcolumn + Columns, ep->topline + Lines); */
  900. } /* do_scroll */
  901.  
  902.  
  903. struct pos
  904. {
  905.     UBYTE * ptr;
  906.     ULONG   len;
  907.     Line    lin;
  908.     Column  col;
  909. };
  910.  
  911.  
  912. Prototype int get_char (ED * ep, struct pos * curr, int dir);
  913.  
  914. int get_char (ED * ep, struct pos * curr, int dir)
  915. {
  916.     int c;
  917.  
  918.     if (dir == 0)
  919.     {
  920.     curr->ptr = CONTENTS(Current);
  921.     curr->len = strlen (curr->ptr);
  922.     curr->lin = Ep->line;
  923.     curr->col = Ep->column;
  924.  
  925.     if (curr->col > curr->len)
  926.         curr->col = curr->len - 1;
  927.  
  928.     c = curr->ptr[curr->col];
  929.     }
  930.     else if (dir < 0)
  931.     {
  932.     if (curr->col < 0)
  933.     {
  934.         do
  935.         {
  936.         curr->lin --;
  937.  
  938.         if (curr->lin < 0)
  939.             return (-1);
  940.  
  941.         curr->ptr = GETTEXT(ep,curr->lin);
  942.         curr->len = strlen (curr->ptr);
  943.         } while (!curr->len);
  944.  
  945.         curr->col = curr->len-1;
  946.     } /* col out of range */
  947.  
  948.     c = curr->ptr[curr->col];
  949.  
  950.     curr->col --;
  951.     }
  952.     else
  953.     {
  954.     if (curr->col > curr->len)
  955.     {
  956.         do
  957.         {
  958.         curr->lin ++;
  959.  
  960.         if (curr->lin >= ep->lines)
  961.             return (-1);
  962.  
  963.         curr->ptr = GETTEXT(ep,curr->lin);
  964.         curr->len = strlen (curr->ptr);
  965.         } while (!curr->len);
  966.  
  967.         curr->col = 0;
  968.     } /* col out of range */
  969.  
  970.     c = curr->ptr[curr->col];
  971.  
  972.     curr->col ++;
  973.     }
  974.  
  975.     return (c);
  976. }
  977.  
  978.  
  979. /*DEFHELP #cmd movement MATCH - find matching paren. Works with (), [], {}, `' and C-comments */
  980.  
  981. DEFUSERCMD("match", 0, CF_VWM|CF_COK, void, do_match, (void),)
  982. {
  983.     char   dec,     /* char that indicates a "level_down"   */
  984.        inc;     /*        -""-         "level_up"     */
  985.     WORD   dir;     /* direction of search            */
  986.     WORD   level;    /* "level"                              */
  987.     int    c;
  988.     struct pos curr;    /* current position */
  989.  
  990.     /* set start values */
  991.     inc = get_char (Ep, &curr, 0);
  992.  
  993.     /* Check for a known paren and select the search-direction accordingly. */
  994.     switch (inc)
  995.     {
  996.     case '{':
  997.         dir = 1;
  998.         dec = '}';
  999.     break;
  1000.  
  1001.     case '}':
  1002.         dir = -1;
  1003.         dec = '{';
  1004.     break;
  1005.  
  1006.     case '[':
  1007.         dir = 1;
  1008.         dec = ']';
  1009.     break;
  1010.  
  1011.     case ']':
  1012.         dir = -1;
  1013.         dec = '[';
  1014.     break;
  1015.  
  1016.     case '(':
  1017.         dir = 1;
  1018.         dec = ')';
  1019.     break;
  1020.  
  1021.     case ')':
  1022.         dir = -1;
  1023.         dec = '(';
  1024.     break;
  1025.  
  1026.     case '`':
  1027.         dir = 1;
  1028.         dec = '\'';
  1029.     break;
  1030.  
  1031.     case '\'':
  1032.         dir = -1;
  1033.         dec = '`';
  1034.     break;
  1035.  
  1036.     case '*':
  1037.     case '/': {
  1038.         int ln, nested;
  1039.  
  1040.         {
  1041.         int pre, next;
  1042.  
  1043.         pre = next = 0;
  1044.  
  1045.         if (curr.col)
  1046.             pre = curr.ptr[curr.col-1];
  1047.  
  1048.         if (curr.col != curr.len-1)
  1049.             next = curr.ptr[curr.col+1];
  1050.  
  1051.         if (inc == '*')
  1052.         {
  1053.             if (pre == '/')
  1054.             {
  1055.             if (next == '/')
  1056.             {
  1057.                 warn ("match: ambigous comment");
  1058.                 return;
  1059.             }
  1060.             else
  1061.                 dir = 1;    /* / * x */
  1062.             }
  1063.             else
  1064.             {
  1065.             if (next == '/')
  1066.                 dir = -1;    /* x * / */
  1067.             else
  1068.                 return;    /* x * x */
  1069.             }
  1070.  
  1071.             /* skip '*' */
  1072.             get_char (Ep, &curr, dir);
  1073.         }
  1074.         else /* inc == '/' */
  1075.         {
  1076.             if (pre == '*')
  1077.             {
  1078.             if (next == '*')
  1079.             {
  1080.                 warn ("match: ambigous comment");
  1081.                 return;
  1082.             }
  1083.             else
  1084.                 dir = -1;    /* * / x */
  1085.             }
  1086.             else
  1087.             {
  1088.             if (next == '*')
  1089.                 dir = 1;    /* x / * */
  1090.             else
  1091.                 return;    /* x / x */
  1092.             }
  1093.  
  1094.             /* skip '/*' */
  1095.             get_char (Ep, &curr, dir);
  1096.             get_char (Ep, &curr, dir);
  1097.         }
  1098.         } /* block */
  1099.  
  1100.         nested = FALSE;
  1101.         level = 1;        /* we _are_ inside the comment */
  1102.  
  1103.         /* now look for the first * /-sequence (get_char returns
  1104.            the next char in the specified direction and from within
  1105.            the comment, * / always terminates it */
  1106.         for (;;)
  1107.         {
  1108.         ln = curr.lin;
  1109.         c = get_char (Ep, &curr, dir);
  1110.  
  1111.         if (c == -1)
  1112.             goto not_found;
  1113.  
  1114.         /* Zeilenwechsel ? -> Trenner */
  1115.         if (ln != curr.lin)
  1116.             continue;
  1117.  
  1118.         while (c == '/')
  1119.         {
  1120.             c = get_char (Ep, &curr, dir);
  1121.  
  1122.             if (c == -1)
  1123.             goto not_found;
  1124.  
  1125.             if (c == '*')
  1126.             {
  1127.             level ++;
  1128.             nested = TRUE;
  1129.             }
  1130.         }
  1131.  
  1132.         while (c == '*')
  1133.         {
  1134.             c = get_char (Ep, &curr, dir);
  1135.  
  1136.             if (c == -1)
  1137.             goto not_found;
  1138.  
  1139.             if (c == '/')
  1140.             {
  1141.             level --;
  1142.  
  1143.             if (!level)
  1144.                 goto found;
  1145.             }
  1146.         }
  1147.         }
  1148.  
  1149.         if (nested)
  1150.         warn ("match: nested commend");
  1151.     break; }
  1152.  
  1153.     default:
  1154.         dir = 0;
  1155.     break;
  1156.     }
  1157.  
  1158.     /* if there is no known paren, just return */
  1159.     if (!dir)
  1160.     return;
  1161.  
  1162.     /* we start with level 0. Since we ARE on a paren, this is increased soon */
  1163.     level = 0;
  1164.  
  1165.     for (;;)
  1166.     {
  1167.     c = get_char (Ep, &curr, dir);
  1168.  
  1169.     if (c == -1)
  1170.     {
  1171. not_found:
  1172.         warn ("match: No matching paren");
  1173.         return;
  1174.     }
  1175.  
  1176.     if (c == inc)
  1177.     { /* check for "inc-char" */
  1178.         level ++;
  1179.     } else
  1180.     {
  1181.         if (c == dec)
  1182.         { /* dito */
  1183.         level --;
  1184.  
  1185.         /* if we have reached the start-level, we are through */
  1186.         if (!level)
  1187.             break;
  1188.         }
  1189.     }
  1190.     }
  1191.  
  1192. found:
  1193.     text_sync ();
  1194.  
  1195.     if (curr.lin >= Ep->lines)
  1196.     curr.lin = Ep->lines - 1;
  1197.  
  1198.     Ep->line   = curr.lin;
  1199.     Ep->column = curr.col - dir;    /* undo last oper. in get_char() */
  1200.  
  1201.     text_load ();
  1202.     text_adjust (FALSE);
  1203. } /* do_match */
  1204.  
  1205.  
  1206. /*DEFHELP #cmd movement PING n - set a text marker (@{B}n@{UB} = 0-9). */
  1207.  
  1208. DEFUSERCMD("ping", 1, CF_VWM|CF_ICO, void, do_ping, (void),)
  1209. {
  1210.     UWORD num = atoi (av[1]);
  1211.  
  1212.     if (num >= PINGDEPTH)
  1213.     {
  1214.     error ("ping:\n%ld out of range\n(max %ld)", num, PINGDEPTH);
  1215.     return;
  1216.     }
  1217.  
  1218.     marker[num].ep     = Ep;
  1219.     marker[num].column = Ep->column;
  1220.     marker[num].line   = Ep->line;
  1221.  
  1222.     title ("Position marked");
  1223. } /* do_ping */
  1224.  
  1225.  
  1226. /*DEFHELP #cmd movement PONG n - move to a previously set text marker (@{B}n@{UB} = 0-9) */
  1227.  
  1228. DEFUSERCMD("pong", 1, CF_VWM, void, do_pong, (void),)
  1229. {
  1230.     WORD  num = atoi (av[1]);
  1231.  
  1232.     text_sync ();
  1233.  
  1234.     if (num < 0 || num >= PINGDEPTH || !marker[num].ep)
  1235.     {
  1236.     error ("pong:\nrange error or\nyet nothing marked");
  1237.     return;
  1238.     }
  1239.  
  1240.     text_cursor (1);
  1241.     switch_ed (marker[num].ep);
  1242.     text_cursor (0);
  1243.  
  1244.     if (IntuitionBase->ActiveWindow != Ep->win)
  1245.     {
  1246.     WindowToFront (Ep->win);
  1247.     ActivateWindow (Ep->win);
  1248.     }
  1249.  
  1250.     if ((Ep->line = marker[num].line) >= Ep->lines)
  1251.     {
  1252.     marker[num].line = Ep->line = Ep->lines - 1;
  1253.     }
  1254.  
  1255.     Ep->column = marker[num].column;
  1256.  
  1257.     text_load ();
  1258.     text_adjust (FALSE);
  1259. } /* do_pong */
  1260.  
  1261.  
  1262. Prototype int get_pong (int num);
  1263.  
  1264. int get_pong (int num)
  1265. {
  1266.      if (num < 0 || num >= PINGDEPTH || !marker[num].ep)
  1267.      {
  1268.       return (-1);
  1269.      }
  1270.  
  1271.      if (marker[num].line >= Ep->lines)
  1272.       return (marker[num].line = Ep->lines-1);
  1273.  
  1274.      return (marker[num].line);
  1275. } /* get_pong */
  1276.  
  1277.  
  1278. static int Savetopline, Savecolumn, Savetopcolumn;
  1279.  
  1280. /*DEFHELP #cmd misc RECALL - recall most recently entered command. Must be used from a keymap (c-esc). */
  1281.  
  1282. DEFUSERCMD("recall", 0, CF_VWM, void, do_recall, (void),)
  1283. {
  1284.     av[0] = "escimm";
  1285.  
  1286.     /* Copy last Histoline if possible */
  1287.     if (NumHistoLines)
  1288.     av[1] = HistoBuff[NumHistoLines - 1];
  1289.     else
  1290.     av[1] = "";
  1291.  
  1292.     do_esc ();
  1293.  
  1294.     if (NumHistoLines)
  1295.     HistoLine --;
  1296. } /* do_recall */
  1297.  
  1298.  
  1299. /*DEFHELP #cmd misc ESC - toggle manual command entry mode */
  1300. /*DEFHELP #cmd misc ESCIMM arg - go into command entry mode prompting with @{B}arg@{UB} */
  1301.  
  1302. DEFUSERCMD("escimm", 1, CF_VWM|CF_PAR, void, do_esc, (void),;)
  1303. DEFUSERCMD("esc",    0, CF_VWM|CF_COK, void, do_esc, (void),)
  1304. {
  1305.     ED    * ep = Ep;
  1306.     RP    * rp = ep->win->RPort;
  1307.     WORD  y;
  1308.  
  1309.     if (GETF_COMLINEMODE(ep))
  1310.     {
  1311.     escapecomlinemode ();
  1312.     return;
  1313.     } else
  1314.     {             /* PATCH_NULL added */
  1315.     esc_partial = Partial;    /* PATCH_NULL added */
  1316.     Partial = NULL;     /* PATCH_NULL added */
  1317.     }
  1318.  
  1319.     text_sync ();
  1320.  
  1321.     if (av[0][3] == 'i')
  1322.     strcpy ((char *)Current, (char *)av[1]);
  1323.     else
  1324.     Current[0] = 0;
  1325.  
  1326.     Clen = strlen ((char *)Current);
  1327.     SETF_COMLINEMODE(ep,1);
  1328.  
  1329.     /* returnoveride (1); */            /* PATCH_NULL [25 Jan 1993] : commented out */
  1330.  
  1331.     Savetopline   = ep->topline;
  1332.     Savecolumn      = ep->column;
  1333.     Savetopcolumn = ep->topcolumn;
  1334.  
  1335.     ep->column = Clen;
  1336.     ep->topcolumn = ep->column - Columns + 1;
  1337.  
  1338.     if (ep->column < Columns)
  1339.     ep->topcolumn = 0;
  1340.  
  1341.     ep->topline   = ep->line - Lines + 1;
  1342.  
  1343.     y = ROW (Lines-1);
  1344.     SetAPen (rp, TEXT_BPEN(ep));
  1345.     SetWrMsk (rp, ALL_MASK);
  1346.     RectFill (rp, COL(0), y, Xpixs, Ypixs);
  1347.  
  1348.     y --;
  1349.     SetAPen (rp, TEXT_FPEN(ep));
  1350.     RectFill (rp, COL(0), y, Xpixs, y);
  1351.  
  1352.     text_displayseg (Lines - 1, 1);
  1353.  
  1354.     text_cursor (1);
  1355.  
  1356.     HistoLine = NumHistoLines;
  1357. } /* do_esc */
  1358.  
  1359.  
  1360. Prototype void escapecomlinemode (void);
  1361.  
  1362. void escapecomlinemode (void)
  1363. {
  1364.     ED     * ep = Ep;
  1365.     RP     * rp = ep->win->RPort;
  1366.     char * ptr;
  1367.  
  1368.     if (esc_partial)
  1369.     {       /* PATCH_NULL P -> esc_p */
  1370.     free(esc_partial);  /* PATCH_NULL P -> esc_p */
  1371.     esc_partial = NULL; /* PATCH_NULL P -> esc_p */
  1372.     }
  1373.  
  1374.     if (GETF_COMLINEMODE(ep))
  1375.     {
  1376.     /* Don't add empty lines */
  1377.     if (*Current)
  1378.     {
  1379.         ptr = Current + strlen (Current) -1;
  1380.  
  1381.         while (*ptr == ' ' && ptr != (char *)Current)
  1382.         ptr --;
  1383.  
  1384.         /* Set string-end after last char. Note that this code
  1385.            removes histo-lines with length 1 (single chars) */
  1386.         if (ptr != (char *)Current)
  1387.         ptr ++;
  1388.  
  1389.         *ptr = 0;
  1390.     }
  1391.  
  1392.     /* If we are somewhere above and we didn't change anything,
  1393.        we won't add a new history-line */
  1394.     /* If there is something to add */
  1395.     if (!(HistoLine != NumHistoLines && !strcmp (Current,
  1396.         HistoBuff[HistoLine])) && *Current)
  1397.         {
  1398.         /* Check if buffer is full */
  1399.         if (NumHistoLines == MaxHistoLines)
  1400.         {
  1401.         /* Free oldest line and shift buffer */
  1402.         free (HistoBuff[0]);
  1403.  
  1404.         movmem (HistoBuff + 1, HistoBuff,
  1405.             sizeof (char *) * (MaxHistoLines - 1));
  1406.  
  1407.         /* We have now space for one line */
  1408.         NumHistoLines --;
  1409.         }
  1410.  
  1411.         /* Allocate new line */
  1412.         ptr = malloc (strlen (Current) + 1);
  1413.  
  1414.         /* Copy new line if possible. Note that even if malloc()
  1415.            failed we don't loose information. */
  1416.         if (ptr)
  1417.         {
  1418.         strcpy (ptr, (char *)Current);
  1419.  
  1420.         /* Add line. At this point, NumHistoLines is ALWAYS
  1421.            less than MaxHistoLines ! */
  1422.         HistoBuff[NumHistoLines ++] = ptr;
  1423.         }
  1424.     }
  1425.  
  1426.     SETF_COMLINEMODE(ep,0);
  1427.  
  1428.     /* returnoveride (0); */        /* PATCH_NULL [25 Jan 1993] : commented out */
  1429.  
  1430.     ep->topline   = Savetopline;
  1431.     ep->column    = Savecolumn;
  1432.     ep->topcolumn = Savetopcolumn;
  1433.  
  1434.     text_load ();
  1435.  
  1436.     SetAPen (rp, TEXT_BPEN(ep));
  1437.     SetWrMsk (rp, ALL_MASK);
  1438.     RectFill (rp, COL(0), ROW(Lines-1)-1, Xpixs, Ypixs);
  1439.  
  1440.     SetAPen (rp, TEXT_FPEN(ep));
  1441.     text_displayseg (Lines - 2, 2);
  1442.     }
  1443. } /* escapecomlinemode */
  1444.  
  1445.  
  1446. Prototype void markerkill (ED * ep);
  1447.  
  1448. void markerkill (ED * ep)
  1449. {
  1450.     WORD  i;
  1451.  
  1452.     for (i = 0; i < PINGDEPTH; ++i)
  1453.     {        /*    remove ping-pong marks    */
  1454.     if (marker[i].ep == ep)
  1455.         marker[i].ep = NULL;
  1456.     }
  1457. } /* markerkill */
  1458.  
  1459.  
  1460. /******************************************************************************
  1461. *****  ENDE cursor.c
  1462. ******************************************************************************/
  1463.