home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term23_2.lha / Source_Code / termSource / termMarker.c < prev    next >
C/C++ Source or Header  |  1992-08-22  |  14KB  |  635 lines

  1. /*
  2. **    $Id: termMarker.c,v 1.4 92/08/15 20:14:43 olsen Sta Locker: olsen $
  3. **    $Revision: 1.4 $
  4. **    $Date: 92/08/15 20:14:43 $
  5. **
  6. **    Text block marker routines
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* BM_Draw():
  15.      *
  16.      *    Redraw or remove marked regions.
  17.      */
  18.  
  19. VOID
  20. BM_Draw(struct BlockMarker *Marker,VOID (*Select)(struct BlockMarker *Marker,WORD Left,WORD Top,WORD Width,WORD Height))
  21. {
  22.         /* Is the first line the same as the last line? If so,
  23.          * continue and mark only single characters. Else,
  24.          * determine first line and column to mark and last
  25.          * line and last column.
  26.          */
  27.  
  28.     if(Marker -> FirstLine != Marker -> LastLine)
  29.     {
  30.         WORD    First    = Marker -> FirstLine - Marker -> Top,
  31.             Last    = Marker -> LastLine  - Marker -> Top,
  32.             Lines;
  33.  
  34.             /* Is the first line visible? If so, mark it. */
  35.  
  36.         if(First >= 0)
  37.             (*Select)(Marker,Marker -> FirstColumn,First,Marker -> Width - Marker -> FirstColumn,1);
  38.         else
  39.         {
  40.             (*Select)(Marker,0,0,Marker -> Width,1);
  41.  
  42.             First = 0;
  43.         }
  44.  
  45.             /* Is the last line visible? If so, mark it. */
  46.  
  47.         if(Last >= 0 && Last < Marker -> Height)
  48.             (*Select)(Marker,0,Last,Marker -> LastColumn,1);
  49.         else
  50.             Last = Marker -> Height;
  51.  
  52.             /* Determine the number of lines the selection spans. */
  53.  
  54.         if((Lines = Last - First - 1) > 0)
  55.             (*Select)(Marker,0,First + 1,Marker -> Width,Lines);
  56.     }
  57.     else
  58.     {
  59.             /* Is the first column different from the last column? */
  60.  
  61.         if(Marker -> FirstColumn != Marker -> LastColumn)
  62.         {
  63.                 /* Is the line visible? If so, mark it. */
  64.  
  65.             if(Marker -> Top <= Marker -> LastLine && Marker -> LastLine < Marker -> Top + Marker -> Height)
  66.                 (*Select)(Marker,Marker -> FirstColumn,Marker -> FirstLine - Marker -> Top,Marker -> LastColumn - Marker -> FirstColumn,1);
  67.         }
  68.     }
  69. }
  70.  
  71.     /* BM_ClearMark(struct BlockMarker *Marker):
  72.      *
  73.      *    Free block marker memory.
  74.      */
  75.  
  76. VOID
  77. BM_ClearMark(struct BlockMarker *Marker)
  78. {
  79.     BM_Draw(Marker,Marker -> Unselect);
  80.  
  81.     FreeVec(Marker);
  82. }
  83.  
  84.     /* BM_SetMark():
  85.      *
  86.      *    Create block marker structure.
  87.      */
  88.  
  89. struct BlockMarker *
  90. BM_SetMark(APTR Object,APTR Select,APTR Unselect,WORD Width,WORD Height,WORD Top,WORD Lines,WORD X,WORD Y,WORD TextFontWidth,WORD TextFontHeight)
  91. {
  92.     if(Height && Lines)
  93.     {
  94.         struct BlockMarker *Marker;
  95.  
  96.             /* Allocate marker buffer. */
  97.  
  98.         if(Marker = (struct BlockMarker *)AllocVec(sizeof(struct BlockMarker),MEMF_ANY | MEMF_CLEAR))
  99.         {
  100.                 /* Fill in the object or canvas, usually a RastPort. */
  101.  
  102.             Marker -> Object    = Object;
  103.  
  104.                 /* Fill in the select and unselect routines. */
  105.  
  106.             Marker -> Select    = Select;
  107.             Marker -> Unselect    = Unselect;
  108.  
  109.                 /* Fill in current display window top and number of
  110.                  * lines in the buffer.
  111.                  */
  112.  
  113.             Marker -> Top        = Top;
  114.             Marker -> Lines        = Lines;
  115.  
  116.                 /* Fill in width and height of the display window. */
  117.  
  118.             Marker -> Width        = Width;
  119.             Marker -> Height    = Height;
  120.  
  121.                 /* Fill in the marker anchor point. */
  122.  
  123.             Marker -> FirstColumn    = X;
  124.             Marker -> LastColumn    = X;
  125.             Marker -> FirstLine    = Y + Top;
  126.             Marker -> LastLine    = Y + Top;
  127.  
  128.                 /* Fill in current mouse position. */
  129.  
  130.             Marker -> LastX        = X;
  131.             Marker -> LastY        = Y;
  132.  
  133.             Marker -> OriginX    = X;
  134.             Marker -> OriginY    = Y + Top;
  135.  
  136.                 /* Remember text font dimensions. */
  137.  
  138.             Marker -> TextFontWidth    = TextFontWidth;
  139.             Marker -> TextFontHeight= TextFontHeight;
  140.         }
  141.  
  142.             /* Return marker buffer. */
  143.  
  144.         return(Marker);
  145.     }
  146.     else
  147.         return(NULL);
  148. }
  149.  
  150.     /* BM_ExtendMark(struct BlockMarker *Marker,WORD X,WORD Y,WORD Delta):
  151.      *
  152.      *    Extend current block marker. This routine was
  153.      *    first written by me, but Martin Berndt rewrote it
  154.      *    after we both realised that it would not work
  155.      *    properly.
  156.      */
  157.  
  158. VOID
  159. BM_ExtendMark(struct BlockMarker *Marker,WORD X,WORD Y,WORD Delta)
  160. {
  161.     if(Marker -> LastX != X || Marker -> LastY != Y)
  162.     {
  163.         LONG    OldCharPos,NewCharPos,
  164.             CharStart,CharEnd,
  165.             CharOrigin,
  166.             OriginY,
  167.             Lines;
  168.         BYTE    Crossed;
  169.  
  170.             OriginY = Marker -> OriginY - Marker -> Top;
  171.  
  172.  
  173.             /* Deal with illegal X position. */
  174.  
  175.         if(X < 0)
  176.             X = 0;
  177.  
  178.         if(X > Marker -> Width)
  179.             X = Marker -> Width;
  180.  
  181.             /* Deal with illegal Y position. */
  182.  
  183.         if(Y < 0)
  184.             Y = 0;
  185.  
  186.         if(Y >= Marker -> Height)
  187.             Y = Marker -> Height - 1;
  188.  
  189.         if(Y + Marker -> Top >= Marker -> Lines)
  190.             Y = Marker -> Lines - Marker -> Top - 1;
  191.  
  192.             /* Is the Y position larger than the last line? If so,
  193.              * truncate it.
  194.              */
  195.  
  196.         if(Y > Marker -> Lines - Marker -> Top)
  197.             Y -= Marker -> Lines - Marker -> Top;
  198.  
  199.             /* Select the text. */
  200.  
  201.         OldCharPos    = (Marker -> LastY + Marker -> Top) * Marker -> Width + Marker -> LastX;
  202.         NewCharPos    = (Y + Marker -> Top) * Marker -> Width + X;
  203.  
  204.         CharStart    = Marker -> FirstLine * Marker -> Width + Marker -> FirstColumn;
  205.         CharEnd        = Marker -> LastLine * Marker -> Width + Marker -> LastColumn;
  206.  
  207.         CharOrigin    = Marker -> OriginY * Marker -> Width + Marker -> OriginX;
  208.  
  209.         Crossed        = (OldCharPos < CharOrigin) ^ (NewCharPos < CharOrigin);
  210.  
  211.         if(NewCharPos > OldCharPos)
  212.         {
  213.             if(Delta && Y < OriginY)
  214.                 (*Marker -> Select)(Marker,0,Y,Marker -> Width,1);
  215.  
  216.             if(Crossed)
  217.             {
  218.                 if((Lines = OriginY - Marker -> LastY - 1) >= 0)
  219.                 {
  220.                     (*Marker -> Unselect)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
  221.  
  222.                     if(Lines > 0)
  223.                         (*Marker -> Unselect)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
  224.  
  225.                     if(Marker -> OriginX)
  226.                         (*Marker -> Unselect)(Marker,0,OriginY,Marker -> OriginX,1);
  227.                 }
  228.                 else
  229.                 {
  230.                     if(Delta)
  231.                         (*Marker -> Unselect)(Marker,0,OriginY,Marker -> LastX,1);
  232.                     else
  233.                         (*Marker -> Unselect)(Marker,Marker -> LastX,OriginY,Marker -> OriginX - Marker -> LastX,1);
  234.                 }
  235.  
  236.                 Marker -> FirstColumn    = Marker -> OriginX;
  237.                 Marker -> FirstLine     = Marker -> OriginY;
  238.  
  239.                 Marker -> LastX        = Marker -> OriginX;
  240.                 Marker -> LastY        = OriginY;
  241.             }
  242.             else
  243.             {
  244.                 if(OldCharPos < CharOrigin)
  245.                 {
  246.                     if((Lines = Y - Marker -> LastY - 1) >= 0)
  247.                     {
  248.                         (*Marker -> Unselect)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
  249.  
  250.                         if(Lines > 0)
  251.                             (*Marker -> Unselect)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
  252.  
  253.                         (*Marker -> Unselect)(Marker,0,Y,X,1);
  254.                     }
  255.                     else
  256.                     {
  257.                         if(Delta)
  258.                             (*Marker -> Unselect)(Marker,0,Y,X,1);
  259.                         else
  260.                             (*Marker -> Unselect)(Marker,Marker -> LastX,Y,X - Marker -> LastX,1);
  261.                     }
  262.  
  263.                     Marker -> FirstColumn    = X;
  264.                     Marker -> FirstLine    = Y + Marker -> Top;
  265.                 }
  266.             }
  267.  
  268.             if(NewCharPos > CharEnd)
  269.             {
  270.                 if((Lines = Y - Marker -> LastY - 1) >= 0)
  271.                 {
  272.                     (*Marker -> Select)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
  273.  
  274.                     if(Lines > 0)
  275.                         (*Marker -> Select)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
  276.  
  277.                     (*Marker -> Select)(Marker,0,Y,X,1);
  278.                 }
  279.                 else
  280.                 {
  281.                     if(Delta)
  282.                         (*Marker -> Select)(Marker,0,Y,X,1);
  283.                     else
  284.                         (*Marker -> Select)(Marker,Marker -> LastX,Y,X - Marker -> LastX,1);
  285.                 }
  286.  
  287.                 Marker -> LastColumn    = X;
  288.                 Marker -> LastLine    = Y + Marker -> Top;
  289.             }
  290.         }
  291.         else
  292.         {
  293.             if(Delta && Y > OriginY)
  294.                 (*Marker -> Select)(Marker,0,Y,Marker -> Width,1);
  295.  
  296.             if(Crossed)
  297.             {
  298.                 if((Lines = Marker -> LastY - OriginY - 1) >= 0)
  299.                 {
  300.                     (*Marker -> Unselect)(Marker,0,Marker -> LastY,Marker -> LastX,1);
  301.  
  302.                     if(Lines > 0)
  303.                         (*Marker -> Unselect)(Marker,0,OriginY + 1,Marker -> Width,Lines);
  304.  
  305.                     (*Marker -> Unselect)(Marker,Marker -> OriginX,OriginY,Marker -> Width - Marker -> OriginX,1);
  306.                 }
  307.                 else
  308.                 {
  309.                     if(Delta)
  310.                         (*Marker -> Unselect)(Marker,Marker -> LastX,OriginY,Marker -> Width - Marker -> LastX,1);
  311.                     else
  312.                         (*Marker -> Unselect)(Marker,Marker -> OriginX,OriginY,Marker -> LastX - Marker -> OriginX,1);
  313.                 }
  314.  
  315.                 Marker -> LastColumn    = Marker -> OriginX;
  316.                 Marker -> LastLine    = Marker -> OriginY;
  317.  
  318.                 Marker -> LastX        = Marker -> OriginX;
  319.                 Marker -> LastY        = OriginY;
  320.             }
  321.             else
  322.             {
  323.                 if(OldCharPos > CharOrigin)
  324.                 {
  325.                     if((Lines = Marker -> LastY - Y - 1) >= 0)
  326.                     {
  327.                         if(Marker -> LastX)
  328.                             (*Marker -> Unselect)(Marker,0,Marker -> LastY,Marker -> LastX,1);
  329.  
  330.                         if(Lines > 0)
  331.                             (*Marker -> Unselect)(Marker,0,Y + 1,Marker -> Width,Lines);
  332.  
  333.                         (*Marker -> Unselect)(Marker,X,Y,Marker -> Width - X,1);
  334.                     }
  335.                     else
  336.                     {
  337.                         if(Delta)
  338.                             (*Marker -> Unselect)(Marker,X,Y,Marker -> Width - X,1);
  339.                         else
  340.                             (*Marker -> Unselect)(Marker,X,Y,Marker -> LastX - X,1);
  341.                     }
  342.  
  343.                     Marker -> LastColumn    = X;
  344.                     Marker -> LastLine    = Y + Marker -> Top;
  345.                 }
  346.             }
  347.  
  348.             if(NewCharPos < CharStart)
  349.             {
  350.                 if((Lines = Marker -> LastY - Y - 1) >= 0)
  351.                 {
  352.                     if(Marker -> LastX)
  353.                         (*Marker -> Select)(Marker,0,Marker -> LastY,Marker -> LastX,1);
  354.  
  355.                     if(Lines > 0)
  356.                         (*Marker -> Select)(Marker,0,Y + 1,Marker -> Width,Lines);
  357.  
  358.                     (*Marker -> Select)(Marker,X,Y,Marker -> Width - X,1);
  359.                 }
  360.                 else
  361.                 {
  362.                     if(Delta)
  363.                         (*Marker -> Select)(Marker,X,Y,Marker -> Width - X,1);
  364.                     else
  365.                         (*Marker -> Select)(Marker,X,Y,Marker -> LastX - X,1);
  366.                 }
  367.  
  368.                 Marker -> FirstColumn    = X;
  369.                 Marker -> FirstLine    = Y + Marker -> Top;
  370.             }
  371.         }
  372.  
  373.         Marker -> LastX = X;
  374.         Marker -> LastY = Y;
  375.     }
  376. }
  377.  
  378.  
  379.     /* ToggleSelect(struct BlockMarker *Marker,WORD Left,WORD Top,WORD Width,WORD Height):
  380.      *
  381.      *    Toggle selection subroutine.
  382.      */
  383.  
  384. VOID
  385. ToggleSelect(struct BlockMarker *Marker,WORD Left,WORD Top,WORD Width,WORD Height)
  386. {
  387.     if(Width && Height)
  388.         ClipBlit(Marker -> Object,0,0,Marker -> Object,Left * Marker -> TextFontWidth,Top * Marker -> TextFontHeight,Width * Marker -> TextFontWidth,Height * Marker -> TextFontHeight,0x50);
  389. }
  390.  
  391.     /* WriteTrimmedString(struct IFFHandle *Handle,STRPTR String,WORD Len):
  392.      *
  393.      *    Write a string to the clipboard, sans trailing spaces.
  394.      */
  395.  
  396. VOID __regargs
  397. WriteTrimmedString(struct IFFHandle *Handle,STRPTR String,WORD Len)
  398. {
  399.     while(Len > 0)
  400.     {
  401.         if(String[Len - 1] != ' ')
  402.             break;
  403.         else
  404.             Len--;
  405.     }
  406.  
  407.     if(Len)
  408.         WriteChunkBytes(Handle,String,Len);
  409. }
  410.  
  411.     /* TrimLength(STRPTR String,WORD Len):
  412.      *
  413.      *    Determine the length of a string, sans trailing spaces.
  414.      */
  415.  
  416. WORD __regargs
  417. TrimLength(STRPTR String,WORD Len)
  418. {
  419.     while(Len > 0)
  420.     {
  421.         if(String[Len - 1] != ' ')
  422.             break;
  423.         else
  424.             Len--;
  425.     }
  426.  
  427.     return(Len);
  428. }
  429.  
  430.     /* ClipPage(struct BlockMarker *Marker):
  431.      *
  432.      *    Send the entire marked page to the clipboard.
  433.      */
  434.  
  435. STATIC VOID __regargs
  436. ClipPage(struct BlockMarker *Marker)
  437. {
  438.     struct IFFHandle *Handle;
  439.  
  440.     if(Handle = AllocIFF())
  441.     {
  442.         if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config . ClipboardUnit))
  443.         {
  444.             InitIFFasClip(Handle);
  445.  
  446.             if(!OpenIFF(Handle,IFFF_WRITE))
  447.             {
  448.                 if(!PushChunk(Handle,'FTXT','FORM',IFFSIZE_UNKNOWN))
  449.                 {
  450.                     if(!PushChunk(Handle,0,'CHRS',IFFSIZE_UNKNOWN))
  451.                     {
  452.                         WORD    Lines = Marker -> LastLine - Marker -> FirstLine - 1,
  453.                             i;
  454.  
  455.                         WriteTrimmedString(Handle,&Raster[RasterWidth * Marker -> FirstLine + Marker -> FirstColumn],Marker -> Width - Marker -> FirstColumn);
  456.                         WriteChunkBytes(Handle,"\n",1);
  457.  
  458.                         if(Lines > 0)
  459.                         {
  460.                             STRPTR Line = &Raster[(Marker -> FirstLine + 1) * RasterWidth];
  461.  
  462.                             for(i = 0 ; i < Lines ; i++)
  463.                             {
  464.                                 WriteTrimmedString(Handle,Line,Marker -> Width);
  465.                                 WriteChunkBytes(Handle,"\n",1);
  466.  
  467.                                 Line += RasterWidth;
  468.                             }
  469.                         }
  470.  
  471.                         WriteTrimmedString(Handle,&Raster[RasterWidth * Marker -> LastLine],Marker -> LastColumn);
  472.                         WriteChunkBytes(Handle,"\n",1);
  473.  
  474.                         PopChunk(Handle);
  475.                     }
  476.  
  477.                     PopChunk(Handle);
  478.                 }
  479.  
  480.                 CloseIFF(Handle);
  481.             }
  482.  
  483.             CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
  484.         }
  485.  
  486.         FreeIFF(Handle);
  487.     }
  488. }
  489.  
  490.     /* MarkClip(BYTE SingleChar,BYTE Xerox):
  491.      *
  492.      *    The Big One. Mark areas of the main screen and send them
  493.      *    to the clipboard.
  494.      */
  495.  
  496. VOID
  497. MarkClip(BYTE SingleChar,BYTE Xerox)
  498. {
  499.     WORD    FirstX = Window -> MouseX / TextFontWidth,
  500.         FirstY = Window -> MouseY / TextFontHeight;
  501.  
  502.     if(SingleChar)
  503.     {
  504.         UBYTE Char;
  505.  
  506.         Char = Raster[FirstY * RasterWidth + FirstX];
  507.  
  508.         if(Char && Char != ' ')
  509.         {
  510.             SerWrite(&Char,1);
  511.  
  512.             if(Xerox)
  513.             {
  514.                 switch(Config . SendCR)
  515.                 {
  516.                     case CR_IGNORE:    break;
  517.  
  518.                     case CR_ASCR:    SerWrite("\r",1);
  519.                             break;
  520.  
  521.                     case CR_ASCRLF:    SerWrite("\r\n",2);
  522.                             break;
  523.                 }
  524.             }
  525.         }
  526.     }
  527.     else
  528.     {
  529.         struct BlockMarker    *Marker;
  530.         BYTE             HasMouse = FALSE;
  531.  
  532.         ClearCursor();
  533.  
  534.         if(Marker = BM_SetMark(Window -> RPort,ToggleSelect,ToggleSelect,LastColumn + 1,LastLine + 1,0,LastLine + 1,Window -> MouseX / TextFontWidth,Window -> MouseY / TextFontHeight,TextFontWidth,TextFontHeight))
  535.         {
  536.             struct IntuiMessage    *Massage;
  537.             ULONG             Code,Class;
  538.             BYTE             Done = FALSE;
  539.             UBYTE             Mask = RPort -> Mask;
  540.             WORD             PlusX = TextFontWidth - 1;
  541.             WORD             MouseX,MouseY;
  542.  
  543.             SetWrMsk(RPort,0xFF);
  544.  
  545.             while(!Done)
  546.             {
  547.                 WaitPort(Window -> UserPort);
  548.  
  549.                 while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
  550.                 {
  551.                     Class    = Massage -> Class;
  552.                     Code    = Massage -> Code;
  553.                     MouseX    = Massage -> MouseX;
  554.                     MouseY    = Massage -> MouseY;
  555.  
  556.                     GT_ReplyIMsg(Massage);
  557.  
  558.                     if(Class == IDCMP_MOUSEBUTTONS && (Code & IECODE_UP_PREFIX))
  559.                     {
  560.                         BM_Draw(Marker,Marker -> Unselect);
  561.  
  562.                         if(Code == MIDDLEUP)
  563.                             Xerox = TRUE;
  564.  
  565.                         Done = TRUE;
  566.  
  567.                         break;
  568.                     }
  569.  
  570.                     if(Class == IDCMP_MOUSEMOVE)
  571.                     {
  572.                         if(!HasMouse)
  573.                         {
  574.                             SetMarker(Window);
  575.  
  576.                             HasMouse = TRUE;
  577.                         }
  578.  
  579.                         BM_ExtendMark(Marker,(MouseX + PlusX) / TextFontWidth,MouseY / TextFontHeight,0);
  580.                     }
  581.                 }
  582.             }
  583.  
  584.             SetWrMsk(RPort,Mask);
  585.  
  586.             if(FirstX != Window -> MouseX / TextFontWidth || FirstY != Window -> MouseY / TextFontHeight)
  587.             {
  588.                 SetWait(Window);
  589.  
  590.                 if(Marker -> FirstColumn == Marker -> Width)
  591.                 {
  592.                     Marker -> FirstLine++;
  593.  
  594.                     Marker -> FirstColumn = 0;
  595.                 }
  596.  
  597.                 if(Marker -> LastColumn == 0)
  598.                 {
  599.                     Marker -> LastLine--;
  600.  
  601.                     Marker -> LastColumn = Marker -> Width;
  602.                 }
  603.  
  604.                 if(Marker -> FirstLine <= Marker -> LastLine)
  605.                 {
  606.                     if(Marker -> FirstLine != Marker -> LastLine || Marker -> FirstColumn != Marker -> LastColumn)
  607.                     {
  608.                         if(Marker -> FirstLine == Marker -> LastLine)
  609.                             SaveClip(&Raster[RasterWidth * Marker -> FirstLine + Marker -> FirstColumn],Marker -> LastColumn - Marker -> FirstColumn);
  610.                         else
  611.                             ClipPage(Marker);
  612.  
  613.                         if(Xerox)
  614.                         {
  615.                             if(!ClipInput)
  616.                             {
  617.                                 if(!OpenClip())
  618.                                     ClipInput = ClipXerox = TRUE;
  619.                                 else
  620.                                     ClipInput = ClipXerox = FALSE;
  621.                             }
  622.                         }
  623.                     }
  624.                 }
  625.             }
  626.  
  627.             FreeVec(Marker);
  628.         }
  629.  
  630.         ClearPointer(Window);
  631.  
  632.         SetCursor();
  633.     }
  634. }
  635.