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

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     text.c
  5.  
  6.     DESCRIPTION
  7.  
  8.     NOTES
  9.  
  10.     BUGS
  11.  
  12.     TODO
  13.  
  14.     EXAMPLES
  15.  
  16.     SEE ALSO
  17.  
  18.     INDEX
  19.  
  20.     HISTORY
  21.     04. Oct 1992    ada created
  22.  
  23. ******************************************************************************/
  24.  
  25. /**************************************
  26.         Includes
  27. **************************************/
  28. #include "defs.h"
  29.  
  30.  
  31. /**************************************
  32.         Globale Variable
  33. **************************************/
  34.  
  35.  
  36. /**************************************
  37.       Interne Defines & Strukturen
  38. **************************************/
  39.  
  40.  
  41. /**************************************
  42.         Interne Variable
  43. **************************************/
  44.  
  45.  
  46. /**************************************
  47.        Interne Prototypes
  48. **************************************/
  49. Prototype ED    * uninit_init         (ED *);
  50. Prototype int      setpen         (Line, Column);
  51. Prototype short   inversemode         (int);
  52. Prototype void      text_cursor         (int);
  53. Prototype int      text_init         (ED *, WIN *, struct NewWindow *);
  54. Prototype Bool      text_switch         (struct Window *);
  55. Prototype Bool      text_sync         (void);
  56. Prototype Bool      text_adjust         (Bool);
  57. Prototype void      text_load         (void);
  58. Prototype int      text_colno         (void);
  59. Prototype int      text_lineno         (void);
  60. Prototype int      text_lines         (void);
  61. Prototype int      text_cols         (void);
  62. Prototype int      text_imode         (void);
  63. Prototype int      text_tabsize         (void);
  64. Prototype ubyte * text_name         (void);
  65. Prototype void      text_uninit         (void);
  66. Prototype void      text_position      (int, int);
  67. Prototype void      text_redisplaycurrline (void);
  68. Prototype void      text_redisplay     (void);
  69. Prototype void      text_write         (ubyte *);
  70. Prototype void      text_displayseg     (int, int);
  71. Prototype void      text_redraw_cmdline     (void);
  72. Prototype void      text_redrawblock     (Bool);
  73. Prototype void      redraw_text         (Line, Line);
  74. Prototype void      redraw_textlineseg     (Line, Column, Column);
  75. Prototype void      redraw_lineseg     (ubyte *, ushort, Column, Column);
  76.  
  77.  
  78. /*****************************************************************************
  79.  
  80.     NAME
  81.     uninit_init
  82.  
  83.     PARAMETER
  84.     ED * ep;
  85.  
  86.     RETURN
  87.     ED * new_ep;
  88.  
  89.     DESCRIPTION
  90.     Resets an editor-struct.
  91.  
  92. ******************************************************************************/
  93.  
  94. ED * uninit_init (ED * ep)
  95. {
  96.     FONT      * font;
  97.     BPTR        lock   = DupLock (ep->dirlock);
  98.     WIN       * win;
  99.     struct Gadget * gadg;
  100.     int         bufsiz = CONFIG_SIZE;
  101.     char      * buf    = malloc (bufsiz);
  102.  
  103.     /* get buffer for config */
  104.     if (!buf)
  105.     {
  106.     nomemory ();
  107.  
  108.     warn ("Out of memory !");
  109.  
  110.     return (NULL);
  111.     }
  112.  
  113.     movmem (&ep->beginconfig, buf, bufsiz);
  114.  
  115.     /* remember window, font and gadget */
  116.     win     = ep->win;
  117.     font    = ep->font;
  118.     gadg    = ep->propgad;
  119.     ep->font    = NULL;
  120.  
  121.     /* throw anything away */
  122.     text_uninit ();
  123.  
  124.     /* init editor */
  125.     text_init (Ep, NULL, NULL);
  126.  
  127.     /* switch to new one */
  128.     ep = Ep;
  129.  
  130.     /* close font if there is one */
  131.     if (ep->font)
  132.     CloseFont (ep->font);
  133.  
  134.     /* reset window */
  135.     ep->win  = win;
  136.  
  137.     /* set new font */
  138.     if (ep->font = font)
  139.     {
  140.     SetFont (ep->win->RPort, font);
  141.     set_window_params ();
  142.     }
  143.  
  144.     /* set gadget */
  145.     ep->propgad = gadg;
  146.  
  147.     /* copy config back */
  148.     movmem (buf, &ep->beginconfig, bufsiz);
  149.  
  150.     /* no modifications. Set cursor to beginning */
  151.     ep->modified = 0;
  152.     ep->line     = ep->topline = 0;
  153.  
  154.     /* create new lock */
  155.     UnLock (ep->dirlock);
  156.     ep->dirlock = (long)lock;
  157.  
  158.     /* free buffer */
  159.     free (buf);
  160.  
  161.     return (ep);
  162. } /* uninit_init */
  163.  
  164.  
  165. /*****************************************************************************
  166.  
  167.     NAME
  168.  
  169.     PARAMETER
  170.  
  171.     RETURN
  172.  
  173.     DESCRIPTION
  174.  
  175. ******************************************************************************/
  176.  
  177. /* Return: Same as is_inblock() ! */
  178. int setpen (Line line, Column column)
  179. {
  180.     ED    * ep   = Ep;
  181.     RP    * rp   = ep->win->RPort;
  182.     short test;
  183.  
  184.     test = is_inblock (line, column);
  185.  
  186.     if (test & BP_INSIDE)
  187.     {
  188.     SetAPen (rp,  BLOCK_FPEN);
  189.     SetBPen (rp,  BLOCK_BPEN);
  190.     SetWrMsk (rp, BLOCK_MASK);
  191.     } else
  192.     {
  193.     SetAPen (rp,  TEXT_FPEN);
  194.     SetBPen (rp,  TEXT_BPEN);
  195.     SetWrMsk (rp, TEXT_MASK);
  196.     }
  197.  
  198.     return (test);
  199. } /* setpen */
  200.  
  201.  
  202. /*****************************************************************************
  203.  
  204.     NAME
  205.  
  206.     PARAMETER
  207.  
  208.     RETURN
  209.  
  210.     DESCRIPTION
  211.  
  212. ******************************************************************************/
  213.  
  214. short inversemode (int n)
  215. {
  216.     RP    * rp = Ep->win->RPort;
  217.     short test;
  218.     UBYTE fgpen;
  219.     UBYTE bgpen;
  220.  
  221.     test = setpen (Ep->line, Ep->column);
  222.  
  223.     if (n)
  224.     {
  225.     fgpen = ~rp->FgPen;
  226.     bgpen = ~rp->BgPen;
  227.  
  228.     SetAPen (rp, bgpen);
  229.     SetBPen (rp, fgpen);
  230.     SetDrMd (rp, JAM2|INVERSVID);
  231.     } else
  232.     SetDrMd (rp, JAM2);
  233.  
  234.     SetWrMsk (rp, -1);
  235.  
  236.     return (test & BP_INSIDE);
  237. } /* inversemode */
  238.  
  239.  
  240. /*****************************************************************************
  241.  
  242.     NAME
  243.  
  244.     PARAMETER
  245.  
  246.     RETURN
  247.  
  248.     DESCRIPTION
  249.  
  250. ******************************************************************************/
  251.  
  252. int text_init (ED * oldep, WIN * win, struct NewWindow * nw)
  253. {
  254.     ED * ep;
  255.  
  256.     if (!(ep = (ED *)allocb (sizeof(ED))) )
  257.     return (0);
  258.  
  259.     setmem (ep, sizeof(ED), 0);
  260.     ep->win = win;
  261.  
  262.     if (oldep)
  263.     {
  264.     ep->dirlock = (long)DupLock (oldep->dirlock);
  265.  
  266.     movmem (&oldep->beginconfig, &ep->beginconfig, CONFIG_SIZE);
  267.  
  268.     if (oldep->font)
  269.     {
  270.         ep->font = oldep->font;
  271.         ep->font->tf_Accessors ++;
  272.  
  273.         if (win)
  274.         SetFont (win->RPort, ep->font);
  275.     }
  276.  
  277.     /* change oldep to "last editor" to have the iconified window
  278.        positioned right */
  279.     oldep = GetTail ((LIST *)&DBase);
  280.  
  281.     if (oldep->iconmode)
  282.     {
  283.         ep->config.iwinx = oldep->win->LeftEdge;
  284.         ep->config.iwiny = oldep->win->TopEdge;
  285.     } else
  286.     {
  287.         ep->config.iwinx = oldep->config.iwinx;
  288.         ep->config.iwiny = oldep->config.iwiny;
  289.     }
  290.  
  291.     ep->config.iwinx += TextLength (oldep->win->RPort, oldep->name,
  292.                 strlen (oldep->name)) + 60;
  293.  
  294.     if (ep->config.iwinx > oldep->win->WScreen->Width)
  295.     {
  296.         ep->config.iwinx = 0;
  297.  
  298.         if(Ep->win->WScreen->Font != NULL)
  299.         /* height */
  300.         ep->config.iwiny += oldep->win->WScreen->Font->ta_YSize + 3;
  301.         else
  302.         ep->config.iwiny += GfxBase->DefaultFont->tf_YSize + 3;
  303.     }
  304.     } else
  305.     {
  306.     PROC * proc = (PROC *)FindTask (NULL);
  307.  
  308.     ep->dirlock = (long)DupLock (proc->pr_CurrentDir);
  309.  
  310.     loadconfig (ep);
  311.     }
  312.  
  313.     ep->lines      = 1;
  314.     ep->maxlines  = 32;
  315.     ep->list      = (ubyte **)alloclptr (ep->maxlines);
  316.     SETLINE(ep,0) = allocline (1);
  317.  
  318.     Current[0] = Clen = 0;
  319.  
  320.     AddTail ((LIST *)&DBase, (NODE *)ep);
  321.     ep->node.ln_Name = ep->name;
  322.     ep->keytable  = currenthash ();      /* PATCH_NULL [01 Feb 1993] : added */
  323.     ep->menustrip = currentmenu ();      /* PATCH_NULL [01 Feb 1993] : added */
  324.  
  325.     strcpy ((char *)ep->name, "unnamed");
  326.     Ep = ep;    /* no switch_ed() here ! */
  327.  
  328.     strcpy (ep->wtitle, "  OK  ");
  329.  
  330.     if (nw)
  331.     {
  332.     if (!ep->iconmode && ep->win)
  333.     {
  334.         nw->LeftEdge = ep->win->LeftEdge;
  335.         nw->TopEdge  = ep->win->TopEdge;
  336.         nw->Width     = ep->win->Width;
  337.         nw->Height     = ep->win->Height;
  338.     } else
  339.     {
  340.         if (ep->config.winwidth && ep->config.winheight)
  341.         {
  342.         nw->LeftEdge = ep->config.winx;
  343.         nw->TopEdge  = ep->config.winy;
  344.         nw->Width    = ep->config.winwidth;
  345.         nw->Height   = ep->config.winheight;
  346.         } else
  347.         {
  348.         nw->LeftEdge = 0;
  349.         nw->TopEdge  = 0;
  350.         nw->Width    = 640;
  351.         nw->Height   = 200;
  352.         }
  353.     }
  354.  
  355.     nw->DetailPen = TEXT_BPEN;
  356.     nw->BlockPen  = TEXT_FPEN;
  357.     }
  358.  
  359.     return (1);
  360. } /* text_init */
  361.  
  362.  
  363. /*****************************************************************************
  364.  
  365.     NAME
  366.     text_switch
  367.  
  368.     PARAMETER
  369.     WIN * win;        The window to switch to.
  370.  
  371.     RETURN
  372.     Bool found;        Was the change successful ?
  373.  
  374.     DESCRIPTION
  375.     Searches for the specified window and makes the editor with that
  376.     window active.
  377.  
  378. ******************************************************************************/
  379.  
  380. Bool text_switch (WIN * win)
  381. {
  382.     ED * ep;
  383.  
  384.     /* look for that window */
  385.  
  386.     for (ep=(ED *)GetHead(&DBase); ep; ep=(ED *)GetSucc((struct Node *)ep))
  387.     {
  388.     if (ep->win == win)
  389.         break;
  390.     }
  391.  
  392.     return (switch_ed (ep));
  393. } /* text_switch */
  394.  
  395.  
  396. /*****************************************************************************
  397.  
  398.     NAME
  399.     text_sync
  400.  
  401.     PARAMETER
  402.     void
  403.  
  404.     RETURN
  405.     Bool redraw;        Did text_sync() a screen-refresh ?
  406.  
  407.     DESCRIPTION
  408.     copy current line to list of lines and say, if screen-update
  409.     is neccessary. Furthermore, Current is filled with spaces upto
  410.     the current column.
  411.  
  412. ******************************************************************************/
  413.  
  414. Bool text_sync (void)
  415. {
  416.     ED      * ep       = Ep;
  417.     char    redraw = 0;
  418.     short   len;
  419.     ubyte * ptr;
  420.     ubyte * line;
  421.  
  422.     /* remove trailing spaces */
  423.     len = strlen ((char *)Current)-1;
  424.     ptr = Current + len;
  425.  
  426.     while (len && *ptr == ' ')
  427.     {
  428.     len --;
  429.     ptr --;
  430.     }
  431.  
  432.     if (*ptr == ' ')
  433.     *ptr = 0;
  434.     else
  435.     {
  436.     ptr[1] = 0;
  437.     len ++;
  438.     }
  439.  
  440.     /* Line length */
  441.     Clen = len;
  442.  
  443.     if (!globalflags.Comlinemode)
  444.     {
  445.     short len_in_blocks, clen_in_blocks;
  446.  
  447.     line = GETTEXT(ep,ep->line);
  448.     len = strlen ((char *)line);
  449.  
  450.     /* Find out how many blocks (*8) we use and how many we need */
  451.     len_in_blocks  =  (len + 8) & ~7;
  452.     clen_in_blocks = (Clen + 8) & ~7;
  453.  
  454.     /* This was highly wasting memory. OS is always padding Alloc's
  455.        to 8 Bytes. If the length of the line is still within one
  456.        block but has changed we freed and allocated new memory.
  457.        This guranteed to fragment memory.
  458.  
  459.        Just use the old version and edit some large text. Use avail,
  460.        save & reload text and "avail" again. The you'll see what I mean.
  461.        This is fixed now. */
  462.  
  463.     /* I must not use strcpy() if the line was empty since empty
  464.        lines are handled differently, i.e. they use static memory.
  465.        Only allocate new, if the line was empty or if the size in
  466.        blocks has changed, i.e. we need one more or less block of
  467.        memory (see AllocMem() in Amiga-ROM-Kernel-Ref.-Manual about
  468.        blocks). */
  469.     if ((!len && Clen) || len_in_blocks != clen_in_blocks)
  470.     {
  471.         if (ptr = allocline(Clen+1))
  472.         {
  473.  
  474. #ifdef DEBUG_MEM_H
  475.     printf ("Allocated at %08x\n", ptr);
  476. #endif
  477.  
  478.         ep->modified = 1;
  479.         globalflags.Overide = 0;
  480.  
  481.         freeline (line);
  482.         SETLINE(ep,ep->line) = ptr;
  483.  
  484.         strcpy ((char *)ptr, (char *)Current);
  485.         } else
  486.         {
  487.         nomemory ();
  488.         strcpy ((char *)Current, (char *)line);
  489.         }
  490.     } else
  491.     { /* Within one block ... */
  492.         ubyte * ptr1, * ptr2;
  493.  
  494.         ptr1 = line;
  495.         ptr2 = Current;
  496.  
  497.         /* We need not to copy stuff that's equal ! */
  498.         while (*ptr1 == *ptr2)
  499.         {
  500.         if (!*ptr1)
  501.             break;
  502.  
  503.         ptr1 ++;
  504.         ptr2 ++;
  505.         }
  506.  
  507.         if (*ptr1 != *ptr2)
  508.         {
  509.         ep->modified = 1;
  510.         globalflags.Overide = 0;
  511.  
  512. /*printf ("Lines \nOld `%s'\nNew `%s'\ndiffer at\n%s\n%s", line, Current, ptr1, ptr2); */
  513.  
  514.         strcpy ((char *)ptr1, (char *)ptr2);
  515. /*printf ("New Line `%s'\n", line);*/
  516.         } /* Any changes ? */
  517.     } /* Old block length != new block length */
  518.     } /* if (!Comlinemode) */
  519.  
  520. error:
  521.     return ((int)text_adjust (FALSE));
  522. } /* text_sync */
  523.  
  524.  
  525. /*****************************************************************************
  526.  
  527.     NAME
  528.     text_adjust
  529.  
  530.     PARAMETER
  531.     Bool force;        TRUE: Redraw screen even if the cursor
  532.                       is visible.
  533.                 FALSE: Draw only, if cursor is not visible.
  534.  
  535.     RETURN
  536.     Bool did_redraw;
  537.  
  538.     DESCRIPTION
  539.     Make sure the current cursor position is visible.
  540.  
  541. ******************************************************************************/
  542.  
  543. Bool text_adjust (Bool force)
  544. {
  545.     if (!Nsu)
  546.     {
  547.     if (Ep->column - Ep->topcolumn >= Columns || Ep->column < Ep->topcolumn)
  548.     {
  549.         force = 1;
  550.  
  551.         Ep->topcolumn = Ep->column - (Columns>>1);
  552.  
  553.         if (Ep->topcolumn < 0)
  554.         Ep->topcolumn = 0;
  555.     }
  556.  
  557.     if (Ep->line - Ep->topline >= Lines || Ep->line < Ep->topline)
  558.     {
  559.         force = 1;
  560.  
  561.         Ep->topline = Ep->line - (Lines>>1);
  562.  
  563.         if (Ep->topline < 0)
  564.         Ep->topline = 0;
  565.     }
  566.  
  567.     /* need I redraw ?? */
  568.     if (force)
  569.         text_redisplay ();
  570.     }
  571.  
  572.     /* pad line with spaces upto cursor */
  573.     while (Ep->column > Clen)
  574.     Current[Clen++] = ' ';
  575.  
  576.     Current[Clen] = '\0';
  577.  
  578.     return (force);
  579. } /* text_adjust */
  580.  
  581.  
  582. /*****************************************************************************
  583.  
  584.     NAME
  585.     text_load
  586.  
  587.     PARAMETER
  588.     void
  589.  
  590.     RETURN
  591.     void
  592.  
  593.     DESCRIPTION
  594.     Load current line into Current. Current is padded with spaces
  595.     if the cursor is to the left.
  596.  
  597. ******************************************************************************/
  598.  
  599.  
  600. void text_load (void)
  601. {
  602.     if (globalflags.Comlinemode)
  603.     return;
  604.  
  605.     strcpy ((char *)Current, GETTEXT(Ep,Ep->line));
  606.  
  607.     Clen = strlen ((char *)Current);
  608.  
  609.     while (Ep->column > Clen)
  610.     Current[Clen++] = ' ';
  611.  
  612.     Current[Clen] = '\0';
  613. } /* text_load */
  614.  
  615.  
  616. /*****************************************************************************
  617.  
  618.     NAME
  619.  
  620.     PARAMETER
  621.  
  622.     RETURN
  623.  
  624.     DESCRIPTION
  625.  
  626. ******************************************************************************/
  627.  
  628. int text_colno (void)
  629. {
  630.     return((int)Ep->column);
  631. } /* text_colno */
  632.  
  633.  
  634. /*****************************************************************************
  635.  
  636.     NAME
  637.  
  638.     PARAMETER
  639.  
  640.     RETURN
  641.  
  642.     DESCRIPTION
  643.  
  644. ******************************************************************************/
  645.  
  646. int text_lineno (void)
  647. {
  648.     return((int)Ep->line+1);
  649. } /* text_lineno */
  650.  
  651.  
  652. /*****************************************************************************
  653.  
  654.     NAME
  655.  
  656.     PARAMETER
  657.  
  658.     RETURN
  659.  
  660.     DESCRIPTION
  661.  
  662. ******************************************************************************/
  663.  
  664. int text_lines (void)
  665. {
  666.     return((int)Ep->lines);
  667. } /* text_lines */
  668.  
  669.  
  670. /*****************************************************************************
  671.  
  672.     NAME
  673.  
  674.     PARAMETER
  675.  
  676.     RETURN
  677.  
  678.     DESCRIPTION
  679.  
  680. ******************************************************************************/
  681.  
  682. int text_cols (void)
  683. {
  684.     return((int)Clen);
  685. } /* text_cols */
  686.  
  687.  
  688. /*****************************************************************************
  689.  
  690.     NAME
  691.  
  692.     PARAMETER
  693.  
  694.     RETURN
  695.  
  696.     DESCRIPTION
  697.  
  698. ******************************************************************************/
  699.  
  700. int text_imode (void)
  701. {
  702.     return((int)Ep->config.insertmode);
  703. } /* text_imode */
  704.  
  705.  
  706. /*****************************************************************************
  707.  
  708.     NAME
  709.  
  710.     PARAMETER
  711.  
  712.     RETURN
  713.  
  714.     DESCRIPTION
  715.  
  716. ******************************************************************************/
  717.  
  718. int text_tabsize (void)
  719. {
  720.     return((int)Ep->config.tabstop);
  721. } /* text_tabsize */
  722.  
  723.  
  724. /*****************************************************************************
  725.  
  726.     NAME
  727.  
  728.     PARAMETER
  729.  
  730.     RETURN
  731.  
  732.     DESCRIPTION
  733.  
  734. ******************************************************************************/
  735.  
  736. ubyte * text_name (void)
  737. {
  738.     return(Ep->name);
  739. } /* text_name */
  740.  
  741.  
  742. /*****************************************************************************
  743.  
  744.     NAME
  745.  
  746.     PARAMETER
  747.  
  748.     RETURN
  749.  
  750.     DESCRIPTION
  751.  
  752. ******************************************************************************/
  753.  
  754. void text_uninit (void)
  755. {
  756.     ED * ep = Ep;
  757.  
  758.     if (ep)
  759.     {
  760.     markerkill (ep);
  761.     check_stack (ep);
  762.  
  763.     freelist (ep->list, ep->lines);
  764.     FreeMem (ep->list, ep->maxlines * sizeof(LINE));
  765.  
  766.     DelAllVarsFromTree((void **)&ep->textvars); /* PATCH_NULL: local vars have to be freed */
  767.  
  768.     if (ActualBlock.ep == ep)
  769.     {
  770.         ActualBlock.type = BT_NONE;
  771.         ActualBlock.ep = NULL;
  772.     }
  773.  
  774.     Remove ((NODE *)ep);
  775.  
  776.     if (ep->font)
  777.     {
  778.         SetFont (ep->win->RPort, ep->win->WScreen->RastPort.Font);
  779.         CloseFont (ep->font);
  780.     }
  781.  
  782.     UnLock (ep->dirlock);
  783.     FreeMem (ep, sizeof(ED));
  784.  
  785.     if (ep = (ED *)GetHead (&DBase))
  786.     {
  787.         Ep = NULL;
  788.  
  789.         switch_ed (ep);
  790.  
  791.         text_load ();
  792.     } else
  793.         Ep = NULL;
  794.     }
  795. } /* text_uninit */
  796.  
  797.  
  798. /*****************************************************************************
  799.  
  800.     NAME
  801.  
  802.     PARAMETER
  803.  
  804.     RETURN
  805.  
  806.     DESCRIPTION
  807.  
  808. ******************************************************************************/
  809.  
  810. void text_cursor (int n)
  811. {
  812.     ED    * ep   = Ep;
  813.     RP    * rp   = ep->win->RPort;
  814.  
  815.     if (Ep->iconmode || Nsu)
  816.     return;
  817.  
  818.     movetocursor ();
  819.     inversemode (n);
  820.  
  821.     if (Current[ep->column])
  822.     {
  823.     Text (rp, Current + ep->column, 1);
  824.     } else
  825.     {
  826.     Text (rp, (STRPTR)" ", 1);
  827.     }
  828.  
  829.     if (n && globalflags.FollowCursor)
  830.     do_makecursorvisible ();
  831.  
  832.     inversemode (0);
  833.  
  834.     /* SetBPen (rp, TEXT_BPEN);
  835.     SetWrMsk (rp, -1); */
  836. } /* text_cursor */
  837.  
  838.  
  839. /*****************************************************************************
  840.  
  841.     NAME
  842.  
  843.     PARAMETER
  844.  
  845.     RETURN
  846.  
  847.     DESCRIPTION
  848.  
  849. ******************************************************************************/
  850.  
  851. void text_position (int col, int row)
  852. {
  853.     ED    * ep     = Ep;
  854.     short column,
  855.       line;
  856.  
  857.     text_sync ();
  858.  
  859.     column = ep->topcolumn + col;
  860.  
  861.     if (column > MAXLINELEN-1)
  862.     column = MAXLINELEN-1;
  863.  
  864.     if (column < 0)
  865.     column = 0;
  866.  
  867.     line = ep->topline + row;
  868.  
  869.     if (line >= ep->lines)
  870.     line = ep->lines - 1;
  871.  
  872.     if (line < 0)
  873.     line = 0;
  874.  
  875.     ep->column = column;
  876.     ep->line = line;
  877.  
  878.     text_load ();
  879.     text_adjust (FALSE);
  880. } /* text_position */
  881.  
  882.  
  883. /*****************************************************************************
  884.  
  885.     NAME
  886.     text_displayseg
  887.  
  888.     PARAMETER
  889.     int start;
  890.     int lines;
  891.  
  892.     RETURN
  893.     void
  894.  
  895.     DESCRIPTION
  896.  
  897. ******************************************************************************/
  898.  
  899. void text_displayseg (int start, int lines)
  900. {
  901.     ED * ep = Ep;
  902.  
  903.     if (Nsu || ep->iconmode) return;
  904.  
  905.     if (globalflags.Comlinemode)
  906.     {
  907.     text_redraw_cmdline ();
  908.     } else
  909.     {
  910.     Line   start_line;
  911.  
  912.     start_line = start + ep->topline;
  913.  
  914.     redraw_block (TRUE, start_line, ep->topcolumn,
  915.             start_line + lines-1, ep->topcolumn + Columns-1);
  916.  
  917.     prop_adj ();
  918.     } /* !Comlinemode */
  919. } /* text_displayseg */
  920.  
  921.  
  922. /*****************************************************************************
  923.  
  924.     NAME
  925.     text_redisplay
  926.  
  927.     PARAMETER
  928.     void
  929.  
  930.     RETURN
  931.     void
  932.  
  933.     DESCRIPTION
  934.  
  935. ******************************************************************************/
  936.  
  937. void text_redraw_cmdline (void)
  938. {
  939.     RP * rp = Ep->win->RPort;
  940.     int  len;
  941.     int  topline = Ep->line - Ep->topline;
  942.  
  943.     /* Clear back */
  944.     SetAPen  (rp, TEXT_BPEN);
  945.     SetWrMsk (rp, -1);
  946.     RectFill (rp, Xbase, ROW(topline), Xpixs, Ypixs);
  947.  
  948.     /* Write text */
  949.     SetAPen (rp, TEXT_FPEN);
  950.     SetBPen (rp, TEXT_BPEN);
  951.  
  952.     len = Clen - Ep->topcolumn;
  953.  
  954.     if (len > 0)
  955.     {
  956.     Move (rp, XTbase, ROWT(topline));
  957.     Text (rp, Current + Ep->topcolumn, (len > Columns) ? Columns : len);
  958.     }
  959. } /* text_redraw_cmdline */
  960.  
  961.  
  962. /*****************************************************************************
  963.  
  964.     NAME
  965.     text_redisplay
  966.  
  967.     PARAMETER
  968.     void
  969.  
  970.     RETURN
  971.     void
  972.  
  973.     DESCRIPTION
  974.  
  975. ******************************************************************************/
  976.  
  977. void text_redisplay (void)
  978. {
  979.     ED * ep = Ep;
  980.     RP * rp = ep->win->RPort;
  981.  
  982.     if (!Nsu)
  983.     {
  984.     if (!globalflags.Comlinemode)
  985.     {
  986.         SetAPen (rp, TEXT_BPEN);
  987.         SetWrMsk (rp, -1);
  988.  
  989.         RectFill (rp, Xbase, Ybase, Xpixs, Ypixs);
  990.     }
  991.  
  992.     text_displayseg (0, Lines);
  993.     }
  994. } /* text_redisplay */
  995.  
  996.  
  997. /*****************************************************************************
  998.  
  999.     NAME
  1000.     text_redisplaycurrline
  1001.  
  1002.     PARAMETER
  1003.     void
  1004.  
  1005.     RETURN
  1006.     void
  1007.  
  1008.     DESCRIPTION
  1009.     Redrenders the current line.
  1010.  
  1011. ******************************************************************************/
  1012.  
  1013. void text_redisplaycurrline (void)
  1014. {
  1015.     ED * ep  = Ep;
  1016.     RP * rp  = ep->win->RPort;
  1017.     int  row = ep->line - ep->topline;
  1018.  
  1019.     if (!Nsu)
  1020.     {
  1021.     if (globalflags.Comlinemode)
  1022.     {
  1023.         text_displayseg (0, Lines);
  1024.     } else {
  1025.         SetAPen (rp, TEXT_BPEN);
  1026.         SetWrMsk (rp, -1);
  1027.         RectFill (rp, Xbase, ROW(row), Xpixs, ROW(row+1)-1);
  1028.  
  1029.         redraw_block (TRUE, ep->line, ep->topcolumn, ep->line,
  1030.             ep->topcolumn + Columns - 1);
  1031.     }
  1032.     }
  1033. } /* text_redisplaycurrline */
  1034.  
  1035.  
  1036. /*****************************************************************************
  1037.  
  1038.     NAME
  1039.     text_write
  1040.  
  1041.     PARAMETER
  1042.     ubyte * str;
  1043.  
  1044.     RETURN
  1045.     void
  1046.  
  1047.     DESCRIPTION
  1048.     Inserts the string str into the text.
  1049.  
  1050. ******************************************************************************/
  1051.  
  1052. void text_write (ubyte * str)
  1053. {
  1054.     short len = strlen ((char *)str);
  1055.     short i;
  1056.     ED    * ep  = Ep;
  1057.     RP    * rp  = ep->win->RPort;
  1058.  
  1059.     if (Clen + len >= MAXLINELEN-1)
  1060.     {
  1061.     text_sync ();
  1062.     text_load ();
  1063.     }
  1064.  
  1065.     if (!ep->config.insertmode)
  1066.     {
  1067.     ushort line, column_start, column_end;
  1068.  
  1069.     if (ep->column + len >= MAXLINELEN-1)
  1070.         goto fail;
  1071.  
  1072.     movmem (str, Current + ep->column, len);
  1073.  
  1074.     /* clear area */
  1075.     line = ep->line - ep->topline;
  1076.     column_start = ep->column - ep->topcolumn;
  1077.     column_end = column_start + len;
  1078.  
  1079.     /* only draw, if we need to (otherwise the screen is refreshed !) */
  1080.     if (column_end < Columns)
  1081.     {
  1082.         SetAPen (rp, TEXT_BPEN);
  1083.         SetWrMsk (rp, TEXT_MASK);       /* don't write over block */
  1084.  
  1085.         /* clear area */
  1086.         RectFill (rp, COL(column_start), ROW(line),
  1087.             COL(column_end)-1, ROW(line+1)-1);
  1088.  
  1089.         /* refresh block */
  1090.         redraw_block (TRUE, ep->line, ep->column, ep->line,
  1091.                 ep->column + len - 1);
  1092.  
  1093.         setpen (ep->line, ep->column);
  1094.     }
  1095.  
  1096.     if (ep->column + len >= Clen)
  1097.         Clen = ep->column + len;
  1098.  
  1099.     Current[Clen] = 0;
  1100.     } else
  1101.     {
  1102.     if (Clen + len >= MAXLINELEN-1)
  1103.         goto fail;
  1104.  
  1105.     movmem (Current + ep->column, Current + ep->column + len,
  1106.         Clen+1-ep->column);
  1107.     movmem (str, Current + ep->column, len);
  1108.     Clen += len;
  1109.  
  1110.     if (len < Columns - (ep->column - ep->topcolumn))
  1111.     {
  1112.         i = ep->line - ep->topline;
  1113.  
  1114.         setpen (ep->line, ep->column);
  1115.  
  1116.         ScrollRaster (rp, -len * Xsize, 0 ,
  1117.         COL(ep->column - ep->topcolumn),
  1118.         ROW(i),
  1119.         Xpixs,
  1120.         ROW(i + 1) - 1);
  1121.     }
  1122.  
  1123.     /* update block */
  1124.     if (ActualBlock.type == BT_NORMAL &&
  1125.         (is_inblock (ep->line, ep->column) & BP_INSIDE))
  1126.     {
  1127.         ActualBlock.end_column += len;
  1128.     }
  1129.     }
  1130.  
  1131.     i = ep->column;
  1132.     redraw_lineseg (Current, ROWT(ep->line - ep->topline), i, i+len);
  1133.  
  1134.     ep->column += len;
  1135.  
  1136.     if (ep->column - ep->topcolumn >= Columns)
  1137.     {
  1138.     text_sync ();
  1139.     text_adjust (FALSE);
  1140.     }
  1141.  
  1142. fail:
  1143.     if (!globalflags.Comlinemode)
  1144.     {
  1145.     if (ep->config.wordwrap)
  1146.         do_reformat(0);
  1147.     else if (ep->config.autosplit)
  1148.     {
  1149.         short thislen;        /* Length of this line */
  1150. //          short nextlen;          /* Length of next line */
  1151.         short wordlen;        /* Length of word */
  1152.         char * ptr;
  1153.  
  1154.         /* Check if we have to break */
  1155.         thislen = strlen ((char *)Current);
  1156.  
  1157.         if (thislen > ep->config.margin && ep->column == thislen)
  1158.         {
  1159.         /* Well, lets start.
  1160.            This algorithm is very simple for now. It does work only,
  1161.            when the cursor is the end of the line and copies the last
  1162.            word in the next line.
  1163.         */
  1164.         wordlen = thislen - 1;
  1165.         ptr = (char *)Current + wordlen;
  1166.  
  1167.         while (*ptr != ' ' && wordlen)
  1168.         {
  1169.             ptr --;
  1170.             wordlen --;
  1171.         }
  1172.  
  1173.         /* If we found a space, we are 1 char wrong */
  1174.         if (wordlen)
  1175.         {
  1176.             ptr ++;
  1177.             wordlen ++;
  1178.         }
  1179.  
  1180.         /* Calc. length of last word */
  1181.         wordlen = thislen - wordlen;
  1182.  
  1183.         /* Do nothing if this word won't fit in the next line */
  1184.         if (wordlen < ep->config.margin)
  1185.         {
  1186.             /* Set cursor at the beginning of the word,
  1187.                split line there, go down and go to last
  1188.                char in this line. */
  1189.             ep->column -= wordlen;
  1190.             do_split ();
  1191.             do_down ();
  1192.             do_lastcolumn ();
  1193.         } /* if does word fit */
  1194.         } /* if "Do we have to split ?" */
  1195.     } /* if Autosplit */
  1196.     } /* if !Comlinemode */
  1197. } /* text_write */
  1198.  
  1199.  
  1200. /*****************************************************************************
  1201.  
  1202.     NAME
  1203.     text_redrawblock
  1204.  
  1205.     PARAMETER
  1206.     Bool on;    Turn block on (TRUE) or off (FALSE)
  1207.  
  1208.     RETURN
  1209.     void
  1210.  
  1211.     DESCRIPTION
  1212.     Redraw the block.
  1213.  
  1214. ******************************************************************************/
  1215.  
  1216. void text_redrawblock (Bool on)
  1217. {
  1218.     ED * saveed = NULL;
  1219.  
  1220.     /* if there is a block that belongs to an editor */
  1221.  
  1222.     if (ActualBlock.ep)
  1223.     {
  1224.     /* change the actual editor, if the editor the block is in and the
  1225.        actual one are not the same */
  1226.  
  1227.     if (ActualBlock.ep != Ep)
  1228.     {
  1229.         saveed = Ep;
  1230.         switch_ed (ActualBlock.ep);
  1231.     }
  1232.  
  1233.     /* redraw the block */
  1234.  
  1235.     displayblock (on);
  1236.  
  1237.     /* if we changed the editor, undo it */
  1238.  
  1239.     if (saveed)
  1240.         switch_ed (saveed);
  1241.     } else if (!on)
  1242.     {
  1243.     /* if we want to turn the block off, do it here */
  1244.  
  1245.     ActualBlock.type = BT_NONE;
  1246.     }
  1247. } /* text_redrawblock */
  1248.  
  1249.  
  1250. /*****************************************************************************
  1251.  
  1252.     NAME
  1253.     redraw_text
  1254.  
  1255.     PARAMETER
  1256.     Line start_line;    Line to start with
  1257.     Line end_line;        Line to end in (not included)
  1258.  
  1259.     RETURN
  1260.     void
  1261.  
  1262.     DESCRIPTION
  1263.     Redraws some lines of text. Only the start-line is included in the
  1264.     update.
  1265.  
  1266. ******************************************************************************/
  1267.  
  1268. void redraw_text (Line start_line, Line end_line)
  1269. {
  1270.     if (start_line < Ep->topline)
  1271.     start_line = Ep->topline;
  1272.  
  1273.     if (end_line > Ep->topline + Lines)
  1274.     end_line = Ep->topline + Lines;
  1275.     if (end_line > Ep->lines)
  1276.     end_line = Ep->lines;
  1277.  
  1278.     for ( ; start_line < end_line; start_line ++)
  1279.     redraw_textline (start_line);
  1280. } /* redraw_text */
  1281.  
  1282.  
  1283. /*****************************************************************************
  1284.  
  1285.     NAME
  1286.     redraw_textline
  1287.  
  1288.     PARAMETER
  1289.     Line line;
  1290.  
  1291.     RETURN
  1292.     void
  1293.  
  1294.     DESCRIPTION
  1295.     Redraws one complete lines of text.
  1296.  
  1297.     NOTES
  1298.     - line must be a valid line from the text.
  1299.     - THIS IS A MACRO !
  1300.  
  1301. ******************************************************************************/
  1302.  
  1303.  
  1304. /*****************************************************************************
  1305.  
  1306.     NAME
  1307.     redraw_textlineseg
  1308.  
  1309.     PARAMETER
  1310.     Line   line;        The line
  1311.     Column start_column;    The column to start in
  1312.     Column end_column;    The column to end with (not included)
  1313.  
  1314.     RETURN
  1315.     void
  1316.  
  1317.     DESCRIPTION
  1318.     Redraws part of a lines in the text. We redraw all text between
  1319.     start_column and end_column including only the former.
  1320.  
  1321.     NOTE
  1322.     If used to update text that traverses a block-border, the colors
  1323.     of the drawn text will be wrong.
  1324.  
  1325. ******************************************************************************/
  1326.  
  1327. void redraw_textlineseg (Line line, Column start_column, Column end_column)
  1328. {
  1329.     setpen (line, start_column);
  1330.  
  1331.     if (line == Ep->line)
  1332.     redraw_lineseg (Current, ROWT(line - Ep->topline),
  1333.         start_column, end_column);
  1334.     else
  1335.     redraw_lineseg (GETTEXT(Ep,line), ROWT(line - Ep->topline),
  1336.         start_column, end_column);
  1337. } /* redraw_textlineseg */
  1338.  
  1339.  
  1340. /*****************************************************************************
  1341.  
  1342.     NAME
  1343.     redraw_lineseg
  1344.  
  1345.     PARAMETER
  1346.     ubyte * text;        The contents of the line
  1347.     ushort    y;        y-position to draw at
  1348.     Column    start_column;    The column to start in
  1349.     Column    end_column;    The column to end with (not included)
  1350.  
  1351.     RETURN
  1352.     void
  1353.  
  1354.     DESCRIPTION
  1355.     Redraws part of a lines in the text. We redraw all text between
  1356.     start_column and end_column including only the former.
  1357.  
  1358. ******************************************************************************/
  1359.  
  1360. void redraw_lineseg (ubyte * text, ushort y, Column start_column, Column end_column)
  1361. {
  1362.     RP *   rp         = Ep->win->RPort;
  1363.     int    len;
  1364.  
  1365.     if (Nsu) return;
  1366.  
  1367.     /* start-column visible ? */
  1368.  
  1369.     if (start_column < Ep->topcolumn)
  1370.     start_column = Ep->topcolumn;
  1371.  
  1372.     /* end-column visible ? */
  1373.  
  1374.     if (end_column > Ep->topcolumn + Columns)
  1375.     end_column = Ep->topcolumn + Columns;
  1376.  
  1377.     /* outside screen ? */
  1378.  
  1379.     if (start_column > end_column)
  1380.     return;
  1381.  
  1382.     /* get length of line beyond the start-column */
  1383.  
  1384.     len = strlen (text);
  1385.  
  1386.     if (len > end_column)
  1387.     len = end_column;
  1388.  
  1389.     len -= start_column;
  1390.  
  1391.     /* if there is still text ... */
  1392.  
  1393.     if (len > 0)
  1394.     {
  1395.     /* get contents of line at offset */
  1396.     text += start_column;
  1397.  
  1398.     while (*text == ' ' && len)
  1399.     {
  1400.         text ++;
  1401.         len --;
  1402.         start_column ++;
  1403.     }
  1404.  
  1405.     /* draw any text that is still to draw */
  1406.  
  1407.     if (len)
  1408.     {
  1409.         /* set gfxcursor */
  1410.  
  1411.         Move (rp, COLT(start_column - Ep->topcolumn), y);
  1412.  
  1413.         /* draw text */
  1414.  
  1415.         Text (rp, text, len);
  1416.     }
  1417.     }
  1418. } /* redraw_lineseg */
  1419.  
  1420.  
  1421. /******************************************************************************
  1422. *****  ENDE text.c
  1423. ******************************************************************************/
  1424.