home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / term43-source.lha / Extras / Source / term-Source.lha / termMarker.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-15  |  18.3 KB  |  841 lines

  1. /*
  2. **    termMarker.c
  3. **
  4. **    Text block marker routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* BM_Draw():
  13.      *
  14.      *    Redraw or remove marked regions.
  15.      */
  16.  
  17. VOID __regargs
  18. BM_Draw(struct BlockMarker *Marker,VOID (*Select)(struct BlockMarker *Marker,LONG Left,LONG Top,LONG Width,LONG Height))
  19. {
  20.         /* Is the first line the same as the last line? If so,
  21.          * continue and mark only single characters. Else,
  22.          * determine first line and column to mark and last
  23.          * line and last column.
  24.          */
  25.  
  26.     if(Marker -> FirstLine != Marker -> LastLine)
  27.     {
  28.         LONG    First    = Marker -> FirstLine - Marker -> Top,
  29.             Last    = Marker -> LastLine  - Marker -> Top,
  30.             Lines;
  31.  
  32.             /* Is the first line visible? If so, mark it. */
  33.  
  34.         if(First >= 0)
  35.             (*Select)(Marker,Marker -> FirstColumn,First,Marker -> Width - Marker -> FirstColumn,1);
  36.         else
  37.         {
  38.             (*Select)(Marker,0,0,Marker -> Width,1);
  39.  
  40.             First = 0;
  41.         }
  42.  
  43.             /* Is the last line visible? If so, mark it. */
  44.  
  45.         if(Last >= 0 && Last < Marker -> Height)
  46.             (*Select)(Marker,0,Last,Marker -> LastColumn,1);
  47.         else
  48.             Last = Marker -> Height;
  49.  
  50.             /* Determine the number of lines the selection spans. */
  51.  
  52.         if((Lines = Last - First - 1) > 0)
  53.             (*Select)(Marker,0,First + 1,Marker -> Width,Lines);
  54.     }
  55.     else
  56.     {
  57.             /* Is the first column different from the last column? */
  58.  
  59.         if(Marker -> FirstColumn != Marker -> LastColumn)
  60.         {
  61.                 /* Is the line visible? If so, mark it. */
  62.  
  63.             if(Marker -> Top <= Marker -> LastLine && Marker -> LastLine < Marker -> Top + Marker -> Height)
  64.                 (*Select)(Marker,Marker -> FirstColumn,Marker -> FirstLine - Marker -> Top,Marker -> LastColumn - Marker -> FirstColumn,1);
  65.         }
  66.     }
  67. }
  68.  
  69.     /* BM_ClearMark(struct BlockMarker *Marker):
  70.      *
  71.      *    Free block marker memory.
  72.      */
  73.  
  74. VOID __regargs
  75. BM_ClearMark(struct BlockMarker *Marker)
  76. {
  77.     BM_Draw(Marker,Marker -> Unselect);
  78.  
  79.     FreeVecPooled(Marker);
  80. }
  81.  
  82.     /* BM_SetMark():
  83.      *
  84.      *    Create block marker structure.
  85.      */
  86.  
  87. struct BlockMarker * __regargs
  88. BM_SetMark(APTR Object,VPTR Select,VPTR Unselect,LONG Width,LONG Height,LONG LeftEdge,LONG TopEdge,LONG Top,LONG Lines,LONG X,LONG Y,WORD TextFontWidth,WORD TextFontHeight)
  89. {
  90.     if(Height && Lines)
  91.     {
  92.         struct BlockMarker *Marker;
  93.  
  94.             /* Allocate marker buffer. */
  95.  
  96.         if(Marker = (struct BlockMarker *)AllocVecPooled(sizeof(struct BlockMarker),MEMF_ANY | MEMF_CLEAR))
  97.         {
  98.                 /* Fill in the object or canvas, usually a RastPort. */
  99.  
  100.             Marker -> Object    = Object;
  101.  
  102.                 /* Fill in the canvas left and top edge. */
  103.  
  104.             Marker -> LeftEdge    = LeftEdge;
  105.             Marker -> TopEdge    = TopEdge;
  106.  
  107.                 /* Fill in the select and unselect routines. */
  108.  
  109.             Marker -> Select    = Select;
  110.             Marker -> Unselect    = Unselect;
  111.  
  112.                 /* Fill in current display window top and number of
  113.                  * lines in the buffer.
  114.                  */
  115.  
  116.             Marker -> Top        = Top;
  117.             Marker -> Lines        = Lines;
  118.  
  119.                 /* Fill in width and height of the display window. */
  120.  
  121.             Marker -> Width        = Width;
  122.             Marker -> Height    = Height;
  123.  
  124.                 /* Fill in the marker anchor point. */
  125.  
  126.             Marker -> FirstColumn    = X;
  127.             Marker -> LastColumn    = X;
  128.             Marker -> FirstLine    = Y + Top;
  129.             Marker -> LastLine    = Y + Top;
  130.  
  131.                 /* Fill in current mouse position. */
  132.  
  133.             Marker -> LastX        = X;
  134.             Marker -> LastY        = Y;
  135.  
  136.             Marker -> OriginX    = X;
  137.             Marker -> OriginY    = Y + Top;
  138.  
  139.                 /* Remember text font dimensions. */
  140.  
  141.             Marker -> TextFontWidth    = TextFontWidth;
  142.             Marker -> TextFontHeight= TextFontHeight;
  143.  
  144.             Marker -> WriteMask    = ((struct RastPort *)Object) -> Mask;
  145.         }
  146.  
  147.             /* Return marker buffer. */
  148.  
  149.         return(Marker);
  150.     }
  151.     else
  152.         return(NULL);
  153. }
  154.  
  155.     /* BM_ExtendMark(struct BlockMarker *Marker,LONG X,LONG Y,LONG Delta):
  156.      *
  157.      *    Extend current block marker. This routine was
  158.      *    first written by me, but Martin Berndt rewrote it
  159.      *    after we both realised that it would not work
  160.      *    properly.
  161.      */
  162.  
  163. VOID __regargs
  164. BM_ExtendMark(struct BlockMarker *Marker,LONG X,LONG Y,LONG Delta)
  165. {
  166.     if(Marker -> LastX != X || Marker -> LastY != Y)
  167.     {
  168.         LONG    OldCharPos,NewCharPos,
  169.             CharStart,CharEnd,
  170.             CharOrigin,
  171.             OriginY,
  172.             Lines;
  173.         BYTE    Crossed;
  174.  
  175.             OriginY = Marker -> OriginY - Marker -> Top;
  176.  
  177.  
  178.             /* Deal with illegal X position. */
  179.  
  180.         if(X < 0)
  181.             X = 0;
  182.  
  183.         if(X > Marker -> Width)
  184.             X = Marker -> Width;
  185.  
  186.             /* Deal with illegal Y position. */
  187.  
  188.         if(Y < 0)
  189.             Y = 0;
  190.  
  191.         if(Y >= Marker -> Height)
  192.             Y = Marker -> Height - 1;
  193.  
  194.         if(Y + Marker -> Top >= Marker -> Lines)
  195.             Y = Marker -> Lines - Marker -> Top - 1;
  196.  
  197.             /* Is the Y position larger than the last line? If so,
  198.              * truncate it.
  199.              */
  200.  
  201.         if(Y > Marker -> Lines - Marker -> Top)
  202.             Y -= Marker -> Lines - Marker -> Top;
  203.  
  204.             /* Select the text. */
  205.  
  206.         OldCharPos    = (Marker -> LastY + Marker -> Top) * Marker -> Width + Marker -> LastX;
  207.         NewCharPos    = (Y + Marker -> Top) * Marker -> Width + X;
  208.  
  209.         CharStart    = Marker -> FirstLine * Marker -> Width + Marker -> FirstColumn;
  210.         CharEnd        = Marker -> LastLine * Marker -> Width + Marker -> LastColumn;
  211.  
  212.         CharOrigin    = Marker -> OriginY * Marker -> Width + Marker -> OriginX;
  213.  
  214.         Crossed        = (OldCharPos < CharOrigin) ^ (NewCharPos < CharOrigin);
  215.  
  216.         if(NewCharPos > OldCharPos)
  217.         {
  218.             if(Delta && Y < OriginY)
  219.                 (*Marker -> Select)(Marker,0,Y,Marker -> Width,1);
  220.  
  221.             if(Crossed)
  222.             {
  223.                 if((Lines = OriginY - Marker -> LastY - 1) >= 0)
  224.                 {
  225.                     (*Marker -> Unselect)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
  226.  
  227.                     if(Lines > 0)
  228.                         (*Marker -> Unselect)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
  229.  
  230.                     if(Marker -> OriginX)
  231.                         (*Marker -> Unselect)(Marker,0,OriginY,Marker -> OriginX,1);
  232.                 }
  233.                 else
  234.                 {
  235.                     if(Delta)
  236.                         (*Marker -> Unselect)(Marker,0,OriginY,Marker -> LastX,1);
  237.                     else
  238.                         (*Marker -> Unselect)(Marker,Marker -> LastX,OriginY,Marker -> OriginX - Marker -> LastX,1);
  239.                 }
  240.  
  241.                 Marker -> FirstColumn    = Marker -> OriginX;
  242.                 Marker -> FirstLine     = Marker -> OriginY;
  243.  
  244.                 Marker -> LastX        = Marker -> OriginX;
  245.                 Marker -> LastY        = OriginY;
  246.             }
  247.             else
  248.             {
  249.                 if(OldCharPos < CharOrigin)
  250.                 {
  251.                     if((Lines = Y - Marker -> LastY - 1) >= 0)
  252.                     {
  253.                         (*Marker -> Unselect)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
  254.  
  255.                         if(Lines > 0)
  256.                             (*Marker -> Unselect)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
  257.  
  258.                         (*Marker -> Unselect)(Marker,0,Y,X,1);
  259.                     }
  260.                     else
  261.                     {
  262.                         if(Delta)
  263.                             (*Marker -> Unselect)(Marker,0,Y,X,1);
  264.                         else
  265.                             (*Marker -> Unselect)(Marker,Marker -> LastX,Y,X - Marker -> LastX,1);
  266.                     }
  267.  
  268.                     Marker -> FirstColumn    = X;
  269.                     Marker -> FirstLine    = Y + Marker -> Top;
  270.                 }
  271.             }
  272.  
  273.             if(NewCharPos > CharEnd)
  274.             {
  275.                 if((Lines = Y - Marker -> LastY - 1) >= 0)
  276.                 {
  277.                     (*Marker -> Select)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
  278.  
  279.                     if(Lines > 0)
  280.                         (*Marker -> Select)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
  281.  
  282.                     (*Marker -> Select)(Marker,0,Y,X,1);
  283.                 }
  284.                 else
  285.                 {
  286.                     if(Delta)
  287.                         (*Marker -> Select)(Marker,0,Y,X,1);
  288.                     else
  289.                         (*Marker -> Select)(Marker,Marker -> LastX,Y,X - Marker -> LastX,1);
  290.                 }
  291.  
  292.                 Marker -> LastColumn    = X;
  293.                 Marker -> LastLine    = Y + Marker -> Top;
  294.             }
  295.         }
  296.         else
  297.         {
  298.             if(Delta && Y > OriginY)
  299.                 (*Marker -> Select)(Marker,0,Y,Marker -> Width,1);
  300.  
  301.             if(Crossed)
  302.             {
  303.                 if((Lines = Marker -> LastY - OriginY - 1) >= 0)
  304.                 {
  305.                     (*Marker -> Unselect)(Marker,0,Marker -> LastY,Marker -> LastX,1);
  306.  
  307.                     if(Lines > 0)
  308.                         (*Marker -> Unselect)(Marker,0,OriginY + 1,Marker -> Width,Lines);
  309.  
  310.                     (*Marker -> Unselect)(Marker,Marker -> OriginX,OriginY,Marker -> Width - Marker -> OriginX,1);
  311.                 }
  312.                 else
  313.                 {
  314.                     if(Delta)
  315.                         (*Marker -> Unselect)(Marker,Marker -> LastX,OriginY,Marker -> Width - Marker -> LastX,1);
  316.                     else
  317.                         (*Marker -> Unselect)(Marker,Marker -> OriginX,OriginY,Marker -> LastX - Marker -> OriginX,1);
  318.                 }
  319.  
  320.                 Marker -> LastColumn    = Marker -> OriginX;
  321.                 Marker -> LastLine    = Marker -> OriginY;
  322.  
  323.                 Marker -> LastX        = Marker -> OriginX;
  324.                 Marker -> LastY        = OriginY;
  325.             }
  326.             else
  327.             {
  328.                 if(OldCharPos > CharOrigin)
  329.                 {
  330.                     if((Lines = Marker -> LastY - Y - 1) >= 0)
  331.                     {
  332.                         if(Marker -> LastX)
  333.                             (*Marker -> Unselect)(Marker,0,Marker -> LastY,Marker -> LastX,1);
  334.  
  335.                         if(Lines > 0)
  336.                             (*Marker -> Unselect)(Marker,0,Y + 1,Marker -> Width,Lines);
  337.  
  338.                         (*Marker -> Unselect)(Marker,X,Y,Marker -> Width - X,1);
  339.                     }
  340.                     else
  341.                     {
  342.                         if(Delta)
  343.                             (*Marker -> Unselect)(Marker,X,Y,Marker -> Width - X,1);
  344.                         else
  345.                             (*Marker -> Unselect)(Marker,X,Y,Marker -> LastX - X,1);
  346.                     }
  347.  
  348.                     Marker -> LastColumn    = X;
  349.                     Marker -> LastLine    = Y + Marker -> Top;
  350.                 }
  351.             }
  352.  
  353.             if(NewCharPos < CharStart)
  354.             {
  355.                 if((Lines = Marker -> LastY - Y - 1) >= 0)
  356.                 {
  357.                     if(Marker -> LastX)
  358.                         (*Marker -> Select)(Marker,0,Marker -> LastY,Marker -> LastX,1);
  359.  
  360.                     if(Lines > 0)
  361.                         (*Marker -> Select)(Marker,0,Y + 1,Marker -> Width,Lines);
  362.  
  363.                     (*Marker -> Select)(Marker,X,Y,Marker -> Width - X,1);
  364.                 }
  365.                 else
  366.                 {
  367.                     if(Delta)
  368.                         (*Marker -> Select)(Marker,X,Y,Marker -> Width - X,1);
  369.                     else
  370.                         (*Marker -> Select)(Marker,X,Y,Marker -> LastX - X,1);
  371.                 }
  372.  
  373.                 Marker -> FirstColumn    = X;
  374.                 Marker -> FirstLine    = Y + Marker -> Top;
  375.             }
  376.         }
  377.  
  378.         Marker -> LastX = X;
  379.         Marker -> LastY = Y;
  380.     }
  381. }
  382.  
  383.  
  384.     /* ToggleSelect(struct BlockMarker *Marker,LONG Left,LONG Top,LONG Width,LONG Height):
  385.      *
  386.      *    Toggle selection subroutine.
  387.      */
  388.  
  389. VOID
  390. ToggleSelect(struct BlockMarker *Marker,LONG Left,LONG Top,LONG Width,LONG Height)
  391. {
  392.     struct RastPort *RPort = (struct RastPort *)Marker -> Object;
  393.  
  394.     if(Width && Height)
  395.     {
  396.         UWORD    OldAPen    = ReadAPen(RPort),
  397.             OldBPen    = ReadBPen(RPort),
  398.             OldDrMd    = ReadDrMd(RPort),
  399.             Mask;
  400.  
  401.         Left    = Marker -> LeftEdge + Left * Marker -> TextFontWidth;
  402.         Top    = Marker -> TopEdge + Top * Marker -> TextFontHeight;
  403.  
  404.         if(Kick30)
  405.         {
  406.             Mask = (1L << GetBitMapAttr(RPort -> BitMap,BMA_DEPTH)) - 1;
  407.  
  408.             SetABPenDrMd(RPort,Mask,OldBPen,JAM1 | COMPLEMENT);
  409.  
  410.             RectFill(RPort,Left,Top,Left + Width * Marker -> TextFontWidth - 1,Top + Height * Marker -> TextFontHeight - 1);
  411.  
  412.             SetABPenDrMd(RPort,OldAPen,OldBPen,OldDrMd);
  413.         }
  414.         else
  415.         {
  416.             Mask = (1L << RPort -> BitMap -> Depth) - 1;
  417.  
  418.             SetAPen(RPort,Mask);
  419.             SetDrMd(RPort,JAM1 | COMPLEMENT);
  420.  
  421.             RectFill(RPort,Left,Top,Left + Width * Marker -> TextFontWidth - 1,Top + Height * Marker -> TextFontHeight - 1);
  422.  
  423.             SetAPen(RPort,OldAPen);
  424.             SetDrMd(RPort,OldDrMd);
  425.         }
  426.     }
  427. }
  428.  
  429.     /* WriteTrimmedString(struct IFFHandle *Handle,STRPTR String,LONG Len,BOOL NeedClipConversion):
  430.      *
  431.      *    Write a string to the clipboard, sans trailing spaces.
  432.      */
  433.  
  434. VOID __regargs
  435. WriteTrimmedString(struct IFFHandle *Handle,STRPTR String,LONG Len,BOOL NeedClipConversion)
  436. {
  437.     while(Len > 0 && String[Len - 1] == ' ')
  438.         Len--;
  439.  
  440.     if(Len)
  441.     {
  442.         if(NeedClipConversion)
  443.         {
  444.             UBYTE    Buffer[256];
  445.             LONG    Size,i;
  446.             STRPTR    Dest;
  447.             UBYTE    c;
  448.  
  449.             do
  450.             {
  451.                 Size = MIN(Len,256);
  452.  
  453.                 Len -= Size;
  454.  
  455.                 for(i = 0, Dest = Buffer ; i < Size ; i++)
  456.                 {
  457.                     if(c = ISOConversion[*String++])
  458.                         *Dest++ = c;
  459.                     else
  460.                         *Dest++ = ' ';
  461.                 }
  462.  
  463.                 if(Dest > Buffer)
  464.                 {
  465.                     Size = (ULONG)Dest - (ULONG)&Buffer[0];
  466.  
  467.                     while(Size > 0 && Buffer[Size - 1] == ' ')
  468.                         Size--;
  469.  
  470.                     if(Size > 0)
  471.                         WriteChunkBytes(Handle,Buffer,Size);
  472.                 }
  473.             }
  474.             while(Len > 0);
  475.         }
  476.         else
  477.             WriteChunkBytes(Handle,String,Len);
  478.     }
  479. }
  480.  
  481.     /* ClipPage(struct BlockMarker *Marker,BOOL Append,BOOL NeedClipConversion):
  482.      *
  483.      *    Send the entire marked page to the clipboard.
  484.      */
  485.  
  486. STATIC VOID __inline
  487. ClipPage(struct BlockMarker *Marker,BOOL Append,BOOL NeedClipConversion)
  488. {
  489.     struct IFFHandle    *Handle;
  490.     APTR             Buffer;
  491.     LONG             Size;
  492.  
  493.     if(Append)
  494.         GetClipContents(Config -> ClipConfig -> ClipboardUnit,&Buffer,&Size);
  495.     else
  496.     {
  497.         Buffer    = NULL;
  498.         Size    = 0;
  499.     }
  500.  
  501.     if(Handle = AllocIFF())
  502.     {
  503.         if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config -> ClipConfig -> ClipboardUnit))
  504.         {
  505.             InitIFFasClip(Handle);
  506.  
  507.             if(!OpenIFF(Handle,IFFF_WRITE))
  508.             {
  509.                 if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
  510.                 {
  511.                     if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
  512.                     {
  513.                         LONG    Lines = Marker -> LastLine - Marker -> FirstLine - 1,
  514.                             i;
  515.  
  516.                         if(Buffer)
  517.                         {
  518.                             WriteChunkBytes(Handle,Buffer,Size);
  519.  
  520.                             FreeVecPooled(Buffer);
  521.                         }
  522.  
  523.                         WriteTrimmedString(Handle,&Raster[RasterWidth * Marker -> FirstLine + Marker -> FirstColumn],Marker -> Width - Marker -> FirstColumn,NeedClipConversion);
  524.                         WriteChunkBytes(Handle,"\n",1);
  525.  
  526.                         if(Lines > 0)
  527.                         {
  528.                             STRPTR Line = &Raster[(Marker -> FirstLine + 1) * RasterWidth];
  529.  
  530.                             for(i = 0 ; i < Lines ; i++)
  531.                             {
  532.                                 WriteTrimmedString(Handle,Line,Marker -> Width,NeedClipConversion);
  533.                                 WriteChunkBytes(Handle,"\n",1);
  534.  
  535.                                 Line += RasterWidth;
  536.                             }
  537.                         }
  538.  
  539.                         WriteTrimmedString(Handle,&Raster[RasterWidth * Marker -> LastLine],Marker -> LastColumn,NeedClipConversion);
  540.                         WriteChunkBytes(Handle,"\n",1);
  541.  
  542.                         PopChunk(Handle);
  543.                     }
  544.  
  545.                     PopChunk(Handle);
  546.                 }
  547.  
  548.                 CloseIFF(Handle);
  549.             }
  550.  
  551.             CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
  552.         }
  553.  
  554.         FreeIFF(Handle);
  555.     }
  556. }
  557.  
  558.     /* MarkWord(LONG MouseX,LONG MouseY):
  559.      *
  560.      *    Mark a single word on the main screen (double-click).
  561.      */
  562.  
  563. VOID __regargs
  564. MarkWord(LONG MouseX,LONG MouseY)
  565. {
  566.     LONG FirstX,FirstY;
  567.  
  568.     FirstX = MouseX / TextFontWidth;
  569.     FirstY = MouseY / TextFontHeight;
  570.  
  571.     if(FirstX > LastColumn)
  572.         FirstX = LastColumn;
  573.  
  574.     if(FirstY > LastLine)
  575.         FirstY = LastLine;
  576.  
  577.     ObtainSemaphore(RasterSemaphore);
  578.  
  579.     if(Raster[FirstY * RasterWidth + FirstX] != ' ' && Raster[FirstY * RasterWidth + FirstX])
  580.     {
  581.         STRPTR    Line = &Raster[FirstY * RasterWidth];
  582.         LONG    LastX;
  583.  
  584.         LastX = FirstX;
  585.  
  586.         while(FirstX > 0 && Line[FirstX - 1] != ' ')
  587.             FirstX--;
  588.  
  589.         while(LastX < LastColumn && Line[LastX + 1] != ' ')
  590.             LastX++;
  591.  
  592.         ObtainSemaphore(&TerminalSemaphore);
  593.  
  594.         if(WindowMarker = BM_SetMark(Window -> RPort,ToggleSelect,ToggleSelect,LastColumn + 1,LastLine + 1,WindowLeft,WindowTop,0,LastLine + 1,FirstX,FirstY,TextFontWidth,TextFontHeight))
  595.         {
  596.             SetMask(RPort,DepthMask);
  597.  
  598.             Marking = TRUE;
  599.  
  600.             ReportMouse(TRUE,Window);
  601.  
  602.             BM_ExtendMark(WindowMarker,LastX + 1,FirstY,0);
  603.  
  604.             SetClipMenu(TRUE);
  605.         }
  606.  
  607.         ReleaseSemaphore(&TerminalSemaphore);
  608.     }
  609.  
  610.     ReleaseSemaphore(RasterSemaphore);
  611. }
  612.  
  613.     /* SetMarker(LONG MouseX,LONG MouseY):
  614.      *
  615.      *    Anchor a marker to the current mouse position.
  616.      */
  617.  
  618. VOID __regargs
  619. SetMarker(LONG MouseX,LONG MouseY)
  620. {
  621.     LONG FirstX,FirstY;
  622.  
  623.     FirstX = MouseX / TextFontWidth;
  624.     FirstY = MouseY / TextFontHeight;
  625.  
  626.     if(FirstX > LastColumn)
  627.         FirstX = LastColumn;
  628.  
  629.     if(FirstY > LastLine)
  630.         FirstY = LastLine;
  631.  
  632.     ObtainSemaphore(&TerminalSemaphore);
  633.  
  634.     if(WindowMarker = BM_SetMark(Window -> RPort,ToggleSelect,ToggleSelect,LastColumn + 1,LastLine + 1,WindowLeft,WindowTop,0,LastLine + 1,FirstX,FirstY,TextFontWidth,TextFontHeight))
  635.     {
  636.         SetMask(RPort,DepthMask);
  637.  
  638.         Marking = TRUE;
  639.  
  640.         ReportMouse(TRUE,Window);
  641.  
  642.         SetClipMenu(TRUE);
  643.     }
  644.  
  645.     ReleaseSemaphore(&TerminalSemaphore);
  646. }
  647.  
  648.     /* MoveMarker(LONG MouseX,LONG MouseY):
  649.      *
  650.      *    Move the marker with the mouse.
  651.      */
  652.  
  653. VOID __regargs
  654. MoveMarker(LONG MouseX,LONG MouseY)
  655. {
  656.     if(WindowMarker)
  657.     {
  658.         ObtainSemaphore(&TerminalSemaphore);
  659.  
  660.         BM_ExtendMark(WindowMarker,(MouseX + TextFontWidth - 1) / TextFontWidth,MouseY / TextFontHeight,0);
  661.  
  662.         ReleaseSemaphore(&TerminalSemaphore);
  663.     }
  664. }
  665.  
  666.     /* DropMarker():
  667.      *
  668.      *    Drop the window marker, restore the window contents.
  669.      */
  670.  
  671. VOID
  672. DropMarker()
  673. {
  674.     if(WindowMarker)
  675.     {
  676.         struct RastPort    *RPort    = WindowMarker -> Object;
  677.         UBYTE         Mask    = WindowMarker -> WriteMask;
  678.  
  679.         ObtainSemaphore(&TerminalSemaphore);
  680.  
  681.         BM_ClearMark(WindowMarker);
  682.  
  683.         ReleaseSemaphore(&TerminalSemaphore);
  684.  
  685.         SetMask(RPort,Mask);
  686.  
  687.         ReportMouse(FALSE,Window);
  688.  
  689.         WindowMarker = NULL;
  690.  
  691.         Marking = FALSE;
  692.  
  693.         SetClipMenu(FALSE);
  694.     }
  695. }
  696.  
  697.     /* FreeMarker():
  698.      *
  699.      *    Free the main window marker.
  700.      */
  701.  
  702. VOID
  703. FreeMarker()
  704. {
  705.     if(WindowMarker)
  706.     {
  707.         struct RastPort    *RPort    = WindowMarker -> Object;
  708.         UBYTE         Mask    = WindowMarker -> WriteMask;
  709.  
  710.         FreeVecPooled(WindowMarker);
  711.  
  712.         WindowMarker = NULL;
  713.  
  714.         SetMask(RPort,Mask);
  715.  
  716.         ReportMouse(FALSE,Window);
  717.  
  718.         Marking = FALSE;
  719.  
  720.         SetClipMenu(FALSE);
  721.     }
  722. }
  723.  
  724.     /* ClipMarker(BYTE Append):
  725.      *
  726.      *    Transfer the marked area to the clipboard.
  727.      */
  728.  
  729. VOID __regargs
  730. ClipMarker(BYTE Append)
  731. {
  732.     if(WindowMarker)
  733.     {
  734.         ObtainSemaphore(RasterSemaphore);
  735.  
  736.         SetWait(Window);
  737.  
  738.         if(WindowMarker -> FirstColumn == WindowMarker -> Width)
  739.         {
  740.             WindowMarker -> FirstLine++;
  741.  
  742.             WindowMarker -> FirstColumn = 0;
  743.         }
  744.  
  745.         if(WindowMarker -> LastColumn == 0)
  746.         {
  747.             WindowMarker -> LastLine--;
  748.  
  749.             WindowMarker -> LastColumn = WindowMarker -> Width;
  750.         }
  751.  
  752.         if(WindowMarker -> FirstLine <= WindowMarker -> LastLine)
  753.         {
  754.             if(WindowMarker -> FirstLine != WindowMarker -> LastLine || WindowMarker -> FirstColumn != WindowMarker -> LastColumn)
  755.             {
  756.                 if(WindowMarker -> FirstLine == WindowMarker -> LastLine)
  757.                 {
  758.                     if(Config -> TerminalConfig -> FontMode != FONT_STANDARD)
  759.                     {
  760.                         UBYTE    Buffer[256];
  761.                         LONG    Len,i;
  762.                         STRPTR    Dest,
  763.                             Source    = &Raster[RasterWidth * WindowMarker -> FirstLine + WindowMarker -> FirstColumn];
  764.                         LONG    Size    = WindowMarker -> LastColumn - WindowMarker -> FirstColumn;
  765.                         UBYTE    c;
  766.  
  767.                         if(Append)
  768.                         {
  769.                             do
  770.                             {
  771.                                 Len = MIN(Size,256);
  772.  
  773.                                 Size -= Len;
  774.  
  775.                                 for(i = 0, Dest = Buffer ; i < Len ; i++)
  776.                                 {
  777.                                     if(c = ISOConversion[*Source++])
  778.                                         *Dest++ = c;
  779.                                     else
  780.                                         *Dest++ = ' ';
  781.                                 }
  782.  
  783.                                 if(Dest > Buffer)
  784.                                     AddClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  785.                             }
  786.                             while(Size > 0);
  787.                         }
  788.                         else
  789.                         {
  790.                             BOOL FirstWrite = TRUE;
  791.  
  792.                             do
  793.                             {
  794.                                 Len = MIN(Size,256);
  795.  
  796.                                 Size -= Len;
  797.  
  798.                                 for(i = 0, Dest = Buffer ; i < Len ; i++)
  799.                                 {
  800.                                     if(c = ISOConversion[*Source++])
  801.                                         *Dest++ = c;
  802.                                     else
  803.                                         *Dest++ = ' ';
  804.                                 }
  805.  
  806.                                 if(Dest > Buffer)
  807.                                 {
  808.                                     if(FirstWrite)
  809.                                     {
  810.                                         FirstWrite = FALSE;
  811.  
  812.                                         SaveClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  813.                                     }
  814.                                     else
  815.                                         AddClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  816.                                 }
  817.                             }
  818.                             while(Size > 0);
  819.                         }
  820.                     }
  821.                     else
  822.                     {
  823.                         if(Append)
  824.                             AddClip(&Raster[RasterWidth * WindowMarker -> FirstLine + WindowMarker -> FirstColumn],WindowMarker -> LastColumn - WindowMarker -> FirstColumn);
  825.                         else
  826.                             SaveClip(&Raster[RasterWidth * WindowMarker -> FirstLine + WindowMarker -> FirstColumn],WindowMarker -> LastColumn - WindowMarker -> FirstColumn);
  827.                     }
  828.                 }
  829.                 else
  830.                     ClipPage(WindowMarker,Append,Config -> TerminalConfig -> FontMode != FONT_STANDARD);
  831.             }
  832.         }
  833.  
  834.         ClrWait(Window);
  835.  
  836.         ReleaseSemaphore(RasterSemaphore);
  837.  
  838.         DropMarker();
  839.     }
  840. }
  841.