home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / TextBuffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  69.0 KB  |  2,932 lines

  1. /*
  2. **    TextBuffer.c
  3. **
  4. **    Support routines for the text buffer.
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Gadget ID codes. */
  17.  
  18. enum    {    GAD_SCROLLER,GAD_UP,GAD_DOWN };
  19.  
  20.     /* Menu ID codes. */
  21.  
  22. enum    {    MEN_SEARCH,MEN_REPEAT,MEN_GOTO,MEN_CLEARBUF_CONTENTS,MEN_QUITBUF,MEN_PASTECLIP };
  23.  
  24.     /* A handy macro to determine the length of a string. */
  25.  
  26. #define LINE_WIDTH(s)    (s)[-1]
  27.  
  28.     /* Some private data (render info & window). */
  29.  
  30. typedef struct TextBufferInfo
  31. {
  32.     UWORD                 Left,Top,
  33.                          Width,Height;
  34.  
  35.     struct Process        *Buddy;
  36.  
  37.     struct Window        *Window;
  38.     struct Screen        *Screen;
  39.     struct Menu            *BufferMenuStrip;
  40.  
  41.     BYTE                 BufferSignal;
  42.     BOOLEAN                 BufferTerminated;
  43.  
  44.     struct RastPort        *RPort;
  45.  
  46.     LONG                 NumBufferLines,
  47.                          NumBufferColumns,
  48.                          LastTopLine;
  49.  
  50.     struct DrawInfo        *BufferDrawInfo;
  51.     struct Image        *BufferAmigaGlyph,
  52.                         *BufferCheckGlyph;
  53.  
  54.     struct TextFont        *LocalFont;
  55.  
  56.     WORD                 LocalTextFontWidth,
  57.                          LocalTextFontHeight;
  58.  
  59.     struct TTextAttr     LocalTextFont;
  60.     UBYTE                 LocalTextFontName[MAX_FILENAME_LENGTH];
  61.  
  62.     struct TTextAttr     LocalUserFont;
  63.     UBYTE                 LocalUserFontName[MAX_FILENAME_LENGTH];
  64.  
  65.     LONG                 TopLine,
  66.                          DisplayedLines;
  67.  
  68.     BOOLEAN                 SearchForward,
  69.                          IgnoreCase,
  70.                          WholeWords,
  71.                          NeedClipConversion;
  72.  
  73.     struct Gadget        *Scroller,
  74.                         *UpArrow,
  75.                         *DownArrow;
  76.  
  77.     struct Image        *UpImage,
  78.                         *DownImage;
  79.  
  80.     UWORD                *BufferLineWidths,
  81.                         *BufferLineOffsets,
  82.                         *BufferColumnOffsets;
  83.  
  84.     ULONG                 ArrowWidth,
  85.                          ArrowHeight;
  86.  
  87.     UWORD                 TitleFrontPen,
  88.                          TitleBackPen,
  89.                          TextFrontPen,
  90.                          TextBackPen;
  91.  
  92.     WORD                 OldColumn,
  93.                          OldLine,
  94.                          OldLength;
  95.  
  96.     LONG                 TitleOffset;
  97.     LONG                 MaxPen;
  98.     WORD                 RightBorderWidth;
  99.  
  100.     struct Screen        *Parent;
  101.  
  102.     UBYTE                 TitleBuffer[100];
  103.  
  104.     struct MsgQueue        *Queue;
  105.     ULONG                 QueueMask;
  106.  
  107.     BOOLEAN                *pSearchForward;
  108.     BOOLEAN                *pIgnoreCase;
  109.     BOOLEAN                *pWholeWords;
  110.     LONG                *pTopLine;
  111. } TextBufferInfo;
  112.  
  113. STATIC VOID
  114. BufferClear(TextBufferInfo *BufferInfo,LONG Left,LONG Top,LONG Right,LONG Bottom)
  115. {
  116.     struct RastPort    *RPort = BufferInfo->RPort;
  117.  
  118.     Left    += BufferInfo->Left;
  119.     Top        += BufferInfo->Top;
  120.     Right    += BufferInfo->Left;
  121.     Bottom    += BufferInfo->Top;
  122.  
  123.     if(Right >= BufferInfo->Left + BufferInfo->Width)
  124.         Right = BufferInfo->Left + BufferInfo->Width - 1;
  125.  
  126.     if(Bottom >= BufferInfo->Top + BufferInfo->Height)
  127.         Bottom = BufferInfo->Top + BufferInfo->Height - 1;
  128.  
  129.     if(Left <= Right && Top <= Bottom)
  130.     {
  131.         SetAPen(RPort,BufferInfo->TextBackPen);
  132.         RectFill(RPort,Left,Top,Right,Bottom);
  133.         SetAPen(RPort,BufferInfo->TextFrontPen);
  134.     }
  135. }
  136.  
  137. STATIC VOID
  138. BufferScroll(TextBufferInfo *BufferInfo,LONG Lines)
  139. {
  140.     if(Lines < 0)
  141.         Lines = -BufferInfo->BufferLineOffsets[-Lines];
  142.     else
  143.         Lines = BufferInfo->BufferLineOffsets[Lines];
  144.  
  145.     ScrollRaster(BufferInfo->RPort,0,Lines,BufferInfo->Left,BufferInfo->Top,BufferInfo->Left + BufferInfo->Width - 1,BufferInfo->Top + BufferInfo->Height - 1);
  146. }
  147.  
  148. STATIC VOID
  149. BufferComplement(TextBufferInfo *BufferInfo,LONG SrcX,LONG SrcY,LONG Width,LONG Height)
  150. {
  151.     struct RastPort *RPort = BufferInfo->RPort;
  152.  
  153.     if(Kick30)
  154.         SetMaxPen(RPort,(ULONG)~0);
  155.  
  156.     SetPens(RPort,(ULONG)~0,0,JAM1 | COMPLEMENT);
  157.  
  158.     SrcX    += BufferInfo->Left;
  159.     SrcY    += BufferInfo->Top;
  160.  
  161.     FillBox(RPort,SrcX,SrcY,Width,Height);
  162.  
  163.     if(Kick30)
  164.         SetMaxPen(RPort,BufferInfo->MaxPen);
  165.  
  166.     SetPens(RPort,BufferInfo->TextFrontPen,BufferInfo->TextBackPen,JAM2);
  167. }
  168.  
  169.     /* DeleteScroller(VOID):
  170.      *
  171.      *    Delete scroller and arrow objects.
  172.      */
  173.  
  174. STATIC VOID
  175. DeleteScroller(TextBufferInfo *BufferInfo)
  176. {
  177.     DisposeObject(BufferInfo->Scroller);
  178.     DisposeObject(BufferInfo->UpArrow);
  179.     DisposeObject(BufferInfo->DownArrow);
  180.     DisposeObject(BufferInfo->UpImage);
  181.     DisposeObject(BufferInfo->DownImage);
  182. }
  183.  
  184.     /* CreateScroller(LONG Height):
  185.      *
  186.      *    Create scroller and arrow objects.
  187.      */
  188.  
  189. STATIC BOOL
  190. CreateScroller(TextBufferInfo *BufferInfo,LONG Height)
  191. {
  192.     STATIC struct TagItem ArrowMappings[] = { GA_ID,GA_ID,TAG_END };
  193.  
  194.     BOOL             Result = FALSE;
  195.     LONG             SizeType;
  196.     struct Screen    *Screen;
  197.  
  198.     if(BufferInfo->Parent)
  199.         Screen = BufferInfo->Parent;
  200.     else
  201.         Screen = BufferInfo->Screen;
  202.  
  203.     if(Screen->Flags & SCREENHIRES)
  204.         SizeType = SYSISIZE_MEDRES;
  205.     else
  206.         SizeType = SYSISIZE_LOWRES;
  207.  
  208.     if(!BufferInfo->Parent)
  209.     {
  210.         if(BufferInfo->UpImage = (struct Image *)NewObject(NULL,SYSICLASS,
  211.             SYSIA_Size,        SizeType,
  212.             SYSIA_Which,    UPIMAGE,
  213.             SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  214.         TAG_DONE))
  215.         {
  216.             if(BufferInfo->DownImage = (struct Image *)NewObject(NULL,SYSICLASS,
  217.                 SYSIA_Size,        SizeType,
  218.                 SYSIA_Which,    DOWNIMAGE,
  219.                 SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  220.             TAG_DONE))
  221.             {
  222.                 LONG ScrollerHeight,LeftEdge;
  223.  
  224.                 GetAttr(IA_Height,    BufferInfo->UpImage,&BufferInfo->ArrowHeight);
  225.                 GetAttr(IA_Width,    BufferInfo->UpImage,&BufferInfo->ArrowWidth);
  226.  
  227.                 ScrollerHeight = Height - 2 * BufferInfo->ArrowHeight;
  228.  
  229.                 LeftEdge = BufferInfo->Screen->Width - BufferInfo->ArrowWidth;
  230.  
  231.                 if(BufferInfo->Scroller = NewObject(NULL,PROPGCLASS,
  232.                     GA_ID,            GAD_SCROLLER,
  233.  
  234.                     GA_Top,            0,
  235.                     GA_Left,        LeftEdge,
  236.                     GA_Width,        BufferInfo->ArrowWidth,
  237.                     GA_Height,        ScrollerHeight,
  238.                     GA_Immediate,    TRUE,
  239.                     GA_FollowMouse,    TRUE,
  240.                     GA_RelVerify,    TRUE,
  241.  
  242.                     PGA_Freedom,    FREEVERT,
  243.                     PGA_NewLook,    TRUE,
  244.  
  245.                     PGA_Visible,    1,
  246.                     PGA_Total,        1,
  247.                 TAG_DONE))
  248.                 {
  249.                     if(BufferInfo->UpArrow = NewObject(NULL,BUTTONGCLASS,
  250.                         GA_ID,            GAD_UP,
  251.                         GA_Image,        BufferInfo->UpImage,
  252.                         GA_Left,        LeftEdge,
  253.                         GA_Top,            ScrollerHeight,
  254.                         GA_Height,        BufferInfo->ArrowHeight,
  255.                         GA_Width,        BufferInfo->ArrowWidth,
  256.                         GA_Immediate,    TRUE,
  257.                         GA_RelVerify,    TRUE,
  258.                         GA_Previous,    BufferInfo->Scroller,
  259.  
  260.                         ICA_TARGET,        ICTARGET_IDCMP,
  261.                         ICA_MAP,        ArrowMappings,
  262.                     TAG_DONE))
  263.                     {
  264.                         if(BufferInfo->DownArrow = NewObject(NULL,BUTTONGCLASS,
  265.                             GA_ID,            GAD_DOWN,
  266.                             GA_Image,        BufferInfo->DownImage,
  267.                             GA_Left,        LeftEdge,
  268.                             GA_Top,            ScrollerHeight + BufferInfo->ArrowHeight,
  269.                             GA_Height,        BufferInfo->ArrowHeight,
  270.                             GA_Width,        BufferInfo->ArrowWidth,
  271.                             GA_Immediate,    TRUE,
  272.                             GA_RelVerify,    TRUE,
  273.                             GA_Previous,    BufferInfo->UpArrow,
  274.  
  275.                             ICA_TARGET,        ICTARGET_IDCMP,
  276.                             ICA_MAP,        ArrowMappings,
  277.                         TAG_DONE))
  278.                             Result = TRUE;
  279.                     }
  280.                 }
  281.             }
  282.         }
  283.     }
  284.     else
  285.     {
  286.         struct Image *SizeImage;
  287.  
  288.         if(SizeImage = (struct Image *)NewObject(NULL,SYSICLASS,
  289.             SYSIA_Size,        SizeType,
  290.             SYSIA_Which,    SIZEIMAGE,
  291.             SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  292.         TAG_DONE))
  293.         {
  294.             ULONG SizeWidth,SizeHeight;
  295.  
  296.             GetAttr(IA_Width,    SizeImage,&SizeWidth);
  297.             GetAttr(IA_Height,    SizeImage,&SizeHeight);
  298.  
  299.             DisposeObject(SizeImage);
  300.  
  301.             BufferInfo->RightBorderWidth = SizeWidth;
  302.  
  303.             if(BufferInfo->UpImage = (struct Image *)NewObject(NULL,SYSICLASS,
  304.                 SYSIA_Size,        SizeType,
  305.                 SYSIA_Which,    UPIMAGE,
  306.                 SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  307.             TAG_DONE))
  308.             {
  309.                 GetAttr(IA_Height,BufferInfo->UpImage,&BufferInfo->ArrowHeight);
  310.  
  311.                 if(BufferInfo->DownImage = (struct Image *)NewObject(NULL,SYSICLASS,
  312.                     SYSIA_Size,        SizeType,
  313.                     SYSIA_Which,    DOWNIMAGE,
  314.                     SYSIA_DrawInfo,    BufferInfo->BufferDrawInfo,
  315.                 TAG_DONE))
  316.                 {
  317.                     if(BufferInfo->Scroller = NewObject(NULL,PROPGCLASS,
  318.                         GA_ID,            GAD_SCROLLER,
  319.  
  320.                         GA_Top,            Screen->WBorTop + Screen->Font->ta_YSize + 2,
  321.                         GA_RelHeight,    -(Screen->WBorTop + Screen->Font->ta_YSize + 2 + SizeHeight + 1 + 2 * BufferInfo->ArrowHeight),
  322.                         GA_Width,        SizeWidth - 8,
  323.                         GA_RelRight,    -(SizeWidth - 5),
  324.  
  325.                         GA_Immediate,    TRUE,
  326.                         GA_FollowMouse,    TRUE,
  327.                         GA_RelVerify,    TRUE,
  328.                         GA_RightBorder,    TRUE,
  329.  
  330.                         PGA_Freedom,    FREEVERT,
  331.                         PGA_NewLook,    TRUE,
  332.                         PGA_Borderless,    TRUE,
  333.  
  334.                         PGA_Visible,    1,
  335.                         PGA_Total,        1,
  336.                     TAG_DONE))
  337.                     {
  338.                         if(BufferInfo->UpArrow = NewObject(NULL,BUTTONGCLASS,
  339.                             GA_ID,            GAD_UP,
  340.  
  341.                             GA_Image,        BufferInfo->UpImage,
  342.                             GA_RelRight,    -(SizeWidth - 1),
  343.                             GA_RelBottom,    -(SizeHeight - 1 + 2 * BufferInfo->ArrowHeight),
  344.                             GA_Height,        BufferInfo->ArrowHeight,
  345.                             GA_Width,        SizeWidth,
  346.                             GA_Immediate,    TRUE,
  347.                             GA_RelVerify,    TRUE,
  348.                             GA_Previous,    BufferInfo->Scroller,
  349.                             GA_RightBorder,    TRUE,
  350.  
  351.                             ICA_TARGET,        ICTARGET_IDCMP,
  352.                             ICA_MAP,        ArrowMappings,
  353.                         TAG_DONE))
  354.                         {
  355.                             if(BufferInfo->DownArrow = NewObject(NULL,BUTTONGCLASS,
  356.                                 GA_ID,            GAD_DOWN,
  357.  
  358.                                 GA_Image,        BufferInfo->DownImage,
  359.                                 GA_RelRight,    -(SizeWidth - 1),
  360.                                 GA_RelBottom,    -(SizeHeight - 1 + BufferInfo->ArrowHeight),
  361.                                 GA_Height,        BufferInfo->ArrowHeight,
  362.                                 GA_Width,        SizeWidth,
  363.                                 GA_Immediate,    TRUE,
  364.                                 GA_RelVerify,    TRUE,
  365.                                 GA_Previous,    BufferInfo->UpArrow,
  366.                                 GA_RightBorder,    TRUE,
  367.  
  368.                                 ICA_TARGET,        ICTARGET_IDCMP,
  369.                                 ICA_MAP,        ArrowMappings,
  370.                             TAG_DONE))
  371.                                 Result = TRUE;
  372.                         }
  373.                     }
  374.                 }
  375.             }
  376.         }
  377.     }
  378.  
  379.     if(!Result)
  380.         DeleteScroller(BufferInfo);
  381.  
  382.     return(Result);
  383. }
  384.  
  385.     /* PrintLine(STRPTR Buffer,LONG LineNumber):
  386.      *
  387.      *    Print a line at a given line number in the displayed area.
  388.      */
  389.  
  390. STATIC VOID
  391. PrintLine(TextBufferInfo *BufferInfo,STRPTR Buffer,LONG LineNumber)
  392. {
  393.     LONG Length = Buffer[-1];
  394.  
  395.         /* Print the text. */
  396.  
  397.     if(Length > 0)
  398.     {
  399.         if(Length > BufferInfo->NumBufferColumns)
  400.             Length = BufferInfo->NumBufferColumns;
  401.  
  402.         if(Length > 0)
  403.             PlaceText(BufferInfo->RPort,BufferInfo->Left,BufferInfo->Top + BufferInfo->BufferLineOffsets[LineNumber],Buffer,Length);
  404.     }
  405.  
  406.     if(Length < 0)
  407.         Length = 0;
  408.  
  409.         /* The line doesn't exactly fill the displayed line,
  410.          * so erase the remaining columns.
  411.          */
  412.  
  413.     if(Length < BufferInfo->BufferLineWidths[LineNumber])
  414.         BufferClear(BufferInfo,BufferInfo->BufferColumnOffsets[Length],BufferInfo->BufferLineOffsets[LineNumber],BufferInfo->BufferColumnOffsets[BufferInfo->BufferLineWidths[LineNumber]] - 1,BufferInfo->BufferLineOffsets[LineNumber + 1] - 1);
  415.  
  416.     BufferInfo->BufferLineWidths[LineNumber] = Length;
  417. }
  418.  
  419.     /* RedrawScreen(LONG FirstLine):
  420.      *
  421.      *    Redraw the contents of the entire screen and return the
  422.      *    number of lines actually drawn.
  423.      */
  424.  
  425. STATIC LONG
  426. RedrawScreen(TextBufferInfo *BufferInfo,LONG FirstLine)
  427. {
  428.     LONG i,Last,Line = 0,Result;
  429.  
  430.     ObtainSemaphore(BufferSemaphore);
  431.  
  432.         /* Determine last line to display. */
  433.  
  434.     if((Last = FirstLine + BufferInfo->NumBufferLines) >= Lines)
  435.     {
  436.         Last = Lines;
  437.  
  438.         if((FirstLine = Last - BufferInfo->NumBufferLines) < 0)
  439.             FirstLine = 0;
  440.  
  441.         BufferInfo->TopLine = FirstLine;
  442.     }
  443.  
  444.     if(Last > FirstLine + BufferInfo->NumBufferLines)
  445.         Last = FirstLine + BufferInfo->NumBufferLines;
  446.  
  447.     Result = Last - FirstLine;
  448.  
  449.     if(Lines)
  450.     {
  451.         if(BufferInfo->LastTopLine != -1)
  452.         {
  453.             LONG Delta = FirstLine - BufferInfo->LastTopLine;
  454.  
  455.             if(ABS(Delta) < BufferInfo->NumBufferLines)
  456.             {
  457.                     /* No change? */
  458.  
  459.                 if(!Delta)
  460.                 {
  461.                     ReleaseSemaphore(BufferSemaphore);
  462.  
  463.                     return(Result);
  464.                 }
  465.                 else
  466.                 {
  467.                     BufferInfo->LastTopLine = FirstLine;
  468.  
  469.                         /* Scrolled up? */
  470.  
  471.                     if(Delta < 0)
  472.                     {
  473.                         for(i = BufferInfo->NumBufferLines - 1 ; i >= -Delta ; i--)
  474.                             BufferInfo->BufferLineWidths[i] = BufferInfo->BufferLineWidths[i + Delta];
  475.  
  476.                         BufferScroll(BufferInfo,Delta);
  477.  
  478.                         Last = FirstLine - Delta;
  479.                     }
  480.                     else
  481.                     {
  482.                         for(i = Delta ; i < BufferInfo->NumBufferLines ; i++)
  483.                             BufferInfo->BufferLineWidths[i - Delta] = BufferInfo->BufferLineWidths[i];
  484.  
  485.                             /* Scrolled down. */
  486.  
  487.                         BufferScroll(BufferInfo,Delta);
  488.  
  489.                         FirstLine += BufferInfo->NumBufferLines - Delta;
  490.  
  491.                         Line = BufferInfo->NumBufferLines - Delta;
  492.                     }
  493.                 }
  494.             }
  495.             else
  496.                 BufferInfo->LastTopLine = FirstLine;
  497.         }
  498.         else
  499.             BufferInfo->LastTopLine = FirstLine;
  500.  
  501.         if(BufferLines)
  502.         {
  503.             for(i = FirstLine ; i < Last ; i++)
  504.                 PrintLine(BufferInfo,BufferLines[i],Line++);
  505.         }
  506.     }
  507.  
  508.     ReleaseSemaphore(BufferSemaphore);
  509.  
  510.         /* We didn't fill the whole screen, so clear the rest. */
  511.  
  512.     if(Result < BufferInfo->NumBufferLines)
  513.     {
  514.         LONG i;
  515.  
  516.         for(i = Result ; i < BufferInfo->NumBufferLines ; i++)
  517.             BufferInfo->BufferLineWidths[i] = 0;
  518.  
  519.         BufferClear(BufferInfo,0,BufferInfo->BufferLineOffsets[Result],BufferInfo->BufferColumnOffsets[BufferInfo->NumBufferColumns] - 1,BufferInfo->BufferLineOffsets[BufferInfo->NumBufferLines] - 1);
  520.     }
  521.  
  522.     return(Result);
  523. }
  524.  
  525.     /* MarkArea(LONG Column,LONG Line,LONG Length):
  526.      *
  527.      *    Mark an area in the term Buffer window.
  528.      */
  529.  
  530. STATIC VOID
  531. MarkArea(TextBufferInfo *BufferInfo,LONG Column,LONG Line,LONG Length)
  532. {
  533.     if(BufferInfo->OldColumn != -1)
  534.         BufferComplement(BufferInfo,BufferInfo->BufferColumnOffsets[BufferInfo->OldColumn],BufferInfo->BufferLineOffsets[BufferInfo->OldLine],BufferInfo->BufferColumnOffsets[BufferInfo->OldLength],BufferInfo->LocalTextFontHeight);
  535.  
  536.     if(Column != -1)
  537.     {
  538.         if(BufferInfo->OldColumn != Column || BufferInfo->OldLine != Line || BufferInfo->OldLength != Length)
  539.             BufferComplement(BufferInfo,BufferInfo->BufferColumnOffsets[Column],BufferInfo->BufferLineOffsets[Line],BufferInfo->BufferColumnOffsets[Length],BufferInfo->LocalTextFontHeight);
  540.     }
  541.  
  542.     BufferInfo->OldColumn    = Column;
  543.     BufferInfo->OldLine        = Line;
  544.     BufferInfo->OldLength    = Length;
  545. }
  546.  
  547. STATIC VOID __stdargs
  548. BufferDestructor(struct DataMsg *Item)
  549. {
  550.     Signal(Item->Client,Item->Mask);
  551. }
  552.  
  553. STATIC VOID
  554. BufferSerWrite(TextBufferInfo *BufferInfo,APTR Data,LONG Size)
  555. {
  556.     struct DataMsg Msg;
  557.  
  558.     InitMsgItem(&Msg,BufferDestructor);
  559.  
  560.     Msg.Type    = DATAMSGTYPE_WRITE;
  561.     Msg.Data    = Data;
  562.     Msg.Size    = Size;
  563.     Msg.Client    = FindTask(NULL);
  564.     Msg.Mask    = 1UL << BufferInfo->BufferSignal;
  565.  
  566.     Forbid();
  567.  
  568.     ClrSignal(Msg.Mask);
  569.  
  570.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  571.  
  572.     Wait(Msg.Mask);
  573.  
  574.     Permit();
  575. }
  576.  
  577.     /* BufferClipPage(struct BlockMarker *Marker):
  578.      *
  579.      *    Send the marked area to the clipboard.
  580.      */
  581.  
  582. STATIC VOID
  583. BufferClipPage(TextBufferInfo *BufferInfo,struct BlockMarker *Marker)
  584. {
  585.     if(BufferLines)
  586.     {
  587.         struct IFFHandle *Handle;
  588.  
  589.         if(Handle = AllocIFF())
  590.         {
  591.             if(Handle->iff_Stream = (ULONG)OpenClipboard(Config->ClipConfig->ClipboardUnit))
  592.             {
  593.                 InitIFFasClip(Handle);
  594.  
  595.                 if(!OpenIFF(Handle,IFFF_WRITE))
  596.                 {
  597.                     if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
  598.                     {
  599.                         if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
  600.                         {
  601.                             LONG Lines = Marker->LastLine - Marker->FirstLine - 1,i;
  602.  
  603.                             if(LINE_WIDTH(BufferLines[Marker->FirstLine]) > Marker->FirstColumn)
  604.                                 WriteTrimmedString(Handle,&BufferLines[Marker->FirstLine][Marker->FirstColumn],LINE_WIDTH(BufferLines[Marker->FirstLine]) - Marker->FirstColumn,BufferInfo->NeedClipConversion);
  605.  
  606.                             WriteChunkBytes(Handle,"\n",1);
  607.  
  608.                             if(Lines > 0)
  609.                             {
  610.                                 for(i = 0 ; i < Lines ; i++)
  611.                                 {
  612.                                     if(LINE_WIDTH(BufferLines[Marker->FirstLine + 1 + i]))
  613.                                         WriteTrimmedString(Handle,BufferLines[Marker->FirstLine + 1 + i],LINE_WIDTH(BufferLines[Marker->FirstLine + 1 + i]),BufferInfo->NeedClipConversion);
  614.  
  615.                                     WriteChunkBytes(Handle,"\n",1);
  616.                                 }
  617.                             }
  618.  
  619.                             if(Marker->LastColumn > LINE_WIDTH(BufferLines[Marker->LastLine]))
  620.                                 WriteTrimmedString(Handle,BufferLines[Marker->LastLine],LINE_WIDTH(BufferLines[Marker->LastLine]),BufferInfo->NeedClipConversion);
  621.                             else
  622.                                 WriteTrimmedString(Handle,BufferLines[Marker->LastLine],Marker->LastColumn,BufferInfo->NeedClipConversion);
  623.  
  624.                             WriteChunkBytes(Handle,"\n",1);
  625.  
  626.                             PopChunk(Handle);
  627.                         }
  628.  
  629.                         PopChunk(Handle);
  630.                     }
  631.  
  632.                     CloseIFF(Handle);
  633.                 }
  634.  
  635.                 CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);
  636.             }
  637.  
  638.             FreeIFF(Handle);
  639.         }
  640.     }
  641. }
  642.  
  643.     /* BufferClip(VOID):
  644.      *
  645.      *    Start buffer marking process.
  646.      */
  647.  
  648. STATIC VOID
  649. BufferClip(TextBufferInfo *BufferInfo)
  650. {
  651.     struct BlockMarker    *Marker;
  652.     LONG                 FirstX,FirstY;
  653.  
  654.     FirstX = (BufferInfo->Window->MouseX - BufferInfo->Left)    / BufferInfo->LocalTextFontWidth,
  655.     FirstY = (BufferInfo->Window->MouseY - BufferInfo->Top)    / BufferInfo->LocalTextFontHeight;
  656.  
  657.     if(Kick30)
  658.         SetMaxPen(BufferInfo->RPort,(ULONG)~0);
  659.  
  660.     if(Marker = BM_SetMark(BufferInfo->Window->RPort,ToggleSelect,ToggleSelect,BufferInfo->NumBufferColumns,BufferInfo->NumBufferLines,BufferInfo->Left,BufferInfo->Top,BufferInfo->TopLine,Lines,FirstX,FirstY,BufferInfo->LocalTextFontWidth,BufferInfo->LocalTextFontHeight))
  661.     {
  662.         struct IntuiMessage    *Massage;
  663.         ULONG                 Code,IClass;
  664.         BOOL                 Done = FALSE,Aborted = FALSE;
  665.         LONG                 PlusX = BufferInfo->LocalTextFontWidth - 1,
  666.                              MouseX,MouseY,
  667.                              Delta = 0;
  668.  
  669.         ReportMouse(TRUE,BufferInfo->Window);
  670.  
  671.         while(!Done)
  672.         {
  673.             WaitPort(BufferInfo->Window->UserPort);
  674.  
  675.             while(Massage = (struct IntuiMessage *)GetMsg(BufferInfo->Window->UserPort))
  676.             {
  677.                 IClass    = Massage->Class;
  678.                 Code    = Massage->Code;
  679.                 MouseX    = Massage->MouseX - BufferInfo->Left;
  680.                 MouseY    = Massage->MouseY - BufferInfo->Top;
  681.  
  682.                 ReplyMsg(Massage);
  683.  
  684.                 if(IClass == IDCMP_INACTIVEWINDOW)
  685.                 {
  686.                     Done = Aborted = TRUE;
  687.  
  688.                     break;
  689.                 }
  690.  
  691.                 if(IClass == IDCMP_INTUITICKS && Delta != 0)
  692.                 {
  693.                     if(BufferLines)
  694.                     {
  695.                         if((Delta > 0 && BufferInfo->TopLine + BufferInfo->NumBufferLines < Lines) || (Delta < 0 && BufferInfo->TopLine > 0))
  696.                         {
  697.                             if(Delta < 0)
  698.                             {
  699.                                 LONG i;
  700.  
  701.                                 for(i = BufferInfo->NumBufferLines - 1 ; i > -Delta ; i--)
  702.                                     BufferInfo->BufferLineWidths[i] = BufferInfo->BufferLineWidths[i + Delta];
  703.  
  704.                                 if(BufferInfo->DisplayedLines)
  705.                                     BufferScroll(BufferInfo,Delta);
  706.  
  707.                                 BufferInfo->BufferLineWidths[0] = BufferInfo->NumBufferColumns;
  708.  
  709.                                 PrintLine(BufferInfo,BufferLines[--BufferInfo->TopLine],0);
  710.                             }
  711.                             else
  712.                             {
  713.                                 LONG i;
  714.  
  715.                                 for(i = Delta ; i < BufferInfo->NumBufferLines ; i++)
  716.                                     BufferInfo->BufferLineWidths[i - Delta] = BufferInfo->BufferLineWidths[i];
  717.  
  718.                                 if(BufferInfo->DisplayedLines)
  719.                                     BufferScroll(BufferInfo,Delta);
  720.  
  721.                                 BufferInfo->BufferLineWidths[BufferInfo->NumBufferLines - 1] = BufferInfo->NumBufferColumns;
  722.  
  723.                                 PrintLine(BufferInfo,BufferLines[BufferInfo->TopLine + BufferInfo->NumBufferLines],BufferInfo->NumBufferLines - 1);
  724.  
  725.                                 BufferInfo->TopLine++;
  726.                             }
  727.  
  728.                             Marker->Top     += Delta;
  729.                             Marker->LastY    -= Delta;
  730.  
  731.                             BM_ExtendMark(Marker,(MouseX + PlusX) / BufferInfo->LocalTextFontWidth,MouseY / BufferInfo->LocalTextFontHeight,Delta);
  732.                         }
  733.                         else
  734.                             Delta = 0;
  735.                     }
  736.                 }
  737.  
  738.                 if(IClass == IDCMP_MOUSEBUTTONS && (Code & IECODE_UP_PREFIX))
  739.                 {
  740.                     BM_Draw(Marker,Marker->Unselect);
  741.  
  742.                     Done = TRUE;
  743.  
  744.                     break;
  745.                 }
  746.  
  747.                 if(IClass == IDCMP_MOUSEMOVE)
  748.                 {
  749.                     BM_ExtendMark(Marker,(MouseX + PlusX) / BufferInfo->LocalTextFontWidth,MouseY / BufferInfo->LocalTextFontHeight,0);
  750.  
  751.                     if(MouseY < 1)
  752.                     {
  753.                         if(BufferInfo->TopLine > 0)
  754.                             Delta = -1;
  755.                     }
  756.                     else
  757.                     {
  758.                         if(MouseY >= BufferInfo->Height - 1 && BufferInfo->TopLine + BufferInfo->NumBufferLines < Lines)
  759.                             Delta = 1;
  760.                     }
  761.  
  762.                     while(Delta)
  763.                     {
  764.                         MouseX    = BufferInfo->Window->MouseX - BufferInfo->Left;
  765.                         MouseY    = BufferInfo->Window->MouseY - BufferInfo->Top;
  766.  
  767.                         if((Delta < 0 && MouseY > 0) || (Delta > 0 && MouseY < BufferInfo->Height - 1))
  768.                             break;
  769.                         else
  770.                         {
  771.                             if(BufferLines)
  772.                             {
  773.                                 if((Delta > 0 && BufferInfo->TopLine + BufferInfo->NumBufferLines < Lines) || (Delta < 0 && BufferInfo->TopLine > 0))
  774.                                 {
  775.                                     if(Delta < 0)
  776.                                     {
  777.                                         LONG i;
  778.  
  779.                                         for(i = BufferInfo->NumBufferLines - 1 ; i > -Delta ; i--)
  780.                                             BufferInfo->BufferLineWidths[i] = BufferInfo->BufferLineWidths[i + Delta];
  781.  
  782.                                         if(BufferInfo->DisplayedLines)
  783.                                             BufferScroll(BufferInfo,Delta);
  784.  
  785.                                         BufferInfo->BufferLineWidths[0] = BufferInfo->NumBufferColumns;
  786.  
  787.                                         PrintLine(BufferInfo,BufferLines[--BufferInfo->TopLine],0);
  788.                                     }
  789.                                     else
  790.                                     {
  791.                                         LONG i;
  792.  
  793.                                         for(i = Delta ; i < BufferInfo->NumBufferLines ; i++)
  794.                                             BufferInfo->BufferLineWidths[i - Delta] = BufferInfo->BufferLineWidths[i];
  795.  
  796.                                         if(BufferInfo->DisplayedLines)
  797.                                             BufferScroll(BufferInfo,Delta);
  798.  
  799.                                         BufferInfo->BufferLineWidths[BufferInfo->NumBufferLines - 1] = BufferInfo->NumBufferColumns;
  800.  
  801.                                         PrintLine(BufferInfo,BufferLines[BufferInfo->TopLine + BufferInfo->NumBufferLines],BufferInfo->NumBufferLines - 1);
  802.  
  803.                                         BufferInfo->TopLine++;
  804.                                     }
  805.  
  806.                                     Marker->Top    += Delta;
  807.                                     Marker->LastY    -= Delta;
  808.  
  809.                                     BM_ExtendMark(Marker,(MouseX + PlusX) / BufferInfo->LocalTextFontWidth,MouseY / BufferInfo->LocalTextFontHeight,Delta);
  810.  
  811.                                     SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  812.                                         PGA_Top,BufferInfo->TopLine,
  813.                                     TAG_DONE);
  814.                                 }
  815.                                 else
  816.                                     break;
  817.                             }
  818.                             else
  819.                                 break;
  820.                         }
  821.                     }
  822.  
  823.                     Delta = 0;
  824.                 }
  825.             }
  826.         }
  827.  
  828.         ReportMouse(FALSE,BufferInfo->Window);
  829.  
  830.         while(Massage = (struct IntuiMessage *)GetMsg(BufferInfo->Window->UserPort))
  831.             ReplyMsg(Massage);
  832.  
  833.         if(!Aborted)
  834.         {
  835.             LONG ThisX,ThisY;
  836.  
  837.             ThisX = (BufferInfo->Window->MouseX - BufferInfo->Left)    / BufferInfo->LocalTextFontWidth;
  838.             ThisY = (BufferInfo->Window->MouseY - BufferInfo->Top)    / BufferInfo->LocalTextFontHeight;
  839.  
  840.             if(FirstX != ThisX || FirstY != ThisY)
  841.             {
  842.                 SetWait(BufferInfo->Window);
  843.  
  844.                 if(Marker->FirstColumn == Marker->Width)
  845.                 {
  846.                     Marker->FirstLine++;
  847.  
  848.                     Marker->FirstColumn = 0;
  849.                 }
  850.  
  851.                 if(Marker->LastColumn == 0)
  852.                 {
  853.                     Marker->LastLine--;
  854.  
  855.                     Marker->LastColumn = Marker->Width;
  856.                 }
  857.  
  858.                 if(Marker->FirstLine <= Marker->LastLine)
  859.                 {
  860.                     if(Marker->FirstLine != Marker->LastLine || Marker->FirstColumn != Marker->LastColumn)
  861.                     {
  862.                         if(BufferLines)
  863.                         {
  864.                             if(Marker->FirstLine == Marker->LastLine)
  865.                             {
  866.                                 if(BufferInfo->NeedClipConversion)
  867.                                 {
  868.                                     UBYTE    Buffer[256];
  869.                                     LONG    Len,i;
  870.                                     STRPTR    Dest,
  871.                                             Source    = &BufferLines[Marker->FirstLine][Marker->FirstColumn];
  872.                                     LONG    Size    = Marker->LastColumn - Marker->FirstColumn;
  873.                                     LONG    c;
  874.                                     BOOL    FirstWrite = TRUE;
  875.  
  876.                                     do
  877.                                     {
  878.                                         Len = MIN(Size,256);
  879.  
  880.                                         Size -= Len;
  881.  
  882.                                         for(i = 0, Dest = Buffer ; i < Len ; i++)
  883.                                         {
  884.                                             if(c = ISOConversion[*Source++])
  885.                                                 *Dest++ = c;
  886.                                             else
  887.                                                 *Dest++ = ' ';
  888.                                         }
  889.  
  890.                                         if(Dest > Buffer)
  891.                                         {
  892.                                             if(FirstWrite)
  893.                                             {
  894.                                                 FirstWrite = FALSE;
  895.  
  896.                                                 SaveClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  897.                                             }
  898.                                             else
  899.                                                 AddClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  900.                                         }
  901.                                     }
  902.                                     while(Size > 0);
  903.                                 }
  904.                                 else
  905.                                     SaveClip(&BufferLines[Marker->FirstLine][Marker->FirstColumn],Marker->LastColumn - Marker->FirstColumn);
  906.                             }
  907.                             else
  908.                                 BufferClipPage(BufferInfo,Marker);
  909.                         }
  910.                     }
  911.                 }
  912.  
  913.                 ClrWait(BufferInfo->Window);
  914.             }
  915.         }
  916.  
  917.         FreeVecPooled(Marker);
  918.     }
  919.  
  920.     if(Kick30)
  921.         SetMaxPen(BufferInfo->RPort,BufferInfo->MaxPen);
  922. }
  923.  
  924. STATIC VOID
  925. StartSearch(TextBufferInfo *BufferInfo,struct SearchInfo *SearchInfo,STRPTR SearchBuffer)
  926. {
  927.     LT_LockWindow(BufferInfo->Window);
  928.  
  929.     if(Lines)
  930.     {
  931.         LONG LineNumber;
  932.  
  933.         ObtainSemaphore(BufferSemaphore);
  934.  
  935.         LineNumber = SearchTextBuffer(SearchInfo);
  936.  
  937.         ReleaseSemaphore(BufferSemaphore);
  938.  
  939.         if(LineNumber == -1)
  940.         {
  941.             ShowRequest(BufferInfo->Window,LocaleString(MSG_TERMBUFFER_DID_NOT_FIND_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SearchBuffer);
  942.  
  943.             FlushMsg(BufferInfo->Window);
  944.  
  945.             SearchInfo->FoundY = -1;
  946.  
  947.             MarkArea(BufferInfo,-1,-1,-1);
  948.         }
  949.         else
  950.         {
  951.             if(LineNumber < BufferInfo->TopLine)
  952.             {
  953.                 MarkArea(BufferInfo,-1,-1,-1);
  954.  
  955.                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine = LineNumber);
  956.  
  957.                 SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  958.                     PGA_Top,BufferInfo->TopLine,
  959.                 TAG_DONE);
  960.             }
  961.             else
  962.             {
  963.                 if(LineNumber > BufferInfo->TopLine + BufferInfo->DisplayedLines - 1)
  964.                 {
  965.                     MarkArea(BufferInfo,-1,-1,-1);
  966.  
  967.                     if(LineNumber >= Lines - BufferInfo->NumBufferLines)
  968.                     {
  969.                         LONG NewCurrentLine;
  970.  
  971.                         if((NewCurrentLine = Lines - BufferInfo->NumBufferLines) < 0)
  972.                             NewCurrentLine = 0;
  973.  
  974.                         if(BufferInfo->TopLine != NewCurrentLine)
  975.                             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine = NewCurrentLine);
  976.                     }
  977.                     else
  978.                         BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine = LineNumber);
  979.  
  980.                     SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  981.                         PGA_Top,BufferInfo->TopLine,
  982.                     TAG_DONE);
  983.                 }
  984.             }
  985.  
  986.             MarkArea(BufferInfo,SearchInfo->FoundX,LineNumber - BufferInfo->TopLine,SearchInfo->PatternWidth);
  987.         }
  988.     }
  989.     else
  990.         ShowRequest(BufferInfo->Window,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  991.  
  992.     LT_UnlockWindow(BufferInfo->Window);
  993. }
  994.  
  995. STATIC BOOL
  996. HandleBuffer(struct SignalSemaphore *Access,TextBufferInfo **Data)
  997. {
  998.     ULONG                     LastSeconds    = 0,
  999.                              LastMicros        = 0,
  1000.                              Seconds,
  1001.                              Micros;
  1002.     BOOL                     ClickAndActivate,
  1003.                              UpdatePercent    = TRUE;
  1004.  
  1005.     ULONG                     SignalSet;
  1006.  
  1007.     struct IntuiMessage        *Massage;
  1008.     ULONG                     MsgClass;
  1009.     UWORD                     MsgCode,MsgQualifier,LastQualifier = NULL;
  1010.     LONG                     MouseX,MouseY;
  1011.  
  1012.     UBYTE                     Char,LastChar = 0,FullChar;
  1013.     LONG                     LastWidth = 0;
  1014.  
  1015.     UBYTE                     PercentBuffer[80];
  1016.     UBYTE                     SearchBuffer[256];
  1017.  
  1018.     struct TagItem            *TagList;
  1019.  
  1020.     STRPTR                     PercentTemplate;
  1021.  
  1022.     BOOL                     RingBack = FALSE;
  1023.  
  1024.     struct SearchContext    *Context    = NULL;
  1025.     struct SearchInfo        *SearchInfo    = NULL;
  1026.  
  1027.     struct Hook                 HistoryHook;
  1028.     TextBufferInfo            *BufferInfo;
  1029.  
  1030.     BufferInfo = *Data;
  1031.  
  1032.     HistoryHook.h_Data = &TextBufferHistory;
  1033.  
  1034.     if(LocaleBase)
  1035.         PercentTemplate = "%lD/%lD (%ld%%)";
  1036.     else
  1037.         PercentTemplate = "%ld/%ld (%ld%%)";
  1038.  
  1039.     FOREVER
  1040.     {
  1041.             /* Show where we are. */
  1042.  
  1043.         if(UpdatePercent)
  1044.         {
  1045.             if(Lines)
  1046.                 SPrintf(PercentBuffer,PercentTemplate,BufferInfo->TopLine,Lines > BufferInfo->NumBufferLines ? Lines - BufferInfo->NumBufferLines : 0,(100 * (BufferInfo->TopLine + BufferInfo->DisplayedLines)) / Lines);
  1047.             else
  1048.                 PercentBuffer[0] = 0;
  1049.  
  1050.             if(BufferInfo->Parent)
  1051.             {
  1052.                 SPrintf(BufferInfo->TitleBuffer,"%s  %s",LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),PercentBuffer);
  1053.  
  1054.                 SetWindowTitles(BufferInfo->Window,BufferInfo->TitleBuffer,(STRPTR)~0);
  1055.             }
  1056.             else
  1057.             {
  1058.                 struct RastPort *RPort;
  1059.                 LONG Width,Len;
  1060.  
  1061.                 RPort = BufferInfo->Screen->BarLayer->rp;
  1062.  
  1063.                 SetPens(RPort,BufferInfo->TitleFrontPen,BufferInfo->TitleBackPen,JAM2);
  1064.  
  1065.                 Len = strlen(PercentBuffer);
  1066.  
  1067.                 PlaceText(RPort,BufferInfo->TitleOffset,1,PercentBuffer,Len);
  1068.  
  1069.                 Width = TextLength(RPort,PercentBuffer,Len);
  1070.  
  1071.                 if(LastWidth > Width)
  1072.                 {
  1073.                     SetAPen(RPort,BufferInfo->TitleBackPen);
  1074.                     RectFill(RPort,BufferInfo->TitleOffset + Width,1,BufferInfo->TitleOffset + LastWidth - 1,RPort->TxHeight - 1);
  1075.                 }
  1076.  
  1077.                 LastWidth = Width;
  1078.             }
  1079.  
  1080.             UpdatePercent = FALSE;
  1081.         }
  1082.  
  1083.         if(BufferInfo->BufferTerminated)
  1084.         {
  1085.             ObtainSemaphore(Access);
  1086.  
  1087.             SignalSet = SetSignal(0,SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferInfo->Window->UserPort) | BufferInfo->QueueMask) & (SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferInfo->Window->UserPort) | BufferInfo->QueueMask);
  1088.  
  1089.                 // Disconnect
  1090.  
  1091.             if(!SignalSet)
  1092.             {
  1093.                 BufferInfo->Buddy = NULL;
  1094.  
  1095.                 *Data = NULL;
  1096.  
  1097.                 ReleaseSemaphore(Access);
  1098.  
  1099.                 break;
  1100.             }
  1101.             else
  1102.                 ReleaseSemaphore(Access);
  1103.         }
  1104.         else
  1105.             SignalSet = Wait(SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferInfo->Window->UserPort) | BufferInfo->QueueMask);
  1106.  
  1107.             /* Leave the town? */
  1108.  
  1109.         if(SignalSet & SIG_KILL)
  1110.             BufferInfo->BufferTerminated = RingBack = TRUE;
  1111.  
  1112.             /* Bring our window to the front. */
  1113.  
  1114.         if(SignalSet & SIG_TOFRONT)
  1115.         {
  1116.             if(Context)
  1117.                 LT_ShowWindow(Context->SearchHandle,TRUE);
  1118.  
  1119.             BumpWindow(BufferInfo->Window);
  1120.         }
  1121.  
  1122.             /* We've got one more line in the
  1123.              * buffer.
  1124.              */
  1125.  
  1126.         if(SignalSet & SIG_UPDATE)
  1127.         {
  1128.             MarkArea(BufferInfo,-1,-1,-1);
  1129.  
  1130.             if(BufferLines && Lines)
  1131.             {
  1132.                 if(Lines - BufferInfo->TopLine > BufferInfo->DisplayedLines && BufferInfo->DisplayedLines < BufferInfo->NumBufferLines)
  1133.                 {
  1134.                     LONG i = BufferInfo->TopLine + BufferInfo->DisplayedLines;
  1135.  
  1136.                     do
  1137.                         PrintLine(BufferInfo,BufferLines[i++],BufferInfo->DisplayedLines++);
  1138.                     while(BufferInfo->DisplayedLines < BufferInfo->NumBufferLines && i < Lines);
  1139.                 }
  1140.             }
  1141.             else
  1142.                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine = 0);
  1143.  
  1144.             SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1145.                 PGA_Total,        Lines,
  1146.                 PGA_Visible,    BufferInfo->DisplayedLines,
  1147.             TAG_DONE);
  1148.  
  1149.             UpdatePercent = TRUE;
  1150.  
  1151.             Signal(ThisProcess,SIG_HANDSHAKE);
  1152.         }
  1153.  
  1154.             /* The contents of the buffer have moved
  1155.              * up a line.
  1156.              */
  1157.  
  1158.         if(SignalSet & SIG_MOVEUP)
  1159.         {
  1160.             MarkArea(BufferInfo,-1,-1,-1);
  1161.  
  1162.             if(BufferInfo->TopLine > 0)
  1163.             {
  1164.                 BufferInfo->LastTopLine = --BufferInfo->TopLine;
  1165.  
  1166.                 SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1167.                     PGA_Top,BufferInfo->TopLine,
  1168.                 TAG_DONE);
  1169.             }
  1170.             else
  1171.             {
  1172.                 LONG i;
  1173.  
  1174.                 for(i = 0 ; i < BufferInfo->NumBufferLines - 1 ; i++)
  1175.                     BufferInfo->BufferLineWidths[i] = BufferInfo->BufferLineWidths[i + 1];
  1176.  
  1177.                 BufferScroll(BufferInfo,-1);
  1178.  
  1179.                 PrintLine(BufferInfo,BufferLines[BufferInfo->NumBufferLines - 1],BufferInfo->NumBufferLines - 1);
  1180.             }
  1181.  
  1182.             UpdatePercent = TRUE;
  1183.  
  1184.             Signal(ThisProcess,SIG_HANDSHAKE);
  1185.         }
  1186.  
  1187.             // A request from the queue?
  1188.  
  1189.         if(SignalSet & BufferInfo->QueueMask)
  1190.         {
  1191.             struct DataMsg    *Msg;
  1192.             LONG             NewCurrentLine;
  1193.  
  1194.             while(Msg = (struct DataMsg *)GetMsgItem(BufferInfo->Queue))
  1195.             {
  1196.                 switch(Msg->Size)
  1197.                 {
  1198.                     case REVIEW_MOVE_TOP:
  1199.  
  1200.                         MarkArea(BufferInfo,-1,-1,-1);
  1201.  
  1202.                         if(BufferInfo->TopLine)
  1203.                         {
  1204.                             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,0);
  1205.  
  1206.                             BufferInfo->TopLine = 0;
  1207.                             LastChar = 0;
  1208.  
  1209.                             SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1210.                                 PGA_Top,BufferInfo->TopLine,
  1211.                             TAG_DONE);
  1212.  
  1213.                             UpdatePercent = TRUE;
  1214.                         }
  1215.  
  1216.                         break;
  1217.  
  1218.                     case REVIEW_MOVE_BOTTOM:
  1219.  
  1220.                         if((NewCurrentLine = Lines - BufferInfo->NumBufferLines) < 0)
  1221.                             NewCurrentLine = 0;
  1222.  
  1223.                         MarkArea(BufferInfo,-1,-1,-1);
  1224.  
  1225.                         if(BufferInfo->TopLine != NewCurrentLine)
  1226.                         {
  1227.                             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1228.  
  1229.                             BufferInfo->TopLine = NewCurrentLine;
  1230.  
  1231.                             LastChar = 0;
  1232.  
  1233.                             SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1234.                                 PGA_Top,BufferInfo->TopLine,
  1235.                             TAG_DONE);
  1236.  
  1237.                             UpdatePercent = TRUE;
  1238.                         }
  1239.  
  1240.                         break;
  1241.  
  1242.                     case REVIEW_MOVE_UP:
  1243.  
  1244.                         if((NewCurrentLine = BufferInfo->TopLine - BufferInfo->NumBufferLines) < 0)
  1245.                             NewCurrentLine = 0;
  1246.  
  1247.                         MarkArea(BufferInfo,-1,-1,-1);
  1248.  
  1249.                         if(NewCurrentLine != BufferInfo->TopLine)
  1250.                         {
  1251.                             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1252.  
  1253.                             BufferInfo->TopLine = NewCurrentLine;
  1254.  
  1255.                             LastChar = 0;
  1256.  
  1257.                             SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1258.                                 PGA_Top,BufferInfo->TopLine,
  1259.                             TAG_DONE);
  1260.  
  1261.                             UpdatePercent = TRUE;
  1262.                         }
  1263.  
  1264.                         break;
  1265.  
  1266.                     case REVIEW_MOVE_DOWN:
  1267.  
  1268.                         if((NewCurrentLine = BufferInfo->TopLine + (2 * BufferInfo->NumBufferLines)) > Lines)
  1269.                             NewCurrentLine = Lines;
  1270.  
  1271.                         if((NewCurrentLine = NewCurrentLine - BufferInfo->NumBufferLines) < 0)
  1272.                             NewCurrentLine = 0;
  1273.  
  1274.                         MarkArea(BufferInfo,-1,-1,-1);
  1275.  
  1276.                         if(NewCurrentLine != BufferInfo->TopLine)
  1277.                         {
  1278.                             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1279.  
  1280.                             BufferInfo->TopLine = NewCurrentLine;
  1281.  
  1282.                             LastChar = 0;
  1283.  
  1284.                             SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1285.                                 PGA_Top,BufferInfo->TopLine,
  1286.                             TAG_DONE);
  1287.  
  1288.                             UpdatePercent = TRUE;
  1289.                         }
  1290.  
  1291.                         break;
  1292.                 }
  1293.  
  1294.                 DeleteMsgItem(Msg);
  1295.             }
  1296.         }
  1297.  
  1298.             /* Process the incoming window
  1299.              * input.
  1300.              */
  1301.  
  1302.         while(Massage = (struct IntuiMessage *)GetMsg(BufferInfo->Window->UserPort))
  1303.         {
  1304.             if(Context && Context->SearchWindow == Massage->IDCMPWindow)
  1305.             {
  1306.                 MsgClass = NULL;
  1307.  
  1308.                 if(HandleSearchMessage(Context,&Massage))
  1309.                 {
  1310.                     BOOL Ok = Context->Ok;
  1311.  
  1312.                     DeleteSearchContext(Context);
  1313.  
  1314.                     Context = NULL;
  1315.  
  1316.                     if(Ok)
  1317.                     {
  1318.                         if(SearchInfo)
  1319.                             DeleteSearchInfo(SearchInfo);
  1320.  
  1321.                         if(SearchInfo = CreateSearchInfo(SearchBuffer,BufferInfo->SearchForward,BufferInfo->IgnoreCase,BufferInfo->WholeWords))
  1322.                             StartSearch(BufferInfo,SearchInfo,SearchBuffer);
  1323.                     }
  1324.                     else
  1325.                     {
  1326.                         if(SearchInfo)
  1327.                             DeleteSearchInfo(SearchInfo);
  1328.  
  1329.                         SearchInfo = NULL;
  1330.                     }
  1331.                 }
  1332.             }
  1333.             else
  1334.             {
  1335.                 MsgClass        = Massage->Class;
  1336.                 MsgCode            = Massage->Code;
  1337.                 MsgQualifier    = Massage->Qualifier;
  1338.                 MouseX            = Massage->MouseX - BufferInfo->Left;
  1339.                 MouseY            = Massage->MouseY - BufferInfo->Top;
  1340.                 TagList            = (struct TagItem *)Massage->IAddress;
  1341.                 Seconds            = Massage->Seconds;
  1342.                 Micros            = Massage->Micros;
  1343.  
  1344.                 ClickAndActivate = FALSE;
  1345.  
  1346.                 if(Seconds == LastSeconds && Micros == LastMicros)
  1347.                 {
  1348.                     if(Massage->Class == IDCMP_ACTIVEWINDOW || Massage->Class == IDCMP_MOUSEBUTTONS)
  1349.                         ClickAndActivate = TRUE;
  1350.                 }
  1351.  
  1352.                 LastSeconds    = Seconds;
  1353.                 LastMicros    = Micros;
  1354.  
  1355.                     /* This hack is necessary to obtain the
  1356.                      * character codes generated for the cursor
  1357.                      * keys. A control or alternate qualifier
  1358.                      * would spoil the result (i.e. we would
  1359.                      * not get a valid key code).
  1360.                      */
  1361.  
  1362.                 Massage->Qualifier = NULL;
  1363.  
  1364.                 Char = KeyConvert(Massage,NULL,NULL);
  1365.  
  1366.                     // Put the qualifier back and do it all again
  1367.  
  1368.                 Massage->Qualifier = MsgQualifier;
  1369.  
  1370.                 FullChar = KeyConvert(Massage,NULL,NULL);
  1371.  
  1372.                 ReplyMsg((struct Message *)Massage);
  1373.             }
  1374.  
  1375.             if(MsgClass == IDCMP_ACTIVEWINDOW)
  1376.                 UpdatePercent = TRUE;
  1377.  
  1378.             if(MsgClass == IDCMP_IDCMPUPDATE)
  1379.             {
  1380.                 switch(GetTagData(GA_ID,0,TagList))
  1381.                 {
  1382.                     case GAD_UP:
  1383.  
  1384.                         if(BufferInfo->TopLine > 0)
  1385.                         {
  1386.                             BufferInfo->TopLine--;
  1387.  
  1388.                             MarkArea(BufferInfo,-1,-1,-1);
  1389.  
  1390.                             SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1391.                                 PGA_Top,BufferInfo->TopLine,
  1392.                             TAG_DONE);
  1393.  
  1394.                             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine);
  1395.  
  1396.                             UpdatePercent = TRUE;
  1397.                         }
  1398.  
  1399.                         break;
  1400.  
  1401.                     case GAD_DOWN:
  1402.  
  1403.                         if(BufferInfo->TopLine + BufferInfo->NumBufferLines < Lines)
  1404.                         {
  1405.                             BufferInfo->TopLine++;
  1406.  
  1407.                             MarkArea(BufferInfo,-1,-1,-1);
  1408.  
  1409.                             SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1410.                                 PGA_Top,BufferInfo->TopLine,
  1411.                             TAG_DONE);
  1412.  
  1413.                             BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine);
  1414.  
  1415.                             UpdatePercent = TRUE;
  1416.                         }
  1417.  
  1418.                         break;
  1419.                 }
  1420.             }
  1421.  
  1422.             if(MsgClass == IDCMP_MOUSEMOVE || MsgClass == IDCMP_GADGETDOWN || MsgClass == IDCMP_GADGETUP)
  1423.             {
  1424.                 LONG Position;
  1425.  
  1426.                 GetAttr(PGA_Top,BufferInfo->Scroller,(ULONG *)&Position);
  1427.  
  1428.                 if(Position != BufferInfo->TopLine)
  1429.                 {
  1430.                     MarkArea(BufferInfo,-1,-1,-1);
  1431.  
  1432.                     BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine = Position);
  1433.  
  1434.                     UpdatePercent = TRUE;
  1435.                 }
  1436.             }
  1437.  
  1438.             if(MsgClass == IDCMP_RAWKEY)
  1439.             {
  1440.                 if(MsgCode == HELP_CODE)
  1441.                     GuideDisplay(CONTEXT_TEXTBUFFER);
  1442.  
  1443.                 if(LastChar)
  1444.                 {
  1445.                     if((MsgCode & IECODE_UP_PREFIX) || !(LastQualifier & IEQUALIFIER_REPEAT))
  1446.                     {
  1447.                         SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1448.                             PGA_Top,BufferInfo->TopLine,
  1449.                         TAG_DONE);
  1450.  
  1451.                         UpdatePercent = TRUE;
  1452.                     }
  1453.                 }
  1454.  
  1455.                 if(LastChar = Char)
  1456.                 {
  1457.                         /* Use the numeric keypad keys to
  1458.                          * move through the buffer.
  1459.                          */
  1460.  
  1461.                     if(MsgQualifier & IEQUALIFIER_NUMERICPAD)
  1462.                     {
  1463.                             /* Remove the numpad qualifier. */
  1464.  
  1465.                         MsgQualifier &= ~IEQUALIFIER_NUMERICPAD;
  1466.  
  1467.                         switch(Char - '0')
  1468.                         {
  1469.                                 /* Jump to bottom. */
  1470.  
  1471.                             case 1:
  1472.  
  1473.                                 Char = CDN;
  1474.                                 MsgQualifier |= IEQUALIFIER_CONTROL;
  1475.                                 break;
  1476.  
  1477.                                 /* Move one line down. */
  1478.  
  1479.                             case 2:
  1480.  
  1481.                                 Char = CDN;
  1482.                                 break;
  1483.  
  1484.                                 /* Move one page down. */
  1485.  
  1486.                             case 3:
  1487.  
  1488.                                 Char = CDN;
  1489.                                 MsgQualifier |= IEQUALIFIER_LSHIFT;
  1490.                                 break;
  1491.  
  1492.                                 /* Jump to top. */
  1493.  
  1494.                             case 7:
  1495.  
  1496.                                 Char = CUP;
  1497.                                 MsgQualifier |= IEQUALIFIER_CONTROL;
  1498.                                 break;
  1499.  
  1500.                                 /* Move one line up. */
  1501.  
  1502.                             case 8:
  1503.  
  1504.                                 Char = CUP;
  1505.                                 break;
  1506.  
  1507.                                 /* Move one page up. */
  1508.  
  1509.                             case 9:
  1510.  
  1511.                                 Char = CUP;
  1512.                                 MsgQualifier |= IEQUALIFIER_LSHIFT;
  1513.                                 break;
  1514.                         }
  1515.                     }
  1516.  
  1517.                         /* Check cursor keys. */
  1518.  
  1519.                     switch(Char)
  1520.                     {
  1521.                             /* Scroll the buffer up. */
  1522.  
  1523.                         case CUP:
  1524.  
  1525.                             if(MsgQualifier & (IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1526.                             {
  1527.                                 MarkArea(BufferInfo,-1,-1,-1);
  1528.  
  1529.                                 if(BufferInfo->TopLine)
  1530.                                 {
  1531.                                     BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,0);
  1532.  
  1533.                                     BufferInfo->TopLine = 0;
  1534.                                     LastChar = 0;
  1535.  
  1536.                                     SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1537.                                         PGA_Top,BufferInfo->TopLine,
  1538.                                     TAG_DONE);
  1539.  
  1540.                                     UpdatePercent = TRUE;
  1541.                                 }
  1542.  
  1543.                                 break;
  1544.                             }
  1545.  
  1546.                             if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1547.                             {
  1548.                                 LONG NewCurrentLine;
  1549.  
  1550.                                 if((NewCurrentLine = BufferInfo->TopLine - BufferInfo->NumBufferLines) < 0)
  1551.                                     NewCurrentLine = 0;
  1552.  
  1553.                                 MarkArea(BufferInfo,-1,-1,-1);
  1554.  
  1555.                                 if(NewCurrentLine != BufferInfo->TopLine)
  1556.                                 {
  1557.                                     BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1558.  
  1559.                                     BufferInfo->TopLine = NewCurrentLine;
  1560.  
  1561.                                     LastChar = 0;
  1562.  
  1563.                                     SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1564.                                         PGA_Top,BufferInfo->TopLine,
  1565.                                     TAG_DONE);
  1566.  
  1567.                                     UpdatePercent = TRUE;
  1568.                                 }
  1569.  
  1570.                                 break;
  1571.                             }
  1572.  
  1573.                             if(BufferInfo->TopLine)
  1574.                             {
  1575.                                 MarkArea(BufferInfo,-1,-1,-1);
  1576.  
  1577.                                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,--BufferInfo->TopLine);
  1578.  
  1579.                                 UpdatePercent = TRUE;
  1580.                             }
  1581.  
  1582.                             break;
  1583.  
  1584.                             /* Scroll the buffer down. */
  1585.  
  1586.                         case CDN:
  1587.  
  1588.                             if(MsgQualifier & (IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1589.                             {
  1590.                                 LONG NewCurrentLine;
  1591.  
  1592.                                 if((NewCurrentLine = Lines - BufferInfo->NumBufferLines) < 0)
  1593.                                     NewCurrentLine = 0;
  1594.  
  1595.                                 MarkArea(BufferInfo,-1,-1,-1);
  1596.  
  1597.                                 if(BufferInfo->TopLine != NewCurrentLine)
  1598.                                 {
  1599.                                     BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1600.  
  1601.                                     BufferInfo->TopLine = NewCurrentLine;
  1602.  
  1603.                                     LastChar = 0;
  1604.  
  1605.                                     SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1606.                                         PGA_Top,BufferInfo->TopLine,
  1607.                                     TAG_DONE);
  1608.  
  1609.                                     UpdatePercent = TRUE;
  1610.                                 }
  1611.  
  1612.                                 break;
  1613.                             }
  1614.  
  1615.                             if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1616.                             {
  1617.                                 LONG NewCurrentLine;
  1618.  
  1619.                                 if((NewCurrentLine = BufferInfo->TopLine + (2 * BufferInfo->NumBufferLines)) > Lines)
  1620.                                     NewCurrentLine = Lines;
  1621.  
  1622.                                 if((NewCurrentLine = NewCurrentLine - BufferInfo->NumBufferLines) < 0)
  1623.                                     NewCurrentLine = 0;
  1624.  
  1625.                                 MarkArea(BufferInfo,-1,-1,-1);
  1626.  
  1627.                                 if(NewCurrentLine != BufferInfo->TopLine)
  1628.                                 {
  1629.                                     BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,NewCurrentLine);
  1630.  
  1631.                                     BufferInfo->TopLine = NewCurrentLine;
  1632.  
  1633.                                     LastChar = 0;
  1634.  
  1635.                                     SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1636.                                         PGA_Top,BufferInfo->TopLine,
  1637.                                     TAG_DONE);
  1638.  
  1639.                                     UpdatePercent = TRUE;
  1640.                                 }
  1641.  
  1642.                                 break;
  1643.                             }
  1644.  
  1645.                             if(BufferInfo->TopLine + BufferInfo->NumBufferLines < Lines)
  1646.                             {
  1647.                                 MarkArea(BufferInfo,-1,-1,-1);
  1648.  
  1649.                                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine + 1);
  1650.  
  1651.                                 BufferInfo->TopLine++;
  1652.  
  1653.                                 UpdatePercent = TRUE;
  1654.                             }
  1655.  
  1656.                             break;
  1657.  
  1658.                         default:
  1659.  
  1660.                             if(BufferInfo->Parent)
  1661.                             {
  1662.                                 Char = FullChar;
  1663.  
  1664.                                 if(Config->SerialConfig->StripBit8)
  1665.                                     Char &= 0x7F;
  1666.  
  1667.                                 if(Status == STATUS_HOLDING)
  1668.                                 {
  1669.                                     if(Char == XOF)
  1670.                                     {
  1671.                                         BufferSerWrite(BufferInfo,&Char,1);
  1672.  
  1673.                                         Status = STATUS_READY;
  1674.                                     }
  1675.                                 }
  1676.                                 else
  1677.                                 {
  1678.                                         // Convert chars as appropriate
  1679.  
  1680.                                     if(Char == '\n')
  1681.                                     {
  1682.                                         switch(Config->TerminalConfig->SendLF)
  1683.                                         {
  1684.                                             case EOL_LF:
  1685.  
  1686.                                                 goto SendIt;
  1687.  
  1688.                                             case EOL_LFCR:
  1689.  
  1690.                                                 BufferSerWrite(BufferInfo,"\n\r",2);
  1691.                                                 break;
  1692.  
  1693.                                             case EOL_CRLF:
  1694.  
  1695.                                                 BufferSerWrite(BufferInfo,"\r\n",2);
  1696.                                                 break;
  1697.  
  1698.                                             case EOL_CR:
  1699.  
  1700.                                                 BufferSerWrite(BufferInfo,"\r",1);
  1701.                                                 break;
  1702.                                         }
  1703.                                     }
  1704.  
  1705.                                     if(Char == '\r')
  1706.                                     {
  1707.                                         switch(Config->TerminalConfig->SendCR)
  1708.                                         {
  1709.                                             case EOL_CR:
  1710.  
  1711.                                                 goto SendIt;
  1712.  
  1713.                                             case EOL_LFCR:
  1714.  
  1715.                                                 BufferSerWrite(BufferInfo,"\n\r",2);
  1716.                                                 break;
  1717.  
  1718.                                             case EOL_CRLF:
  1719.  
  1720.                                                 BufferSerWrite(BufferInfo,"\r\n",2);
  1721.                                                 break;
  1722.  
  1723.                                             case EOL_LF:
  1724.  
  1725.                                                 BufferSerWrite(BufferInfo,"\n",1);
  1726.                                                 break;
  1727.                                         }
  1728.                                     }
  1729.  
  1730.                                         /* Stop in/output. */
  1731.  
  1732.                                     if(Char == XON)
  1733.                                     {
  1734.                                         if(Config->SerialConfig->PassThrough)
  1735.                                             BufferSerWrite(BufferInfo,&Char,1);
  1736.  
  1737.                                         if(Config->SerialConfig->xONxOFF)
  1738.                                             Status = STATUS_HOLDING;
  1739.                                     }
  1740.  
  1741.                                         /* Restart in/output. */
  1742.  
  1743.                                     if(Char == XOF)
  1744.                                     {
  1745.                                         if(Config->SerialConfig->PassThrough)
  1746.                                             BufferSerWrite(BufferInfo,&Char,1);
  1747.  
  1748.                                         if(Status == STATUS_HOLDING)
  1749.                                             Status = STATUS_READY;
  1750.                                     }
  1751.  
  1752.                                         /* Convert special
  1753.                                          * Amiga characters into
  1754.                                          * alien IBM dialect.
  1755.                                          */
  1756.  
  1757. SendIt:                                if(Config->TerminalConfig->FontMode == FONT_IBM)
  1758.                                     {
  1759.                                         if(IBMConversion[Char])
  1760.                                             BufferSerWrite(BufferInfo,&IBMConversion[Char],1);
  1761.                                         else
  1762.                                             BufferSerWrite(BufferInfo,&Char,1);
  1763.                                     }
  1764.                                     else
  1765.                                         BufferSerWrite(BufferInfo,&Char,1);
  1766.                             }
  1767.  
  1768.                             break;
  1769.                         }
  1770.                     }
  1771.  
  1772.                     LastQualifier = MsgQualifier;
  1773.                 }
  1774.                 else
  1775.                     LastQualifier = NULL;
  1776.  
  1777.                 continue;
  1778.             }
  1779.  
  1780.                 /* User hit a mouse button. */
  1781.  
  1782.             if(MsgClass == IDCMP_MOUSEBUTTONS && (!ClickAndActivate || MsgCode != SELECTDOWN) && !(MsgCode & IECODE_UP_PREFIX))
  1783.             {
  1784.                 MarkArea(BufferInfo,-1,-1,-1);
  1785.  
  1786.                     /* Reasonable dimensions? */
  1787.  
  1788.                 if(MouseY / BufferInfo->LocalTextFontHeight < BufferInfo->DisplayedLines && MouseX / BufferInfo->LocalTextFontWidth < BufferInfo->NumBufferColumns)
  1789.                 {
  1790.                     ObtainSemaphore(BufferSemaphore);
  1791.  
  1792.                     BufferClip(BufferInfo);
  1793.  
  1794.                     UpdatePercent = TRUE;
  1795.  
  1796.                     BufferInfo->LastTopLine = BufferInfo->TopLine;
  1797.  
  1798.                     ReleaseSemaphore(BufferSemaphore);
  1799.  
  1800.                     if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1801.                     {
  1802.                         struct DataMsg Msg;
  1803.  
  1804.                         InitMsgItem(&Msg,BufferDestructor);
  1805.  
  1806.                         Msg.Type    = DATAMSGTYPE_WRITECLIP;
  1807.                         Msg.Size    = Config->ClipConfig->ClipboardUnit;
  1808.                         Msg.Client    = FindTask(NULL);
  1809.                         Msg.Mask    = 1UL << BufferInfo->BufferSignal;
  1810.  
  1811.                         Forbid();
  1812.  
  1813.                         ClrSignal(1L << BufferInfo->BufferSignal);
  1814.  
  1815.                         PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1816.  
  1817.                         Wait(1L << BufferInfo->BufferSignal);
  1818.  
  1819.                         Permit();
  1820.                     }
  1821.  
  1822.                     break;
  1823.                 }
  1824.             }
  1825.  
  1826.             if(MsgClass == IDCMP_MENUHELP)
  1827.                 GuideDisplay(CONTEXT_BUFFER_MENU);
  1828.  
  1829.             if(MsgClass == IDCMP_CLOSEWINDOW)
  1830.                 BufferInfo->BufferTerminated = TRUE;
  1831.  
  1832.             if(MsgClass == IDCMP_NEWSIZE)
  1833.             {
  1834.                 LONG Width,Height;
  1835.  
  1836.                 MarkArea(BufferInfo,-1,-1,-1);
  1837.  
  1838.                 BufferInfo->LastTopLine = -1;
  1839.  
  1840.                 BufferInfo->Width                = BufferInfo->Window->Width        - (BufferInfo->Window->BorderLeft    + BufferInfo->Window->BorderRight);
  1841.                 BufferInfo->Height                = BufferInfo->Window->Height    - (BufferInfo->Window->BorderTop    + BufferInfo->Window->BorderBottom);
  1842.  
  1843.                 Width                            = BufferInfo->Width    - (BufferInfo->Width    % BufferInfo->LocalTextFontWidth);
  1844.                 Height                            = BufferInfo->Height    - (BufferInfo->Height    % BufferInfo->LocalTextFontHeight);
  1845.  
  1846.                 BufferInfo->NumBufferColumns    = BufferInfo->Width / BufferInfo->LocalTextFontWidth;
  1847.                 BufferInfo->NumBufferLines        = BufferInfo->Height / BufferInfo->LocalTextFontHeight;
  1848.  
  1849.                 if(Width < BufferInfo->Width)
  1850.                     BufferClear(BufferInfo,Width,0,BufferInfo->Width - 1,BufferInfo->Height - 1);
  1851.  
  1852.                 if(Height < BufferInfo->Height)
  1853.                     BufferClear(BufferInfo,0,Height,BufferInfo->Width - 1,BufferInfo->Height - 1);
  1854.  
  1855.                 BufferInfo->Width    = Width;
  1856.                 BufferInfo->Height    = Height;
  1857.  
  1858.                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine);
  1859.  
  1860.                 SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  1861.                     PGA_Total,        Lines,
  1862.                     PGA_Top,        BufferInfo->TopLine,
  1863.                     PGA_Visible,    BufferInfo->DisplayedLines,
  1864.                 TAG_DONE);
  1865.  
  1866.                 UpdatePercent = TRUE;
  1867.             }
  1868.  
  1869.             if(MsgClass == IDCMP_MENUPICK)
  1870.             {
  1871.                 struct MenuItem    *MenuItem;
  1872.                 struct DataMsg     Msg;
  1873.  
  1874.                 while(MsgCode != MENUNULL)
  1875.                 {
  1876.                     if(MenuItem = ItemAddress(BufferInfo->BufferMenuStrip,MsgCode))
  1877.                     {
  1878.                         switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
  1879.                         {
  1880.                             case MEN_PASTECLIP:
  1881.  
  1882.                                 InitMsgItem(&Msg,BufferDestructor);
  1883.  
  1884.                                 Msg.Type    = DATAMSGTYPE_WRITECLIP;
  1885.                                 Msg.Size    = Config->ClipConfig->ClipboardUnit;
  1886.                                 Msg.Client    = FindTask(NULL);
  1887.                                 Msg.Mask    = 1UL << BufferInfo->BufferSignal;
  1888.  
  1889.                                 Forbid();
  1890.  
  1891.                                 ClrSignal(Msg.Mask);
  1892.  
  1893.                                 PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1894.  
  1895.                                 Wait(Msg.Mask);
  1896.  
  1897.                                 Permit();
  1898.                                 break;
  1899.  
  1900.                             case MEN_SEARCH:
  1901.  
  1902.                                 if(Context)
  1903.                                     LT_ShowWindow(Context->SearchHandle,TRUE);
  1904.                                 else
  1905.                                     Context = CreateSearchContext(BufferInfo->Window,SearchBuffer,&HistoryHook,&BufferInfo->SearchForward,&BufferInfo->IgnoreCase,&BufferInfo->WholeWords);
  1906.  
  1907.                                 UpdatePercent = TRUE;
  1908.  
  1909.                                 break;
  1910.  
  1911.                             case MEN_REPEAT:
  1912.  
  1913.                                 if(Context)
  1914.                                     LT_ShowWindow(Context->SearchHandle,TRUE);
  1915.                                 else
  1916.                                 {
  1917.                                     if(SearchInfo)
  1918.                                         StartSearch(BufferInfo,SearchInfo,SearchBuffer);
  1919.                                     else
  1920.                                         Context = CreateSearchContext(BufferInfo->Window,SearchBuffer,&HistoryHook,&BufferInfo->SearchForward,&BufferInfo->IgnoreCase,&BufferInfo->WholeWords);
  1921.                                 }
  1922.  
  1923.                                 UpdatePercent = TRUE;
  1924.  
  1925.                                 break;
  1926.  
  1927.                             case MEN_GOTO:
  1928.  
  1929.                                 if(Window)
  1930.                                     BumpWindow(Window);
  1931.  
  1932.                                 break;
  1933.  
  1934.                             case MEN_QUITBUF:
  1935.  
  1936.                                 BufferInfo->BufferTerminated = TRUE;
  1937.                                 break;
  1938.  
  1939.                             case MEN_CLEARBUF_CONTENTS:
  1940.  
  1941.                                 if(Lines)
  1942.                                 {
  1943.                                     struct DataMsg *Msg;
  1944.  
  1945.                                     if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg)))
  1946.                                     {
  1947.                                         Msg->Type = DATAMSGTYPE_CLEARBUFFER;
  1948.  
  1949.                                         UpdatePercent = TRUE;
  1950.  
  1951.                                         LT_LockWindow(BufferInfo->Window);
  1952.  
  1953.                                         if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1954.                                         {
  1955.                                             PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  1956.                                             Msg = NULL;
  1957.                                         }
  1958.                                         else
  1959.                                         {
  1960.                                             if(Config->MiscConfig->ProtectiveMode)
  1961.                                             {
  1962.                                                 if(!ShowRequest(BufferInfo->Window,LocaleString(MSG_TERMBUFFER_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines))
  1963.                                                 {
  1964.                                                     LT_UnlockWindow(BufferInfo->Window);
  1965.  
  1966.                                                     break;
  1967.                                                 }
  1968.                                             }
  1969.  
  1970.                                             PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  1971.                                             Msg = NULL;
  1972.                                         }
  1973.  
  1974.                                         DeleteMsgItem(Msg);
  1975.                                     }
  1976.  
  1977.                                     LT_UnlockWindow(BufferInfo->Window);
  1978.  
  1979.                                     FlushMsg(BufferInfo->Window);
  1980.                                 }
  1981.  
  1982.                                 break;
  1983.                         }
  1984.  
  1985.                         MsgCode = MenuItem->NextSelect;
  1986.                     }
  1987.                     else
  1988.                         break;
  1989.                 }
  1990.             }
  1991.  
  1992.         }
  1993.     }
  1994.  
  1995.     if(Context)
  1996.         DeleteSearchContext(Context);
  1997.  
  1998.     if(SearchInfo)
  1999.         DeleteSearchInfo(SearchInfo);
  2000.  
  2001.         // Put the stuff back
  2002.  
  2003.     *BufferInfo->pTopLine        = BufferInfo->TopLine;
  2004.     *BufferInfo->pSearchForward    = BufferInfo->SearchForward;
  2005.     *BufferInfo->pIgnoreCase    = BufferInfo->IgnoreCase;
  2006.     *BufferInfo->pWholeWords    = BufferInfo->WholeWords;
  2007.  
  2008.     return(RingBack);
  2009. }
  2010.  
  2011. STATIC VOID
  2012. DeleteBufferInfo(TextBufferInfo *BufferInfo)
  2013. {
  2014.     if(BufferInfo)
  2015.     {
  2016.         FreeVecPooled(BufferInfo->BufferLineWidths);
  2017.  
  2018.         if(BufferInfo->Window)
  2019.         {
  2020.             ClearMenuStrip(BufferInfo->Window);
  2021.  
  2022.             LT_DeleteWindowLock(BufferInfo->Window);
  2023.  
  2024.             CloseWindow(BufferInfo->Window);
  2025.         }
  2026.  
  2027.         DeleteScroller(BufferInfo);
  2028.  
  2029.         DisposeObject(BufferInfo->BufferAmigaGlyph);
  2030.         DisposeObject(BufferInfo->BufferCheckGlyph);
  2031.  
  2032.         FreeScreenDrawInfo(BufferInfo->Screen,BufferInfo->BufferDrawInfo);
  2033.  
  2034.         LT_DisposeMenu(BufferInfo->BufferMenuStrip);
  2035.  
  2036.         if(BufferInfo->Screen && !BufferInfo->Parent)
  2037.             CloseScreen(BufferInfo->Screen);
  2038.  
  2039.         if(BufferInfo->LocalFont)
  2040.             CloseFont(BufferInfo->LocalFont);
  2041.  
  2042.         if(BufferInfo->BufferSignal != -1)
  2043.             FreeSignal(BufferInfo->BufferSignal);
  2044.  
  2045.         DeleteMsgQueue(BufferInfo->Queue);
  2046.  
  2047.         FreeVecPooled(BufferInfo);
  2048.     }
  2049. }
  2050.  
  2051. STATIC TextBufferInfo *
  2052. CreateBufferInfo(struct Screen *Parent,BOOLEAN *pSearchForward,BOOLEAN *pIgnoreCase,BOOLEAN *pWholeWords,LONG *pTopLine)
  2053. {
  2054.     TextBufferInfo *BufferInfo;
  2055.  
  2056.     if(BufferInfo = (TextBufferInfo *)AllocVecPooled(sizeof(TextBufferInfo),MEMF_ANY | MEMF_CLEAR))
  2057.     {
  2058.         BOOL                         Defaults;
  2059.  
  2060.         struct ColorSpec             ColorSpec[3];
  2061.  
  2062.         LONG                         Width,Height;
  2063.         ULONG                         DisplayMode;
  2064.  
  2065.         struct Rectangle             DisplayClip;
  2066.         struct DimensionInfo         DimensionInfo;
  2067.  
  2068.         BufferInfo->pSearchForward    = pSearchForward;
  2069.         BufferInfo->pIgnoreCase        = pIgnoreCase;
  2070.         BufferInfo->pWholeWords        = pWholeWords;
  2071.         BufferInfo->pTopLine        = pTopLine;
  2072.  
  2073.         BufferInfo->TopLine            = *pTopLine;
  2074.         BufferInfo->LastTopLine        = -1;
  2075.  
  2076.         BufferInfo->SearchForward    = *pSearchForward;
  2077.         BufferInfo->IgnoreCase        = *pIgnoreCase;
  2078.         BufferInfo->WholeWords        = *pWholeWords;
  2079.  
  2080.         BufferInfo->OldColumn        = -1;
  2081.         BufferInfo->OldLine            = -1;
  2082.         BufferInfo->OldLength        = -1;
  2083.  
  2084.         BufferInfo->Buddy            = (struct Process *)FindTask(NULL);
  2085.  
  2086.         CopyMem(&TextFont,&BufferInfo->LocalTextFont,sizeof(struct TTextAttr));
  2087.  
  2088.         BufferInfo->LocalTextFont.tta_Name    = BufferInfo->LocalTextFontName;
  2089.         BufferInfo->LocalTextFont.tta_YSize    = Config->TerminalConfig->TextFontHeight;
  2090.  
  2091.         strcpy(BufferInfo->LocalTextFontName,Config->TerminalConfig->TextFontName);
  2092.  
  2093.         CopyMem(&UserFont,&BufferInfo->LocalUserFont,sizeof(struct TTextAttr));
  2094.  
  2095.         BufferInfo->LocalUserFont.tta_Name = BufferInfo->LocalUserFontName;
  2096.  
  2097.         strcpy(BufferInfo->LocalUserFontName,UserFont.tta_Name);
  2098.  
  2099.         if(!Config->CaptureConfig->ConvertChars && Config->TerminalConfig->FontMode != FONT_STANDARD)
  2100.         {
  2101.             strcpy(BufferInfo->LocalTextFontName,Config->TerminalConfig->IBMFontName);
  2102.  
  2103.             BufferInfo->LocalTextFont.tta_YSize = Config->TerminalConfig->IBMFontHeight;
  2104.  
  2105.             BufferInfo->NeedClipConversion = TRUE;
  2106.         }
  2107.         else
  2108.             BufferInfo->NeedClipConversion = FALSE;
  2109.  
  2110.         if(BufferInfo->LocalFont = OpenDiskFont(&BufferInfo->LocalTextFont))
  2111.         {
  2112.             BufferInfo->LocalTextFontWidth    = BufferInfo->LocalFont->tf_XSize;
  2113.             BufferInfo->LocalTextFontHeight    = BufferInfo->LocalFont->tf_YSize;
  2114.  
  2115.             Forbid();
  2116.  
  2117.             if(Window && DrawInfo)
  2118.             {
  2119.                 LONG Colour;
  2120.  
  2121.                     /* Set up the startup colours for our buffer screen. */
  2122.  
  2123.                 ColorSpec[0].ColorIndex = 0;
  2124.  
  2125.                 Colour = GetRGB4(Window->WScreen->ViewPort.ColorMap,Pens[BACKGROUNDPEN]);
  2126.  
  2127.                 ColorSpec[0].Red    = (Colour >> 8) & 0xF;
  2128.                 ColorSpec[0].Green    = (Colour >> 4) & 0xF;
  2129.                 ColorSpec[0].Blue    = (Colour     ) & 0xF;
  2130.  
  2131.                 ColorSpec[1].ColorIndex = 1;
  2132.  
  2133.                 Colour = GetRGB4(Window->WScreen->ViewPort.ColorMap,Pens[TEXTPEN]);
  2134.  
  2135.                 ColorSpec[1].Red    = (Colour >> 8) & 0xF;
  2136.                 ColorSpec[1].Green    = (Colour >> 4) & 0xF;
  2137.                 ColorSpec[1].Blue    = (Colour     ) & 0xF;
  2138.  
  2139.                 ColorSpec[2].ColorIndex = -1;
  2140.  
  2141.                 Defaults = FALSE;
  2142.             }
  2143.             else
  2144.                 Defaults = TRUE;
  2145.  
  2146.             Permit();
  2147.  
  2148.             DisplayMode = Config->CaptureConfig->BufferScreenMode;
  2149.  
  2150.             if(ModeNotAvailable(DisplayMode))
  2151.                 DisplayMode = Config->ScreenConfig->DisplayMode;
  2152.  
  2153.             if(ModeNotAvailable(DisplayMode))
  2154.             {
  2155.                 struct Screen *PubScreen = LockPubScreen(NULL);
  2156.  
  2157.                 if(PubScreen)
  2158.                 {
  2159.                     DisplayMode = GetVPModeID(&PubScreen->ViewPort);
  2160.  
  2161.                     UnlockPubScreen(NULL,PubScreen);
  2162.                 }
  2163.                 else
  2164.                     DisplayMode = DEFAULT_MONITOR_ID | HIRES_KEY;
  2165.             }
  2166.  
  2167.                 /* Set up the actual width of the screen we want. */
  2168.  
  2169.             Width = Config->CaptureConfig->BufferWidth * BufferInfo->LocalTextFontWidth + BufferInfo->ArrowWidth + 1;
  2170.  
  2171.             if((BufferInfo->BufferSignal = AllocSignal(-1)) != -1)
  2172.             {
  2173.                     /* Get the mode dimension info. */
  2174.  
  2175.                 if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,DisplayMode))
  2176.                 {
  2177.                         /* Determine maximum text overscan width. */
  2178.  
  2179.                     LONG TextWidth = DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1;
  2180.  
  2181.                         /* Too small? */
  2182.  
  2183.                     if(Width < DimensionInfo.MinRasterWidth)
  2184.                         Width = DimensionInfo.MinRasterWidth;
  2185.  
  2186.                         /* Far too large? */
  2187.  
  2188.                     if(Width > DimensionInfo.MaxRasterWidth)
  2189.                         Width = DimensionInfo.MaxRasterWidth;
  2190.  
  2191.                         /* A bit too large? */
  2192.  
  2193.                     if(Width > TextWidth)
  2194.                         Width = TextWidth;
  2195.  
  2196.                         /* Inquire the text overscan dimensions. */
  2197.  
  2198.                     if(QueryOverscan(DisplayMode,&DisplayClip,OSCAN_TEXT))
  2199.                     {
  2200.                             /* Centre the buffer screen. */
  2201.  
  2202.                         if(DisplayClip.MaxX - DisplayClip.MinX + 1 > Width)
  2203.                         {
  2204.                             LONG Differ = (DisplayClip.MaxX - DisplayClip.MinX + 1 - Width) / 2;
  2205.  
  2206.                             switch(Config->CaptureConfig->BufferScreenPosition)
  2207.                             {
  2208.                                 case SCREEN_LEFT:
  2209.  
  2210.                                     DisplayClip.MaxX = DisplayClip.MinX + Width;
  2211.                                     break;
  2212.  
  2213.                                 case SCREEN_RIGHT:
  2214.  
  2215.                                     DisplayClip.MinX = DisplayClip.MaxX - Width;
  2216.                                     break;
  2217.  
  2218.                                 case SCREEN_CENTRE:
  2219.  
  2220.                                     DisplayClip.MinX += Differ;
  2221.                                     DisplayClip.MaxX -= Differ;
  2222.  
  2223.                                     break;
  2224.                             }
  2225.                         }
  2226.  
  2227.                             /* Open a single bitplane clone of the main screen. */
  2228.  
  2229.                         if(Parent)
  2230.                         {
  2231.                             BufferInfo->Parent = Parent;
  2232.                             BufferInfo->Screen = Parent;
  2233.  
  2234.                             if(BufferInfo->Queue = CreateMsgQueue(NULL,0))
  2235.                                 BufferInfo->QueueMask = BufferInfo->Queue->SigMask;
  2236.                             else
  2237.                                 BufferInfo->Screen = NULL;
  2238.                         }
  2239.                         else
  2240.                         {
  2241.                             BufferInfo->Screen = OpenScreenTags(NULL,
  2242.                                 SA_Title,        LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),
  2243.                                 SA_Depth,        1,
  2244.                                 SA_Left,        DisplayClip.MinX,
  2245.                                 SA_DClip,        &DisplayClip,
  2246.                                 SA_DisplayID,    DisplayMode,
  2247.                                 SA_Font,        &BufferInfo->LocalUserFont,
  2248.                                 SA_Behind,        TRUE,
  2249.                                 SA_AutoScroll,    TRUE,
  2250.  
  2251.                                 Defaults ? TAG_IGNORE : SA_Colors,ColorSpec,
  2252.                             TAG_END);
  2253.                         }
  2254.  
  2255.                         if(BufferInfo->Screen)
  2256.                         {
  2257.                             if(BufferInfo->BufferDrawInfo = GetScreenDrawInfo(BufferInfo->Screen))
  2258.                             {
  2259.                                 ULONG *MenuTags;
  2260.  
  2261.                                 CreateMenuGlyphs(BufferInfo->Screen,BufferInfo->BufferDrawInfo,&BufferInfo->BufferAmigaGlyph,&BufferInfo->BufferCheckGlyph);
  2262.  
  2263.                                 if(Parent)
  2264.                                 {
  2265.                                     STATIC ULONG ReviewTags[] =
  2266.                                     {
  2267.                                         LAMN_TitleID,            MSG_TERMREVIEW_PROJECT_MEN,
  2268.                                             LAMN_ItemID,        MSG_TERMREVIEW_SEARCH_MEN,
  2269.                                                 LAMN_UserData,    MEN_SEARCH,
  2270.                                             LAMN_ItemID,        MSG_TERMREVIEW_REPEAT_SEARCH_MEN,
  2271.                                                 LAMN_UserData,    MEN_REPEAT,
  2272.  
  2273.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2274.  
  2275.                                             LAMN_ItemID,        MSG_TERMREVIEW_CLEAR_BUFFER_MEN,
  2276.                                                 LAMN_UserData,    MEN_CLEARBUF_CONTENTS,
  2277.  
  2278.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2279.  
  2280.                                             LAMN_ItemID,        MSG_TERMREVIEW_CLOSE_BUFFER_MEN,
  2281.                                                 LAMN_UserData,    MEN_QUITBUF,
  2282.  
  2283.                                             LAMN_ItemID,        MSG_CLOSE_WINDOW_TXT,
  2284.                                                 LAMN_KeyText,    (ULONG)":",
  2285.                                                 LAMN_UserData,    MEN_QUITBUF,
  2286.  
  2287.                                         LAMN_TitleID,            MSG_TERMBUFFER_EDIT_MEN,
  2288.                                             LAMN_ItemID,        MSG_TERMBUFFER_PASTE_MEN,
  2289.                                                 LAMN_UserData,    MEN_PASTECLIP,
  2290.  
  2291.                                         TAG_DONE
  2292.                                     };
  2293.  
  2294.                                     MenuTags = ReviewTags;
  2295.                                 }
  2296.                                 else
  2297.                                 {
  2298.                                     STATIC ULONG BufferTags[] =
  2299.                                     {
  2300.                                         LAMN_TitleID,            MSG_TERMBUFFER_PROJECT_MEN,
  2301.                                             LAMN_ItemID,        MSG_TERMBUFFER_SEARCH_MEN,
  2302.                                                 LAMN_UserData,    MEN_SEARCH,
  2303.                                             LAMN_ItemID,        MSG_TERMBUFFER_REPEAT_SEARCH_MEN,
  2304.                                                 LAMN_UserData,    MEN_REPEAT,
  2305.  
  2306.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2307.  
  2308.                                             LAMN_ItemID,        MSG_TERMBUFFER_GO_TO_MAIN_SCREEN_MEN,
  2309.                                                 LAMN_UserData,    MEN_GOTO,
  2310.  
  2311.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2312.  
  2313.                                             LAMN_ItemID,        MSG_TERMBUFFER_CLEAR_BUFFER_MEN,
  2314.                                                 LAMN_UserData,    MEN_CLEARBUF_CONTENTS,
  2315.  
  2316.                                             LAMN_ItemText,        (ULONG)NM_BARLABEL,
  2317.  
  2318.                                             LAMN_ItemID,        MSG_TERMBUFFER_CLOSE_BUFFER_MEN,
  2319.                                                 LAMN_UserData,    MEN_QUITBUF,
  2320.  
  2321.                                         TAG_DONE
  2322.                                     };
  2323.  
  2324.                                     MenuTags = BufferTags;
  2325.                                 }
  2326.  
  2327.                                 if(BufferInfo->BufferMenuStrip = LT_NewMenuTags(
  2328.                                     LH_LocaleHook,            &LocaleHook,
  2329.                                     LAMN_Screen,            BufferInfo->Screen,
  2330.                                     LAMN_TextAttr,            &BufferInfo->LocalUserFont,
  2331.                                     LAMN_AmigaGlyph,        BufferInfo->BufferAmigaGlyph,
  2332.                                     LAMN_CheckmarkGlyph,    BufferInfo->BufferCheckGlyph,
  2333.                                 TAG_MORE,MenuTags))
  2334.                                 {
  2335.                                     UWORD *Pens = BufferInfo->BufferDrawInfo->dri_Pens;
  2336.  
  2337.                                     if(BufferInfo->BufferDrawInfo->dri_NumPens > BARDETAILPEN)
  2338.                                     {
  2339.                                         BufferInfo->TitleFrontPen    = Pens[BARDETAILPEN];
  2340.                                         BufferInfo->TitleBackPen    = Pens[BARBLOCKPEN];
  2341.                                     }
  2342.                                     else
  2343.                                     {
  2344.                                         BufferInfo->TitleFrontPen    = Pens[DETAILPEN];
  2345.                                         BufferInfo->TitleBackPen    = Pens[BLOCKPEN];
  2346.                                     }
  2347.  
  2348.                                     BufferInfo->TextFrontPen    = Pens[TEXTPEN];
  2349.                                     BufferInfo->TextBackPen        = Pens[BACKGROUNDPEN];
  2350.  
  2351.                                     BufferInfo->MaxPen = MAX(BufferInfo->TextFrontPen,BufferInfo->TextBackPen);
  2352.  
  2353.                                     Height = (BufferInfo->Screen->Height - (BufferInfo->Screen->BarHeight + 2)) / BufferInfo->LocalTextFontHeight;
  2354.  
  2355.                                     if(CreateScroller(BufferInfo,Height * BufferInfo->LocalTextFontHeight))
  2356.                                     {
  2357.                                         LONG Left,Top;
  2358.  
  2359.                                         if(Parent)
  2360.                                         {
  2361.                                             Left    = Window->LeftEdge;
  2362.                                             Top        = Window->TopEdge + Window->BorderTop;
  2363.                                             Width    = Window->Width;
  2364.                                             Height    = Window->Height - Window->BorderTop;
  2365.  
  2366.                                             GetWindowInfo(WINDOW_REVIEW,&Left,&Top,&Width,&Height,Width,Height);
  2367.                                         }
  2368.                                         else
  2369.                                         {
  2370.                                             Left    = 0;
  2371.                                             Top        = BufferInfo->Screen->BarHeight + 2;
  2372.                                             Width    = BufferInfo->Screen->Width;
  2373.                                             Height    = Height * BufferInfo->LocalTextFontHeight;
  2374.                                         }
  2375.  
  2376.                                         if(BufferInfo->Window = OpenWindowTags(NULL,
  2377.                                             WA_Left,            Left,
  2378.                                             WA_Top,                Top,
  2379.                                             WA_Width,            Width,
  2380.                                             WA_Height,            Height,
  2381.                                             WA_Backdrop,        Parent == NULL,
  2382.                                             WA_Borderless,        Parent == NULL,
  2383.                                             WA_DepthGadget,        Parent != NULL,
  2384.                                             WA_DragBar,            Parent != NULL,
  2385.                                             WA_CloseGadget,        Parent != NULL,
  2386.                                             WA_SizeGadget,        Parent != NULL,
  2387.                                             WA_NoCareRefresh,    TRUE,
  2388.                                             WA_NewLookMenus,    TRUE,
  2389.                                             WA_RptQueue,        1,
  2390.                                             WA_IDCMP,            IDCMP_IDCMPUPDATE | IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP_MENUPICK | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE | IDCMP_MENUHELP | IDCMP_SIZEVERIFY | IDCMP_NEWSIZE | IDCMP_CLOSEWINDOW,
  2391.                                             WA_MenuHelp,        TRUE,
  2392.                                             WA_Gadgets,            BufferInfo->Scroller,
  2393.                                             BackfillTag,        Parent ? &BackfillHook : NULL,
  2394.                                             WA_CustomScreen,    BufferInfo->Screen,
  2395.  
  2396. //                                            BufferInfo->Screen ? WA_CustomScreen : OpenWindowTag,    BufferInfo->Screen,
  2397.                                             BufferInfo->BufferAmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, BufferInfo->BufferAmigaGlyph,
  2398.                                             BufferInfo->BufferCheckGlyph ? WA_Checkmark : TAG_IGNORE, BufferInfo->BufferCheckGlyph,
  2399.                                         TAG_DONE))
  2400.                                         {
  2401.                                             SetMenuStrip(BufferInfo->Window,BufferInfo->BufferMenuStrip);
  2402.  
  2403.                                             BufferInfo->Left    = BufferInfo->Window->BorderLeft;
  2404.                                             BufferInfo->Top        = BufferInfo->Window->BorderTop;
  2405.                                             BufferInfo->Width    = BufferInfo->Window->Width        - (BufferInfo->Window->BorderLeft    + BufferInfo->Window->BorderRight);
  2406.                                             BufferInfo->Height    = BufferInfo->Window->Height    - (BufferInfo->Window->BorderTop    + BufferInfo->Window->BorderBottom);
  2407.  
  2408.                                             if(Parent)
  2409.                                             {
  2410.                                                 BufferInfo->Width    -= BufferInfo->Width    % BufferInfo->LocalTextFontWidth;
  2411.                                                 BufferInfo->Height    -= BufferInfo->Height    % BufferInfo->LocalTextFontHeight;
  2412.  
  2413.                                                 WindowLimits(BufferInfo->Window,BufferInfo->Window->BorderLeft + 20 * BufferInfo->LocalTextFontWidth + BufferInfo->Window->BorderRight,BufferInfo->Window->BorderTop + BufferInfo->LocalTextFontHeight + BufferInfo->Window->BorderBottom,BufferInfo->Screen->Width,BufferInfo->Screen->Height);
  2414.                                             }
  2415.                                             else
  2416.                                                 BufferInfo->Width -= BufferInfo->ArrowWidth;
  2417.  
  2418.                                             if(BufferInfo->BufferLineWidths = (UWORD *)AllocVecPooled(2 * sizeof(UWORD) * (BufferInfo->Window->WScreen->Height / BufferInfo->LocalTextFontHeight + 1) + sizeof(UWORD) * (BufferInfo->Window->WScreen->Width / BufferInfo->LocalTextFontWidth + 1),MEMF_ANY | MEMF_CLEAR))
  2419.                                             {
  2420.                                                 LONG Index;
  2421.                                                 LONG i;
  2422.  
  2423.                                                 BufferInfo->BufferLineOffsets    = &BufferInfo->BufferLineWidths[BufferInfo->Window->WScreen->Height / BufferInfo->LocalTextFontHeight + 1];
  2424.                                                 BufferInfo->BufferColumnOffsets    = &BufferInfo->BufferLineOffsets[BufferInfo->Window->WScreen->Height / BufferInfo->LocalTextFontHeight + 1];
  2425.  
  2426.                                                 for(i = Index = 0 ; i < BufferInfo->Window->WScreen->Height / BufferInfo->LocalTextFontHeight + 1 ; i++)
  2427.                                                 {
  2428.                                                     BufferInfo->BufferLineOffsets[i] = Index;
  2429.  
  2430.                                                     Index += BufferInfo->LocalTextFontHeight;
  2431.                                                 }
  2432.  
  2433.                                                 for(i = Index = 0 ; i < BufferInfo->Window->WScreen->Width / BufferInfo->LocalTextFontWidth + 1 ; i++)
  2434.                                                 {
  2435.                                                     BufferInfo->BufferColumnOffsets[i] = Index;
  2436.  
  2437.                                                     Index += BufferInfo->LocalTextFontWidth;
  2438.                                                 }
  2439.  
  2440.                                                     /* Determine maximum dimensions of
  2441.                                                      * the buffer screen (in rows and
  2442.                                                      * columns).
  2443.                                                      */
  2444.  
  2445.                                                 if(Parent)
  2446.                                                     BufferInfo->NumBufferColumns = BufferInfo->Width / BufferInfo->LocalTextFontWidth;
  2447.                                                 else
  2448.                                                     BufferInfo->NumBufferColumns = (BufferInfo->Window->Width - (BufferInfo->ArrowWidth + 1)) / BufferInfo->LocalTextFontWidth;
  2449.  
  2450.                                                 BufferInfo->NumBufferLines = BufferInfo->Height / BufferInfo->LocalTextFontHeight;
  2451.  
  2452.                                                 if(BufferInfo->TopLine == -1 || !Config->CaptureConfig->RememberBufferScreen)
  2453.                                                 {
  2454.                                                     switch(Config->CaptureConfig->OpenBufferScreen)
  2455.                                                     {
  2456.                                                         case BUFFER_TOP:
  2457.  
  2458.                                                             BufferInfo->TopLine = 0;
  2459.                                                             break;
  2460.  
  2461.                                                         case BUFFER_END:
  2462.  
  2463.                                                             if((BufferInfo->TopLine = Lines - BufferInfo->NumBufferLines) < 0)
  2464.                                                                 BufferInfo->TopLine = 0;
  2465.  
  2466.                                                             break;
  2467.  
  2468.                                                         default:
  2469.  
  2470.                                                             BufferInfo->TopLine = 0;
  2471.                                                             break;
  2472.                                                     }
  2473.                                                 }
  2474.  
  2475.                                                 if(BufferInfo->TopLine > Lines - BufferInfo->NumBufferLines || BufferInfo->TopLine < 0)
  2476.                                                     BufferInfo->TopLine = 0;
  2477.  
  2478.                                                 BufferInfo->RPort = BufferInfo->Window->RPort;
  2479.  
  2480.                                                 SetFont(BufferInfo->RPort,BufferInfo->LocalFont);
  2481.  
  2482.                                                     /* Bring the screen to the front. */
  2483.  
  2484.                                                 BumpWindow(BufferInfo->Window);
  2485.  
  2486.                                                     /* Set the drawing pens for the window. */
  2487.  
  2488.                                                 if(Kick30)
  2489.                                                     SetMaxPen(BufferInfo->RPort,BufferInfo->MaxPen);
  2490.  
  2491.                                                 SetPens(BufferInfo->RPort,BufferInfo->TextFrontPen,BufferInfo->TextBackPen,JAM2);
  2492.  
  2493.                                                     /* Initial creation of the buffer display. */
  2494.  
  2495.                                                 BufferInfo->DisplayedLines = RedrawScreen(BufferInfo,BufferInfo->TopLine);
  2496.  
  2497.                                                 SetGadgetAttrs(BufferInfo->Scroller,BufferInfo->Window,NULL,
  2498.                                                     PGA_Top,        BufferInfo->TopLine,
  2499.                                                     PGA_Total,        Lines,
  2500.                                                     PGA_Visible,    BufferInfo->NumBufferLines,
  2501.                                                 TAG_DONE);
  2502.  
  2503.                                                 if(!Parent)
  2504.                                                 {
  2505.                                                     struct RastPort *RPort = BufferInfo->Screen->BarLayer->rp;
  2506.  
  2507.                                                     BufferInfo->TitleOffset = TextLength(RPort,LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),strlen(LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT))) + TextLength(RPort,"  ",1) + 4;
  2508.                                                 }
  2509.  
  2510.                                                 return(BufferInfo);
  2511.                                             }
  2512.                                         }
  2513.                                     }
  2514.                                 }
  2515.                             }
  2516.                         }
  2517.                     }
  2518.                 }
  2519.             }
  2520.         }
  2521.     }
  2522.  
  2523.     DeleteBufferInfo(BufferInfo);
  2524.  
  2525.     return(NULL);
  2526. }
  2527.  
  2528.     /* BufferServer():
  2529.      *
  2530.      *    Asynchronous task to display the data stored in the
  2531.      *    scrollback display buffer.
  2532.      */
  2533.  
  2534. STATIC VOID __saveds
  2535. BufferServer(VOID)
  2536. {
  2537.     STATIC BOOLEAN    SearchForward    = TRUE,
  2538.                     IgnoreCase        = TRUE,
  2539.                     WholeWords        = FALSE;
  2540.     STATIC LONG        TopLine            = -1;
  2541.  
  2542.     TextBufferInfo    *BufferInfo;
  2543.     struct Task        *Father,*Me;
  2544.     BOOL             RingBack = TRUE;
  2545.  
  2546.         // Wake this guy up
  2547.  
  2548.     Me = FindTask(NULL);
  2549.  
  2550.     Father = (struct Task *)Me->tc_UserData;
  2551.  
  2552.         // Snap our fingers...
  2553.  
  2554.     if(BufferInfo = CreateBufferInfo(NULL,&SearchForward,&IgnoreCase,&WholeWords,&TopLine))
  2555.     {
  2556.             // Open wide, here I come!
  2557.  
  2558.         ObtainSemaphore(&BufferTaskSemaphore);
  2559.  
  2560.         BufferInfoData = BufferInfo;
  2561.  
  2562.         ReleaseSemaphore(&BufferTaskSemaphore);
  2563.  
  2564.             // Up and running
  2565.  
  2566.         Signal(Father,SIG_HANDSHAKE);
  2567.  
  2568.         Father = NULL;
  2569.  
  2570.             // Swish the tinsel
  2571.  
  2572.         RingBack = HandleBuffer(&BufferTaskSemaphore,&BufferInfoData);
  2573.  
  2574.             // Activate the main window again
  2575.  
  2576.         if(Window)
  2577.             BumpWindow(Window);
  2578.  
  2579.             // The wrecking crew
  2580.  
  2581.         DeleteBufferInfo(BufferInfo);
  2582.     }
  2583.  
  2584.         // Shutdown in an orderly fashion
  2585.  
  2586.     Forbid();
  2587.  
  2588.     if(RingBack)
  2589.     {
  2590.         if(Father)
  2591.             Signal(Father,SIG_HANDSHAKE);
  2592.         else
  2593.             Signal(ThisProcess,SIG_HANDSHAKE);
  2594.     }
  2595. }
  2596.  
  2597.     /* LaunchBuffer():
  2598.      *
  2599.      *    Launch the buffer process.
  2600.      */
  2601.  
  2602. BOOL
  2603. LaunchBuffer()
  2604. {
  2605.     ObtainSemaphore(&BufferTaskSemaphore);
  2606.  
  2607.         /* Is the buffer process already running? */
  2608.  
  2609.     if(BufferInfoData)
  2610.     {
  2611.             /* Tell it to bring its screen to the front. */
  2612.  
  2613.         Signal(BufferInfoData->Buddy,SIG_TOFRONT);
  2614.  
  2615.         ReleaseSemaphore(&BufferTaskSemaphore);
  2616.  
  2617.             /* Return success. */
  2618.  
  2619.         return(TRUE);
  2620.     }
  2621.     else
  2622.     {
  2623.         struct Task    *Child;
  2624.         BOOL         Result = FALSE;
  2625.  
  2626.         ReleaseSemaphore(&BufferTaskSemaphore);
  2627.  
  2628.         Forbid();
  2629.  
  2630.             /* Launch the buffer process. */
  2631.  
  2632.         if(Child = (struct Task *)CreateNewProcTags(
  2633.             NP_Entry,        BufferServer,
  2634.             NP_Name,        "term Buffer Process",
  2635.             NP_WindowPtr,    -1,
  2636.         TAG_END))
  2637.         {
  2638.             Child->tc_UserData = FindTask(NULL);
  2639.  
  2640.             ClrSignal(SIG_HANDSHAKE);
  2641.  
  2642.             Wait(SIG_HANDSHAKE);
  2643.  
  2644.             ObtainSemaphore(&BufferTaskSemaphore);
  2645.  
  2646.             if(BufferInfoData)
  2647.                 Result = TRUE;
  2648.  
  2649.             ReleaseSemaphore(&BufferTaskSemaphore);
  2650.         }
  2651.  
  2652.         Permit();
  2653.  
  2654.             /* Return the result. */
  2655.  
  2656.         return(Result);
  2657.     }
  2658. }
  2659.  
  2660.     /* TerminateBuffer():
  2661.      *
  2662.      *    Terminate the buffer process.
  2663.      */
  2664.  
  2665. VOID
  2666. TerminateBuffer()
  2667. {
  2668.     ObtainSemaphore(&BufferTaskSemaphore);
  2669.  
  2670.     if(BufferInfoData)
  2671.     {
  2672.         Forbid();
  2673.  
  2674.         Signal(BufferInfoData->Buddy,SIG_KILL);
  2675.  
  2676.         ReleaseSemaphore(&BufferTaskSemaphore);
  2677.  
  2678.         ClrSignal(SIG_HANDSHAKE);
  2679.  
  2680.         Wait(SIG_HANDSHAKE);
  2681.  
  2682.         Permit();
  2683.     }
  2684.     else
  2685.         ReleaseSemaphore(&BufferTaskSemaphore);
  2686. }
  2687.  
  2688.     /* MoveBuffer(TextBufferInfo *BufferInfo,BYTE Mode):
  2689.      *
  2690.      *    Move the currently displayed buffer area somewhere.
  2691.      */
  2692.  
  2693. VOID
  2694. MoveBuffer(struct SignalSemaphore *Access,const struct TextBufferInfo **Data,LONG Mode)
  2695. {
  2696.     struct TextBufferInfo *BufferInfo;
  2697.  
  2698.     ObtainSemaphore(Access);
  2699.  
  2700.     BufferInfo = (TextBufferInfo *)*Data;
  2701.  
  2702.     if(BufferInfo && BufferInfo->Queue)
  2703.     {
  2704.         LONG SigBit;
  2705.  
  2706.         if((SigBit = AllocSignal(-1)) != -1)
  2707.         {
  2708.             struct DataMsg Msg;
  2709.  
  2710.             InitMsgItem(&Msg,BufferDestructor);
  2711.  
  2712.             Msg.Type    = DATAMSGTYPE_MOVEREVIEW;
  2713.             Msg.Size    = Mode;
  2714.             Msg.Client    = FindTask(NULL);
  2715.             Msg.Mask    = 1L << SigBit;
  2716.  
  2717.             ClrSignal(Msg.Mask);
  2718.  
  2719.             PutMsgItem(BufferInfo->Queue,(struct MsgItem *)&Msg);
  2720.  
  2721.             ReleaseSemaphore(Access);
  2722.  
  2723.             Wait(Msg.Mask);
  2724.  
  2725.             FreeSignal(SigBit);
  2726.  
  2727.             return;
  2728.         }
  2729.     }
  2730.  
  2731.     ReleaseSemaphore(Access);
  2732. }
  2733.  
  2734.     /* NotifyBuffer(struct SignalSemaphore *Access,const struct TextBufferInfo **Data,ULONG Signals):
  2735.      *
  2736.      *    Send a signal to the buffer process.
  2737.      */
  2738.  
  2739. VOID
  2740. NotifyBuffer(struct SignalSemaphore *Access,const struct TextBufferInfo **Data,ULONG Signals)
  2741. {
  2742.     struct TextBufferInfo *BufferInfo;
  2743.  
  2744.     ObtainSemaphore(Access);
  2745.  
  2746.     BufferInfo = (TextBufferInfo *)*Data;
  2747.  
  2748.     if(BufferInfo && BufferInfo->Buddy)
  2749.     {
  2750.         Forbid();
  2751.  
  2752.         ReleaseSemaphore(Access);
  2753.  
  2754.         ClrSignal(SIG_HANDSHAKE);
  2755.  
  2756.         Signal(BufferInfo->Buddy,Signals);
  2757.  
  2758.         Wait(SIG_HANDSHAKE);
  2759.  
  2760.         Permit();
  2761.     }
  2762.     else
  2763.         ReleaseSemaphore(Access);
  2764. }
  2765.  
  2766.  
  2767. /*****************************************************************************/
  2768.  
  2769.  
  2770. STATIC VOID __saveds
  2771. ReviewServer(VOID)
  2772. {
  2773.     STATIC BOOLEAN    SearchForward    = TRUE,
  2774.                     IgnoreCase        = TRUE,
  2775.                     WholeWords        = FALSE;
  2776.     STATIC LONG        TopLine            = -1;
  2777.  
  2778.     TextBufferInfo    *BufferInfo;
  2779.     struct Task        *Father,*Me;
  2780.     BOOL             RingBack = TRUE;
  2781.  
  2782.         // Wake this guy up
  2783.  
  2784.     Me = FindTask(NULL);
  2785.  
  2786.     Father = (struct Task *)Me->tc_UserData;
  2787.  
  2788.         // Snap our fingers...
  2789.  
  2790.     if(BufferInfo = CreateBufferInfo(Window->WScreen,&SearchForward,&IgnoreCase,&WholeWords,&TopLine))
  2791.     {
  2792.             // Open wide, here I come!
  2793.  
  2794.         ObtainSemaphore(&ReviewTaskSemaphore);
  2795.  
  2796.         ReviewInfoData = BufferInfo;
  2797.  
  2798.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2799.  
  2800.             // Up and running
  2801.  
  2802.         Signal(Father,SIG_HANDSHAKE);
  2803.  
  2804.         Father = NULL;
  2805.  
  2806.             // Swish the tinsel
  2807.  
  2808.         RingBack = HandleBuffer(&ReviewTaskSemaphore,&ReviewInfoData);
  2809.  
  2810.         if(Config->CaptureConfig->RememberBufferWindow)
  2811.             PutWindowInfo(WINDOW_REVIEW,BufferInfo->Window->LeftEdge,BufferInfo->Window->TopEdge,BufferInfo->Window->Width,BufferInfo->Window->Height);
  2812.  
  2813.             // Activate the main window again
  2814.  
  2815.         if(Window)
  2816.             BumpWindow(Window);
  2817.  
  2818.             // The wrecking crew
  2819.  
  2820.         DeleteBufferInfo(BufferInfo);
  2821.  
  2822.         Forbid();
  2823.  
  2824.         CheckItem(MEN_REVIEW_WINDOW,FALSE);
  2825.  
  2826.         Permit();
  2827.     }
  2828.  
  2829.         // Shutdown in an orderly fashion
  2830.  
  2831.     Forbid();
  2832.  
  2833.     if(RingBack)
  2834.     {
  2835.         if(Father)
  2836.             Signal(Father,SIG_HANDSHAKE);
  2837.         else
  2838.             Signal(ThisProcess,SIG_HANDSHAKE);
  2839.     }
  2840. }
  2841.  
  2842. VOID
  2843. MoveReview(LONG Mode)
  2844. {
  2845.     MoveBuffer(&ReviewTaskSemaphore,&ReviewInfoData,Mode);
  2846. }
  2847.  
  2848. VOID
  2849. DeleteReview()
  2850. {
  2851.     CheckItem(MEN_REVIEW_WINDOW,FALSE);
  2852.  
  2853.     ObtainSemaphore(&ReviewTaskSemaphore);
  2854.  
  2855.     if(ReviewInfoData)
  2856.     {
  2857.         Forbid();
  2858.  
  2859.         Signal(ReviewInfoData->Buddy,SIG_KILL);
  2860.  
  2861.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2862.  
  2863.         ClrSignal(SIG_HANDSHAKE);
  2864.  
  2865.         Wait(SIG_HANDSHAKE);
  2866.  
  2867.         Permit();
  2868.     }
  2869.     else
  2870.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2871. }
  2872.  
  2873. BOOL
  2874. CreateReview()
  2875. {
  2876.     BOOL Result = FALSE;
  2877.  
  2878.     ObtainSemaphore(&ReviewTaskSemaphore);
  2879.  
  2880.         /* Is the Review process already running? */
  2881.  
  2882.     if(ReviewInfoData)
  2883.     {
  2884.             /* Tell it to bring its screen to the front. */
  2885.  
  2886.         Signal(ReviewInfoData->Buddy,SIG_TOFRONT);
  2887.  
  2888.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2889.  
  2890.             /* Return success. */
  2891.  
  2892.         Result = TRUE;
  2893.     }
  2894.     else
  2895.     {
  2896.         struct Task    *Child;
  2897.  
  2898.         ReleaseSemaphore(&ReviewTaskSemaphore);
  2899.  
  2900.         Forbid();
  2901.  
  2902.             /* Launch the Review process. */
  2903.  
  2904.         if(Child = (struct Task *)CreateNewProcTags(
  2905.             NP_Entry,        ReviewServer,
  2906.             NP_Name,        "term Review Process",
  2907.             NP_WindowPtr,    -1,
  2908.         TAG_END))
  2909.         {
  2910.             Child->tc_UserData = FindTask(NULL);
  2911.  
  2912.             ClrSignal(SIG_HANDSHAKE);
  2913.  
  2914.             Wait(SIG_HANDSHAKE);
  2915.  
  2916.             ObtainSemaphore(&ReviewTaskSemaphore);
  2917.  
  2918.             if(ReviewInfoData)
  2919.                 Result = TRUE;
  2920.  
  2921.             ReleaseSemaphore(&ReviewTaskSemaphore);
  2922.         }
  2923.  
  2924.         Permit();
  2925.     }
  2926.  
  2927.     if(Result)
  2928.         CheckItem(MEN_REVIEW_WINDOW,TRUE);
  2929.  
  2930.     return(Result);
  2931. }
  2932.