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