home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / comms / comprgs / t22bi2.lha / Source_Code / termSource / termBuffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-09  |  37.5 KB  |  1,611 lines

  1. /*
  2. **    $Id: termBuffer.c,v 1.7 92/05/05 18:11:37 olsen Sta Locker: olsen $
  3. **    $Revision: 1.7 $
  4. **    $Date: 92/05/05 18:11:37 $
  5. **
  6. **    Support routines for the log book (review buffer)
  7. **
  8. **    Copyright ⌐ 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* Some private data (render info & window). */
  15.  
  16. STATIC struct Window    *BufferWindow;
  17. STATIC struct Screen    *BufferScreen;
  18.  
  19. struct Gadget        *BufferGadget;
  20.  
  21. STATIC struct RastPort    *BPort;
  22. STATIC APTR         BufferVisualInfo;
  23.  
  24. STATIC LONG         BufLine,BufCols;
  25.  
  26. STATIC BYTE         MarkedArea;
  27.  
  28. STATIC BYTE         BufferTerminated;
  29.  
  30. enum    {    MEN_SEARCH,MEN_REPEAT,MEN_GOTO,MEN_CLEARBUF,MEN_CLOSEBUF,MEN_QUITBUF };
  31.  
  32. STATIC struct NewMenu BufferMenu[] =
  33. {
  34.     { NM_TITLE, NULL,         0 , 0, 0, (APTR)0},
  35.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_SEARCH},
  36.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_REPEAT},
  37.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  38.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_GOTO},
  39.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  40.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_CLEARBUF},
  41.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_CLOSEBUF},
  42.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  43.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_QUITBUF},
  44.     { NM_END, 0,             0 , 0, 0, (APTR)0}
  45. };
  46.  
  47.     /* AllocString(UBYTE *String,WORD Len):
  48.      *
  49.      +    Allocate space for a string.
  50.      */
  51.  
  52. STATIC UBYTE *
  53. AllocString(UBYTE *String,WORD Len)
  54. {
  55.     ULONG *Mem;
  56.  
  57.     if(Mem = AllocMem(sizeof(ULONG) + Len,MEMF_ANY))
  58.     {
  59.         *Mem++ = Len;
  60.  
  61.         CopyMem(String,Mem,Len);
  62.  
  63.         String = (UBYTE *)Mem;
  64.  
  65.         return(String);
  66.     }
  67.  
  68.     return(NULL);
  69. }
  70.  
  71.     /* FreeString(UBYTE *String):
  72.      *
  73.      *    Free the space occupied by a string.
  74.      */
  75.  
  76. STATIC VOID
  77. FreeString(UBYTE *String)
  78. {
  79.     FreeMem(&((ULONG *)String)[-1],((ULONG *)String)[-1] + sizeof(ULONG));
  80. }
  81.  
  82.     /* AddLine(UBYTE *Line,LONG Size):
  83.      *
  84.      *    Add a line to the display buffer.
  85.      */
  86.  
  87. VOID
  88. AddLine(UBYTE *Line,LONG Size)
  89. {
  90.     if(!BufferClosed)
  91.     {
  92.         ULONG Signals = 0;
  93.  
  94.             /* Is the buffer array initialized? */
  95.  
  96.         if(BufferLines)
  97.         {
  98.                 /* Pick up the global access semaphore
  99.                  * (two tasks are sharing the data).
  100.                  */
  101.  
  102.             ObtainSemaphore(BufferSemaphore);
  103.  
  104.                 /* Check for limit. */
  105.  
  106.             if(Config . MaxLogBuffSize && BufferSpace >= Config . MaxLogBuffSize)
  107.                 goto Wrap;
  108.  
  109.                 /* We've reached the last line in the buffer. */
  110.  
  111.             if(Lines == MaxLines)
  112.             {
  113.                 UBYTE **MoreBuffer;
  114.                 LONG i;
  115.  
  116.                     /* Allocate space for some more lines. */
  117.  
  118.                 if(MoreBuffer = (UBYTE **)AllocVec((MaxLines + 100) * sizeof(UBYTE *),MEMF_ANY|MEMF_CLEAR))
  119.                 {
  120.                         /* Copy the old lines to the new
  121.                          * buffer.
  122.                          */
  123.  
  124.                     for(i = 0 ; i < Lines ; i++)
  125.                         MoreBuffer[i] = BufferLines[i];
  126.  
  127.                         /* Free the old lines. */
  128.  
  129.                     FreeVec(BufferLines);
  130.  
  131.                         /* Set the new buffer. */
  132.  
  133.                     MaxLines += 100;
  134.  
  135.                     BufferLines = MoreBuffer;
  136.                 }
  137.                 else
  138.                 {
  139.                         /* We couldn't get enough memory
  140.                          * to extend the number of lines
  141.                          * in the buffer, so we'll have
  142.                          * to wrap the contents of the
  143.                          * buffer around.
  144.                          */
  145.  
  146.                     if(Lines)
  147.                     {
  148. Wrap:                        BufferSpace -= ((ULONG *)BufferLines[0])[-1];
  149.  
  150.                         FreeString(BufferLines[0]);
  151.  
  152.                         for(i = 1 ; i < MaxLines ; i++)
  153.                             BufferLines[i - 1] = BufferLines[i];
  154.  
  155.                         Lines--;
  156.  
  157.                             /* Tell the buffer task to
  158.                              * refresh the display.
  159.                              */
  160.  
  161.                         Signals = SIGBREAKF_CTRL_F;
  162.                     }
  163.                 }
  164.             }
  165.  
  166.                 /* Allocate a new line and copy the buffer contents
  167.                  * into it.
  168.                  */
  169.  
  170.             if(BufferLines[Lines] = AllocString(Line,Size))
  171.             {
  172.                 Lines++;
  173.  
  174.                 BufferSpace += Size;
  175.                         }
  176.  
  177.             ReleaseSemaphore(BufferSemaphore);
  178.  
  179.                 /* Tell the buffer task to update the display. */
  180.  
  181.             if(!Signals)
  182.             {
  183.                 Signals = SIGBREAKF_CTRL_E;
  184.  
  185.                 UpdateReview(FALSE);
  186.             }
  187.             else
  188.                 UpdateReview(TRUE);
  189.  
  190.             if(BufferProcess)
  191.                 Signal(BufferProcess,Signals);
  192.         }
  193.     }
  194. }
  195.  
  196.     /* ClearBuffer():
  197.      *
  198.      *    Clear the current display buffer and flush the contents
  199.      *    of the buffered capture file handles.
  200.      */
  201.  
  202. VOID
  203. ClearBuffer()
  204. {
  205.     LONG i;
  206.  
  207.     if(BufferProcess)
  208.     {
  209.         Signal(BufferProcess,SIGBREAKF_CTRL_C);
  210.  
  211.         Wait(SIGBREAKF_CTRL_C);
  212.     }
  213.  
  214.     if(PrinterCapture)
  215.         Flush(PrinterCapture);
  216.  
  217.         /* Free the contents of the display buffer. */
  218.  
  219.     if(BufferLines)
  220.     {
  221.         for(i = 0 ; i < Lines ; i++)
  222.         {
  223.             if(BufferLines[i])
  224.                 FreeString(BufferLines[i]);
  225.         }
  226.  
  227.         FreeVec(BufferLines);
  228.  
  229.         BufferLines = NULL;
  230.  
  231.         Lines = 0;
  232.  
  233.         MaxLines = 100;
  234.  
  235.         BufferLines = (UBYTE **)AllocVec(MaxLines * sizeof(UBYTE *),MEMF_ANY|MEMF_CLEAR);
  236.     }
  237.  
  238.     BufferSpace = 0;
  239. }
  240.  
  241.     /* StoreBuffer(APTR Buffer,LONG Size):
  242.      *
  243.      *    Store data in the display buffer.
  244.      */
  245.  
  246. VOID
  247. StoreBuffer(APTR Buffer,LONG Size)
  248. {
  249.     STATIC UBYTE     LineBuffer[200];
  250.     STATIC LONG      BufferCount = 0;
  251.  
  252.     UBYTE        *CharBuffer = Buffer;
  253.     LONG         i;
  254.  
  255.     for(i = 0 ; i < Size ; i++)
  256.     {
  257.             /* Look which char we are to handle. */
  258.  
  259.         switch(CharBuffer[i])
  260.         {
  261.                 /* Ignore the following characters. */
  262.  
  263.             case FFD:
  264.             case BEL:
  265.             case DEL:
  266.             case VTB:
  267.             case XON:
  268.             case XOF:    continue;
  269.  
  270.                 /* Move the cursor to the next tab
  271.                  * stop.
  272.                  */
  273.  
  274.             case TAB:    if(BufferCount + 8 < LastColumn)
  275.                     {
  276.                         strcpy(&LineBuffer[BufferCount],"        ");
  277.  
  278.                         BufferCount += 8;
  279.  
  280.                         break;
  281.                     }
  282.  
  283.                     continue;
  284.  
  285.                 /* Move the cursor one step back. */
  286.  
  287.             case BKS:    if(BufferCount)
  288.                         BufferCount--;
  289.  
  290.                     continue;
  291.  
  292.                 /* Ignore carriage return (should have been
  293.                  * filtered already).
  294.                  */
  295.  
  296.             case RET:    continue;
  297.  
  298.                 /* Terminate the current line. */
  299.  
  300.             case ENT:    AddLine(LineBuffer,BufferCount);
  301.  
  302.                     BufferCount = 0;
  303.                     continue;
  304.  
  305.                 /* Stuff the character into the buffer. */
  306.  
  307.             default:    LineBuffer[BufferCount++] = CharBuffer[i];
  308.                     break;
  309.         }
  310.  
  311.             /* The line is full, add it to the display buffer. */
  312.  
  313.         if(BufferCount > LastColumn || BufferCount == sizeof(LineBuffer))
  314.         {
  315.             AddLine(LineBuffer,BufferCount);
  316.  
  317.             BufferCount = 0;
  318.         }
  319.     }
  320. }
  321.  
  322.     /* FlushIMsg(struct Window *Window):
  323.      *
  324.      +    Clear the MsgPort of a window.
  325.      */
  326.  
  327. STATIC VOID
  328. FlushIMsg(struct Window *Window)
  329. {
  330.     struct IntuiMessage *Massage;
  331.  
  332.     while(Massage = GT_GetIMsg(Window -> UserPort))
  333.         GT_ReplyIMsg(Massage);
  334. }
  335.  
  336.     /* CreateAllGadgets():
  337.      *
  338.      *    Create all the gadgets required by the
  339.      *    buffer screen (i.e. the scroller gadget).
  340.      */
  341.  
  342. STATIC struct Gadget *
  343. CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList)
  344. {
  345.     struct Gadget        *Gadget;
  346.     struct NewGadget     NewGadget;
  347.  
  348.     memset(&NewGadget,0,sizeof(struct NewGadget));
  349.  
  350.     if(Gadget = CreateContext(GadgetList))
  351.     {
  352.         NewGadget . ng_Width        = 16;
  353.         NewGadget . ng_Height        = BufferWindow -> Height;
  354.         NewGadget . ng_TextAttr        = &DefaultFont;
  355.         NewGadget . ng_VisualInfo    = BufferVisualInfo;
  356.         NewGadget . ng_GadgetID        = 0;
  357.         NewGadget . ng_LeftEdge        = BufferWindow -> Width - 16;
  358.         NewGadget . ng_TopEdge        = 0;
  359.  
  360.         GadgetArray[0] = Gadget = CreateGadget(SCROLLER_KIND,Gadget,&NewGadget,
  361.             GTSC_Arrows,    (Config . DisplayMode & LACE) ? 16 : 8,
  362.             PGA_Freedom,    LORIENT_VERT,
  363.             GA_Immediate,    TRUE,
  364.             GA_RelVerify,    TRUE,
  365.         TAG_DONE);
  366.     }
  367.  
  368.     return(Gadget);
  369. }
  370.  
  371.     /* GetSearchString(UBYTE *Buffer):
  372.      *
  373.      *    Prompt user for a string to search the buffer for.
  374.      */
  375.  
  376. STATIC BYTE
  377. GetSearchString(UBYTE *Buffer)
  378. {
  379.     struct Gadget    *GadgetList = NULL;
  380.     struct Gadget    *GadgetArray[4];
  381.     struct Window    *PanelWindow;
  382.     LONG         Width;
  383.     UBYTE         OtherBuffer[256];
  384.     BYTE         Success = FALSE;
  385.  
  386.     strcpy(OtherBuffer,Buffer);
  387.  
  388.     if(CreateAllGetsGadgets(FALSE,OtherBuffer,LocaleString(MSG_TERMBUFFER_ENTER_SEARCH_STRING_TXT),&Width,&GadgetArray[0],&GadgetList,BufferVisualInfo,BufferScreen -> WBorTop + BufferScreen -> Font -> ta_YSize + 1,BufferScreen))
  389.     {
  390.         if(PanelWindow = OpenWindowTags(NULL,
  391.             WA_Width,    Width,
  392.             WA_Height,    58,
  393.  
  394.             WA_Left,    (BufferScreen -> Width - Width) >> 1,
  395.             WA_Top,        (BufferScreen -> Height - 56) >> 1,
  396.  
  397.             WA_Activate,    TRUE,
  398.             WA_DragBar,    TRUE,
  399.             WA_DepthGadget,    TRUE,
  400.             WA_CloseGadget,    TRUE,
  401.             WA_RMBTrap,    TRUE,
  402.             WA_CustomScreen,BufferScreen,
  403.  
  404.             WA_IDCMP,    IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_GADGETDOWN | BUTTONIDCMP | STRINGIDCMP,
  405.  
  406.             WA_Title,    LocaleString(MSG_TERMBUFFER_ENTER_SEARCH_STRING_TXT),
  407.         TAG_DONE))
  408.         {
  409.             struct IntuiMessage    *Massage;
  410.             ULONG             Class,Code;
  411.             struct Gadget        *Gadget;
  412.             BYTE             Terminated = FALSE;
  413.             ULONG             SignalSet;
  414.  
  415.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  416.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  417.             GT_RefreshWindow(PanelWindow,NULL);
  418.  
  419.             ActiveGadget = NULL;
  420.  
  421.             while(!Terminated)
  422.             {
  423.                 SignalSet = Wait((1 << PanelWindow -> UserPort -> mp_SigBit) | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_C);
  424.  
  425.                 if(SignalSet & SIGBREAKF_CTRL_D)
  426.                     BumpWindow(PanelWindow);
  427.  
  428.                 if(SignalSet & SIGBREAKF_CTRL_C)
  429.                 {
  430.                     BufferTerminated = TRUE;
  431.  
  432.                     Terminated = TRUE;
  433.                 }
  434.  
  435.                 if(SignalSet & (1 << PanelWindow -> UserPort -> mp_SigBit))
  436.                 {
  437.                     while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  438.                     {
  439.                         Class    = Massage -> Class;
  440.                         Code    = Massage -> Code;
  441.                         Gadget    = (struct Gadget *)Massage -> IAddress;
  442.  
  443.                         GT_ReplyIMsg(Massage);
  444.  
  445.                         if(Class == IDCMP_VANILLAKEY)
  446.                             KeySelect(GadgetArray,3,Code,PanelWindow,&Gadget,&Class,&Code);
  447.  
  448.                         if(Class == IDCMP_GADGETDOWN)
  449.                         {
  450.                             if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  451.                                 ActiveGadget = Gadget;
  452.                         }
  453.  
  454.                         if(Class == IDCMP_ACTIVEWINDOW && ActiveGadget)
  455.                             ActivateGadget(ActiveGadget,PanelWindow,NULL);
  456.  
  457.                         if(Class == IDCMP_CLOSEWINDOW)
  458.                             Terminated = TRUE;
  459.  
  460.                         if(Class == IDCMP_GADGETUP)
  461.                         {
  462.                             switch(Gadget -> GadgetID)
  463.                             {
  464.                                 case 0: if(Code != '\t' && ((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer[0])
  465.                                     {
  466.                                         strcpy(Buffer,GT_STRING(GadgetArray[0]));
  467.  
  468.                                         Success = TRUE;
  469.  
  470.                                         Terminated = TRUE;
  471.                                     }
  472.  
  473.                                     break;
  474.  
  475.                                 case 1:    if(((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer[0])
  476.                                     {
  477.                                         strcpy(Buffer,GT_STRING(GadgetArray[0]));
  478.  
  479.                                         Success = TRUE;
  480.  
  481.                                         Terminated = TRUE;
  482.                                     }
  483.  
  484.                                     break;
  485.  
  486.                                 case 3:    Terminated = TRUE;
  487.                                     break;
  488.                             }
  489.                         }
  490.                     }
  491.                 }
  492.             }
  493.  
  494.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  495.  
  496.             CloseWindow(PanelWindow);
  497.         }
  498.     }
  499.  
  500.     FreeGadgets(GadgetList);
  501.  
  502.     return(Success);
  503. }
  504.  
  505.     /* PrintLine(UBYTE *Buffer,LONG LineNumber):
  506.      *
  507.      *    Print a line at a given line number in the displayed area.
  508.      */
  509.  
  510. STATIC VOID
  511. PrintLine(UBYTE *Buffer,LONG LineNumber)
  512. {
  513.     WORD Length = ((ULONG *)Buffer)[-1];
  514.  
  515.         /* The line doesn't exactly fill the displayed line,
  516.          * so erase the remaining columns.
  517.          */
  518.  
  519.     if(Length < BufCols)
  520.     {
  521.         SetAPen(BPort,0);
  522.  
  523.         RectFill(BPort,Length << 3,LineNumber << 3,(BufCols << 3) - 1,((LineNumber + 1) << 3) - 1);
  524.  
  525.         SetAPen(BPort,1);
  526.     }
  527.  
  528.         /* Print the text. */
  529.  
  530.     if(Length)
  531.     {
  532.         Move(BPort,0,(LineNumber << 3) + 6);
  533.  
  534.         if(Length > BufCols)
  535.             Text(BPort,Buffer,BufCols);
  536.         else
  537.             Text(BPort,Buffer,Length);
  538.     }
  539. }
  540.  
  541.     /* RedrawScreen(LONG FirstLine):
  542.      *
  543.      *    Redraw the contents of the entire screen and return the
  544.      *    number of lines actually drawn.
  545.      */
  546.  
  547. STATIC LONG
  548. RedrawScreen(LONG FirstLine)
  549. {
  550.     LONG i,Last,Line = 0;
  551.  
  552.         /* Determine last line to display. */
  553.  
  554.     if((Last = FirstLine + BufLine) >= Lines)
  555.         Last = Lines;
  556.  
  557.         /* Obtain the access semaphore and display the single
  558.          * lines.
  559.          */
  560.  
  561.     ObtainSemaphore(BufferSemaphore);
  562.  
  563.     for(i = FirstLine ; i < Last ; i++)
  564.         PrintLine(BufferLines[i],Line++);
  565.  
  566.     ReleaseSemaphore(BufferSemaphore);
  567.  
  568.         /* We didn't fill the whole screen, so clear the rest. */
  569.  
  570.     if(Line < BufLine)
  571.     {
  572.         SetAPen(BPort,0);
  573.  
  574.         RectFill(BPort,0,Line << 3,BufferWindow -> Width - (1 + 16),BufferWindow -> Height - 1);
  575.  
  576.         SetAPen(BPort,1);
  577.     }
  578.  
  579.     return(Line);
  580. }
  581.  
  582.     /* MarkArea(WORD Column,WORD Line,WORD Length):
  583.      *
  584.      *    Mark an area in the term Buffer window.
  585.      */
  586.  
  587. STATIC VOID
  588. MarkArea(WORD Column,WORD Line,WORD Length)
  589. {
  590.     STATIC WORD OldColumn = -1,OldLine = -1,OldLength = -1;
  591.  
  592.     if(OldColumn != Column || OldLine != Line || OldLength != Length)
  593.     {
  594.         if(OldColumn != -1)
  595.             ClipBlit(BPort,0,0,BPort,OldColumn << 3,OldLine << 3,OldLength << 3,8,0x50);
  596.  
  597.         MarkedArea = TRUE;
  598.  
  599.         if(Column != -1)
  600.             ClipBlit(BPort,0,0,BPort,Column << 3,Line << 3,Length << 3,8,0x50);
  601.         else
  602.             MarkedArea = FALSE;
  603.     }
  604.  
  605.     OldColumn    = Column;
  606.     OldLine        = Line;
  607.     OldLength    = Length;
  608. }
  609.  
  610.     /* Search():
  611.      *
  612.      *    String search function, based on the Boyer-Moore search
  613.      *    algorithm.
  614.      */
  615.  
  616. STATIC LONG
  617. Search(UBYTE *Pattern,LONG *FoundX,LONG *FoundY,LONG *SaveX)
  618. {
  619.     UBYTE    Distance[256],NewPattern[256],PatternWidth,SearchWidth;
  620.     LONG    LineNumber = -1,i;
  621.     WORD    j,k,l;
  622.  
  623.         /* Determine length of search pattern. */
  624.  
  625.     PatternWidth = strlen(Pattern);
  626.  
  627.         /* Convert search pattern to upper cse. */
  628.  
  629.     for(i = 0 ; i <= PatternWidth ; i++)
  630.         NewPattern[i] = ToUpper(Pattern[i]);
  631.  
  632.         /* Create distance table. */
  633.  
  634.     for(i = 0 ; i < 256 ; i++)
  635.         Distance[i] = PatternWidth;
  636.  
  637.     for(i = 0 ; i < PatternWidth - 1 ; i++)
  638.         Distance[NewPattern[i]] = PatternWidth - i - 1;
  639.  
  640.         /* Run down the buffer. */
  641.  
  642.     for(i = *FoundY ; i < Lines ; i++)
  643.     {
  644.             /* Is there anything to search for? */
  645.  
  646.         if(SearchWidth = ((ULONG *)BufferLines[i])[-1])
  647.         {
  648.                 /* Casteth the magick spelle of
  649.                  * Boyer-Moore...
  650.                  */
  651.  
  652.             j = PatternWidth;
  653.  
  654.             do
  655.             {
  656.                 k = PatternWidth;
  657.                 l = j;
  658.  
  659.                 do
  660.                 {
  661.                     k--;
  662.                     l--;
  663.                 }
  664.                 while(k >= 0 && NewPattern[k] == ToUpper(BufferLines[i][l]));
  665.  
  666.                 j += Distance[ToUpper(BufferLines[i][j - 1])];
  667.             }
  668.             while(k >= 0 && j <= SearchWidth);
  669.  
  670.                 /* Found first occurence, set up the
  671.                  * data and quit.
  672.                  */
  673.  
  674.             if(k < 0)
  675.             {
  676.                 *FoundX    = l + 1;
  677.                 *FoundY    = LineNumber = i;
  678.  
  679.                 *SaveX    = l + 1;
  680.  
  681.                 if(BufferLines[i][*FoundX + 1])
  682.                     *FoundX++;
  683.                 else
  684.                 {
  685.                     if(*FoundY - 1 < Lines)
  686.                     {
  687.                         *FoundX = 0;
  688.                         *FoundY++;
  689.                     }
  690.                 }
  691.  
  692.                 return(LineNumber);
  693.             }
  694.             else
  695.                 *FoundX = 0;
  696.         }
  697.     }
  698.  
  699.     return(LineNumber);
  700. }
  701.  
  702.     /* BufferServer():
  703.      *
  704.      *    Asynchronous task to display the data stored in the
  705.      *    scrollback display buffer.
  706.      */
  707.  
  708. VOID __saveds
  709. BufferServer()
  710. {
  711.     struct ColorSpec     ColorSpec[3];
  712.  
  713.     ULONG             SignalSet;
  714.  
  715.     struct IntuiMessage    *Massage;
  716.     ULONG             Class,Code,Qualifier;
  717.     UBYTE             Char,LastChar = 0;
  718.  
  719.     LONG             CurrentLine,DisplayedLines;
  720.  
  721.     UBYTE             PercentBuffer[80];
  722.  
  723.     struct Menu        *BufferMenuStrip;
  724.  
  725.     STATIC UBYTE         SearchBuffer[256];
  726.     LONG             LineNumber,SaveX,FoundX = 0,FoundY = 0;
  727.     ULONG             DisplayMode;
  728.  
  729.     struct Rectangle     DisplayClip;
  730.  
  731.     UWORD             SomeColour;
  732.  
  733.     struct Gadget        *GadgetList = NULL;
  734.     struct Gadget        *GadgetArray[1];
  735.  
  736.     BYTE             Scrolling = FALSE;
  737.  
  738.     BufferTerminated = FALSE;
  739.  
  740.         /* Set up the startup colours for our buffer screen. */
  741.  
  742.     ColorSpec[0] . ColorIndex    = 0;
  743.     ColorSpec[0] . Red        = (Config . Colours[0] >> 8) & 0xF;
  744.     ColorSpec[0] . Green        = (Config . Colours[0] >> 4) & 0xF;
  745.     ColorSpec[0] . Blue        = (Config . Colours[0]     ) & 0xF;
  746.  
  747.     switch(Config . ColourMode)
  748.     {
  749.         case COLOUR_EIGHT:    SomeColour = Config . Colours[7];
  750.                     break;
  751.  
  752.         case COLOUR_SIXTEEN:    SomeColour = Config . Colours[15];
  753.                     break;
  754.  
  755.         case COLOUR_AMIGA:
  756.         default:        SomeColour = Config . Colours[1];
  757.                     break;
  758.     }
  759.  
  760.     ColorSpec[1] . ColorIndex    = 1;
  761.     ColorSpec[1] . Red        = (SomeColour >> 8) & 0xF;
  762.     ColorSpec[1] . Green        = (SomeColour >> 4) & 0xF;
  763.     ColorSpec[1] . Blue        = (SomeColour     ) & 0xF;
  764.  
  765.     ColorSpec[2] . ColorIndex    = -1;
  766.  
  767.         /* We'll use a fixed screen width, only the
  768.          * height is adapted from the main screen.
  769.          */
  770.  
  771.     DisplayMode = Config . DisplayMode;
  772.  
  773.         /* Inquire the text overscan dimensions. */
  774.  
  775.     if(QueryOverscan(DisplayMode,&DisplayClip,OSCAN_TEXT))
  776.     {
  777.             /* Centre the buffer screen. */
  778.  
  779.         if(DisplayClip . MaxX - DisplayClip . MinX + 1 > 640 + 16)
  780.         {
  781.             WORD Differ = ((DisplayClip . MaxX - DisplayClip . MinX + 1) - (640 + 16)) >> 1;
  782.  
  783.             DisplayClip . MinX += Differ;
  784.             DisplayClip . MaxX -= Differ;
  785.         }
  786.  
  787.             /* Open a single bitplane clone of the main screen. */
  788.  
  789.         if(BufferScreen = (struct Screen *)OpenScreenTags(NULL,
  790.             SA_Title,    LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),
  791.             SA_Depth,    1,
  792.             SA_DClip,    &DisplayClip,
  793.             SA_DisplayID,    DisplayMode,
  794.             SA_Font,    &DefaultFont,
  795.             SA_Behind,    TRUE,
  796.             SA_AutoScroll,    TRUE,
  797.             SA_Colors,    ColorSpec,
  798.         TAG_END))
  799.         {
  800.             if(BufferVisualInfo = GetVisualInfo(BufferScreen,TAG_DONE))
  801.             {
  802.                 LocalizeMenu(BufferMenu,MSG_TERMBUFFER_PROJECT_MEN);
  803.  
  804.                 if(BufferMenuStrip = CreateMenus(BufferMenu,
  805.                     GTMN_FrontPen, 0,
  806.                 TAG_DONE))
  807.                 {
  808.                     if(LayoutMenus(BufferMenuStrip,BufferVisualInfo,
  809.                         GTMN_TextAttr,&DefaultFont,
  810.                     TAG_DONE))
  811.                     {
  812.                         WORD TitleOffset;
  813.  
  814.                         TitleOffset = (strlen(LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT)) + 1) * 8 + 4;
  815.  
  816.                             /* Open a cute window on our buffer screen. */
  817.  
  818.                         if(BufferWindow = OpenWindowTags(NULL,
  819.                             WA_Top,        BufferScreen -> BarHeight + 2,
  820.                             WA_Left,    0,
  821.                             WA_Width,    BufferScreen -> Width,
  822.                             WA_Height,    BufferScreen -> Height - (Screen -> BarHeight + 2),
  823.                             WA_Backdrop,    TRUE,
  824.                             WA_Borderless,    TRUE,
  825.                             WA_SmartRefresh,FALSE,
  826.                             WA_CustomScreen,BufferScreen,
  827.                             WA_RMBTrap,    TRUE,
  828.                             WA_RptQueue,    1,
  829.                             WA_IDCMP,    IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK | IDCMP_INACTIVEWINDOW | ARROWIDCMP | SLIDERIDCMP,
  830.                         TAG_DONE))
  831.                         {
  832.                             if(CreateAllGadgets(&GadgetArray[0],&GadgetList))
  833.                             {
  834.                                     /* Signal our father process that
  835.                                      * we're running.
  836.                                      */
  837.  
  838.                                 Signal(ThisProcess,SIGBREAKF_CTRL_C);
  839.  
  840.                                 SetMenuStrip(BufferWindow,BufferMenuStrip);
  841.  
  842.                                 BufferGadget = GadgetArray[0];
  843.  
  844.                                 AddGList(BufferWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  845.                                 RefreshGList(GadgetList,BufferWindow,NULL,(UWORD)-1);
  846.                                 GT_RefreshWindow(BufferWindow,NULL);
  847.  
  848. Restart:                                /* Set the IBM font if necessary. */
  849.  
  850.                                 BPort = BufferWindow -> RPort;
  851.  
  852.                                 if(Config . Font == FONT_IBM && IBM)
  853.                                     SetFont(BPort,IBM);
  854.  
  855.                                     /* Determine maximum dimensions of
  856.                                      * the buffer screen (in rows and
  857.                                      * columns).
  858.                                      */
  859.  
  860.                                 BufCols    = (BufferWindow -> Width - 16) >> 3;
  861.                                 BufLine    = BufferWindow -> Height >> 3;
  862.  
  863.                                     /* Bring the screen to the front. */
  864.  
  865.                                 BumpWindow(BufferWindow);
  866.  
  867.                                     /* Set the drawing pens for the window. */
  868.  
  869.                                 SetAPen(BPort,1);
  870.                                 SetBPen(BPort,0);
  871.                                 SetDrMd(BPort,JAM2);
  872.  
  873.                                     /* Initial creation of the buffer display. */
  874.  
  875.                                 DisplayedLines = RedrawScreen(CurrentLine = 0);
  876.  
  877.                                 GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  878.                                     GTSC_Top,    0,
  879.                                     GTSC_Total,    Lines,
  880.                                     GTSC_Visible,    BufLine,
  881.                                 TAG_DONE);
  882.  
  883.                                 BufferWindow -> Flags &= ~WFLG_RMBTRAP;
  884.  
  885.                                 while(!BufferTerminated)
  886.                                 {
  887.                                         /* Show where we are. */
  888.  
  889.                                     if(Lines)
  890.                                     {
  891.                                         extern APTR LocaleBase;
  892.  
  893.                                         SetAPen(BufferScreen -> BarLayer -> rp,0);
  894.                                         SetBPen(BufferScreen -> BarLayer -> rp,1);
  895.                                         SetDrMd(BufferScreen -> BarLayer -> rp,JAM2);
  896.  
  897.                                         if(LocaleBase)
  898.                                             SPrintf(PercentBuffer,"%lD/%lD (%ld%%)                  ",CurrentLine,Lines > BufLine ? Lines - BufLine : 0,(100 * (CurrentLine + DisplayedLines)) / Lines);
  899.                                         else
  900.                                             SPrintf(PercentBuffer,"%ld/%ld (%ld%%)                  ",CurrentLine,Lines > BufLine ? Lines - BufLine : 0,(100 * (CurrentLine + DisplayedLines)) / Lines);
  901.  
  902.                                         Move(BufferScreen -> BarLayer -> rp,TitleOffset,7);
  903.                                         Text(BufferScreen -> BarLayer -> rp,PercentBuffer,strlen(PercentBuffer));
  904.                                     }
  905.  
  906.                                     SignalSet = Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F | (1 << BufferWindow -> UserPort -> mp_SigBit));
  907.  
  908.                                         /* Leave the town? */
  909.  
  910.                                     if(SignalSet & SIGBREAKF_CTRL_C)
  911.                                         BufferTerminated = TRUE;
  912.  
  913.                                         /* Bring our window to the front. */
  914.  
  915.                                     if(SignalSet & SIGBREAKF_CTRL_D)
  916.                                         BumpWindow(BufferWindow);
  917.  
  918.                                         /* We've got one more line in the
  919.                                          * buffer.
  920.                                          */
  921.  
  922.                                     if(SignalSet & SIGBREAKF_CTRL_E)
  923.                                     {
  924.                                         if(Lines - CurrentLine > DisplayedLines && DisplayedLines < BufLine)
  925.                                         {
  926.                                             ObtainSemaphore(BufferSemaphore);
  927.  
  928.                                             PrintLine(BufferLines[CurrentLine + DisplayedLines],DisplayedLines++);
  929.  
  930.                                             ReleaseSemaphore(BufferSemaphore);
  931.                                         }
  932.  
  933.                                         GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  934.                                             GTSC_Total,    Lines,
  935.                                             GTSC_Visible,    BufLine,
  936.                                         TAG_DONE);
  937.                                     }
  938.  
  939.                                         /* The contents of the buffer have moved
  940.                                          * up a line.
  941.                                          */
  942.  
  943.                                     if(SignalSet & SIGBREAKF_CTRL_F)
  944.                                         DisplayedLines = RedrawScreen(CurrentLine);
  945.  
  946.                                         /* Process the incoming window
  947.                                          * input.
  948.                                          */
  949.  
  950.                                     while(!BufferTerminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(BufferWindow -> UserPort)))
  951.                                     {
  952.                                         Class        = Massage -> Class;
  953.                                         Code        = Massage -> Code;
  954.                                         Qualifier    = Massage -> Qualifier;
  955.  
  956.                                             /* This hack is necessary to obtain the
  957.                                              * character codes generated for the cursor
  958.                                              * keys. A control or alternate qualifier
  959.                                              * would spoil the result (i.e. we would
  960.                                              * not get a valid key code).
  961.                                              */
  962.  
  963.                                         Massage -> Qualifier = NULL;
  964.  
  965.                                         Char = KeyConvert(Massage,NULL,NULL);
  966.  
  967.                                             /* Just in case anybody needs it... */
  968.  
  969.                                         Massage -> Qualifier = Qualifier;
  970.  
  971.                                         GT_ReplyIMsg(Massage);
  972.  
  973.                                         if(Class == IDCMP_GADGETUP)
  974.                                             Scrolling = FALSE;
  975.  
  976.                                         if(Class == IDCMP_GADGETDOWN)
  977.                                             Scrolling = TRUE;
  978.  
  979.                                         if((Class == IDCMP_MOUSEMOVE && Scrolling) || Class == IDCMP_GADGETDOWN)
  980.                                         {
  981.                                             if(Code != CurrentLine)
  982.                                             {
  983.                                                 if(ABS(CurrentLine - Code) == 1)
  984.                                                 {
  985.                                                     Qualifier    = NULL;
  986.                                                     Class        = IDCMP_RAWKEY;
  987.  
  988.                                                     if(Code > CurrentLine)
  989.                                                         Code = CDN;
  990.                                                     else
  991.                                                         Code = CUP;
  992.  
  993.                                                     goto UseKey;
  994.                                                 }
  995.                                                 else
  996.                                                 {
  997.                                                     if(MarkedArea)
  998.                                                         MarkArea(-1,-1,-1);
  999.                                             
  1000.                                                     DisplayedLines = RedrawScreen(CurrentLine = Code);
  1001.                                                 }
  1002.                                             }
  1003.                                         }
  1004.  
  1005.                                         if(Class == IDCMP_RAWKEY)
  1006.                                         {
  1007.                                             if(LastChar && (Code & IECODE_UP_PREFIX))
  1008.                                             {
  1009.                                                 GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  1010.                                                     GTSC_Top,    CurrentLine,
  1011.                                                     GTSC_Total,    Lines,
  1012.                                                     GTSC_Visible,    BufLine,
  1013.                                                 TAG_DONE);
  1014.                                             }
  1015.  
  1016.                                             if(LastChar = Char)
  1017.                                             {
  1018.                                                     /* Use the numeric keypad keys to
  1019.                                                      * move through the buffer.
  1020.                                                      */
  1021.  
  1022. UseKey:                                                if(Qualifier & IEQUALIFIER_NUMERICPAD)
  1023.                                                 {
  1024.                                                         /* Remove the numpad qualifier. */
  1025.  
  1026.                                                     Qualifier &= ~IEQUALIFIER_NUMERICPAD;
  1027.  
  1028.                                                     switch(Char - '0')
  1029.                                                     {
  1030.                                                             /* Jump to bottom. */
  1031.  
  1032.                                                         case 1: Char = CDN;
  1033.                                                             Qualifier |= IEQUALIFIER_CONTROL;
  1034.                                                             break;
  1035.  
  1036.                                                             /* Jump to top. */
  1037.  
  1038.                                                         case 7: Char = CUP;
  1039.                                                             Qualifier |= IEQUALIFIER_CONTROL;
  1040.                                                             break;
  1041.  
  1042.                                                             /* Move one page down. */
  1043.  
  1044.                                                         case 3: Char = CDN;
  1045.                                                             Qualifier |= IEQUALIFIER_LSHIFT;
  1046.                                                             break;
  1047.  
  1048.                                                             /* Move one page up. */
  1049.  
  1050.                                                         case 9: Char = CUP;
  1051.                                                             Qualifier |= IEQUALIFIER_LSHIFT;
  1052.                                                             break;
  1053.  
  1054.                                                             /* Move one line down. */
  1055.  
  1056.                                                         case 2: Char = CDN;
  1057.                                                             break;
  1058.  
  1059.                                                             /* Move one line up. */
  1060.  
  1061.                                                         case 8: Char = CUP;
  1062.                                                             break;
  1063.                                                     }
  1064.                                                 }
  1065.  
  1066.                                                     /* Check cursor keys. */
  1067.  
  1068.                                                 switch(Char)
  1069.                                                 {
  1070.                                                         /* Scroll the buffer up. */
  1071.  
  1072.                                                     case CUP:    if(Qualifier & IEQUALIFIER_CONTROL)
  1073.                                                             {
  1074.                                                                 if(MarkedArea)
  1075.                                                                     MarkArea(-1,-1,-1);
  1076.  
  1077.                                                                 if(CurrentLine)
  1078.                                                                 {
  1079.                                                                     DisplayedLines = RedrawScreen(CurrentLine = 0);
  1080.  
  1081.                                                                     GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  1082.                                                                         GTSC_Top,    0,
  1083.                                                                         GTSC_Total,    Lines,
  1084.                                                                         GTSC_Visible,    BufLine,
  1085.                                                                     TAG_DONE);
  1086.                                                                 }
  1087.  
  1088.                                                                 break;
  1089.                                                             }
  1090.  
  1091.                                                             if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1092.                                                             {
  1093.                                                                 LONG NewCurrentLine;
  1094.  
  1095.                                                                 if((NewCurrentLine = CurrentLine - BufLine) < 0)
  1096.                                                                     NewCurrentLine = 0;
  1097.  
  1098.                                                                 if(MarkedArea)
  1099.                                                                     MarkArea(-1,-1,-1);
  1100.  
  1101.                                                                 if(NewCurrentLine != CurrentLine)
  1102.                                                                 {
  1103.                                                                     DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
  1104.  
  1105.                                                                     GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  1106.                                                                         GTSC_Top,    CurrentLine,
  1107.                                                                         GTSC_Total,    Lines,
  1108.                                                                         GTSC_Visible,    BufLine,
  1109.                                                                     TAG_DONE);
  1110.                                                                 }
  1111.  
  1112.                                                                 break;
  1113.                                                             }
  1114.  
  1115.                                                             if(CurrentLine)
  1116.                                                             {
  1117.                                                                 if(MarkedArea)
  1118.                                                                     MarkArea(-1,-1,-1);
  1119.  
  1120.                                                                 if(DisplayedLines)
  1121.                                                                     ScrollRaster(BPort,0,-8,0,0,(BufCols << 3) - 1,(DisplayedLines << 3) - 1);
  1122.  
  1123.                                                                 CurrentLine--;
  1124.  
  1125.                                                                 ObtainSemaphore(BufferSemaphore);
  1126.  
  1127.                                                                 PrintLine(BufferLines[CurrentLine],0);
  1128.  
  1129.                                                                 ReleaseSemaphore(BufferSemaphore);
  1130.  
  1131.                                                                 if(DisplayedLines < BufLine)
  1132.                                                                     DisplayedLines++;
  1133.                                                             }
  1134.  
  1135.                                                             break;
  1136.  
  1137.                                                         /* Scroll the buffer down. */
  1138.     
  1139.                                                     case CDN:    if(Qualifier & IEQUALIFIER_CONTROL)
  1140.                                                             {
  1141.                                                                 LONG NewCurrentLine;
  1142.  
  1143.                                                                 if((NewCurrentLine = Lines - BufLine) < 0)
  1144.                                                                     NewCurrentLine = 0;
  1145.  
  1146.                                                                 if(MarkedArea)
  1147.                                                                     MarkArea(-1,-1,-1);
  1148.  
  1149.                                                                 if(CurrentLine != NewCurrentLine)
  1150.                                                                 {
  1151.                                                                     DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
  1152.  
  1153.                                                                     GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  1154.                                                                         GTSC_Top,    CurrentLine,
  1155.                                                                         GTSC_Total,    Lines,
  1156.                                                                         GTSC_Visible,    BufLine,
  1157.                                                                     TAG_DONE);
  1158.                                                                 }
  1159.  
  1160.                                                                 break;
  1161.                                                             }
  1162.  
  1163.                                                             if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1164.                                                             {
  1165.                                                                 LONG NewCurrentLine;
  1166.  
  1167.                                                                 if((NewCurrentLine = CurrentLine + (2 * BufLine)) > Lines)
  1168.                                                                     NewCurrentLine = Lines;
  1169.  
  1170.                                                                 if((NewCurrentLine = NewCurrentLine - BufLine) < 0)
  1171.                                                                     NewCurrentLine = 0;
  1172.  
  1173.                                                                 if(MarkedArea)
  1174.                                                                     MarkArea(-1,-1,-1);
  1175.  
  1176.                                                                 if(NewCurrentLine != CurrentLine)
  1177.                                                                 {
  1178.                                                                     DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
  1179.  
  1180.                                                                     GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  1181.                                                                         GTSC_Top,    CurrentLine,
  1182.                                                                         GTSC_Total,    Lines,
  1183.                                                                         GTSC_Visible,    BufLine,
  1184.                                                                     TAG_DONE);
  1185.                                                                 }
  1186.  
  1187.                                                                 break;
  1188.                                                             }
  1189.  
  1190.                                                             if(CurrentLine + BufLine < Lines)
  1191.                                                             {
  1192.                                                                 if(MarkedArea)
  1193.                                                                     MarkArea(-1,-1,-1);
  1194.  
  1195.                                                                 if(DisplayedLines)
  1196.                                                                     ScrollRaster(BPort,0,8,0,0,(BufCols << 3) - 1,(DisplayedLines << 3) - 1);
  1197.  
  1198.                                                                 ObtainSemaphore(BufferSemaphore);
  1199.  
  1200.                                                                 PrintLine(BufferLines[CurrentLine + BufLine],BufLine - 1);
  1201.  
  1202.                                                                 ReleaseSemaphore(BufferSemaphore);
  1203.  
  1204.                                                                 CurrentLine++;
  1205.  
  1206.                                                                 if(DisplayedLines < BufLine)
  1207.                                                                     DisplayedLines++;
  1208.                                                             }
  1209.  
  1210.                                                             break;
  1211.  
  1212.                                                     default:    break;
  1213.                                                 }
  1214.                                             }
  1215.  
  1216.                                             continue;
  1217.                                         }
  1218.  
  1219.                                             /* User hit a mouse button. */
  1220.  
  1221.                                         if(Class == IDCMP_MOUSEBUTTONS && !(Code & IECODE_UP_PREFIX))
  1222.                                         {
  1223.                                             BYTE SkipLoop = FALSE;
  1224.                                             LONG ThisLine,ThisColumn,MyColumn,LastColumn,SomeColumn;
  1225.                                             UBYTE *TheLine;
  1226.  
  1227.                                                 /* Remember initial mouse position. */
  1228.  
  1229.                                             ThisColumn    = Massage -> MouseX >> 3;
  1230.                                             ThisLine    = Massage -> MouseY >> 3;
  1231.  
  1232.                                             if(MarkedArea)
  1233.                                                 MarkArea(-1,-1,-1);
  1234.  
  1235.                                                 /* Reasonable dimensions? */
  1236.  
  1237.                                             if(ThisLine < DisplayedLines)
  1238.                                             {
  1239.                                                     /* Find the approriate line and its length. */
  1240.  
  1241.                                                 TheLine        = BufferLines[CurrentLine + ThisLine];
  1242.                                                 LastColumn    = ((ULONG *)BufferLines[CurrentLine + ThisLine])[-1];
  1243.  
  1244.                                                     /* Resonable dimensions? */
  1245.  
  1246.                                                 if(ThisColumn < LastColumn)
  1247.                                                 {
  1248.                                                     MyColumn = ThisColumn;
  1249.  
  1250.                                                     ReportMouse(TRUE,BufferWindow);
  1251.  
  1252.                                                         /* Loop until left mouse button is release. */
  1253.  
  1254.                                                     while(!SkipLoop)
  1255.                                                     {
  1256.                                                         SignalSet = Wait(SIGBREAKF_CTRL_F | (1 << BufferWindow -> UserPort -> mp_SigBit));
  1257.  
  1258.                                                             /* Contents of the buffer has changed! */
  1259.  
  1260.                                                         if(SignalSet & SIGBREAKF_CTRL_F)
  1261.                                                         {
  1262.                                                             if(FoundY)
  1263.                                                                 FoundY--;
  1264.  
  1265.                                                             DisplayBeep(BufferScreen);
  1266.                                                             break;
  1267.                                                         }
  1268.  
  1269.                                                         while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
  1270.                                                         {
  1271.                                                             Class    = Massage -> Class;
  1272.                                                             Code    = Massage -> Code;
  1273.  
  1274.                                                             ReplyMsg(Massage);
  1275.  
  1276.                                                                 /* Mouse left inner space. */
  1277.  
  1278.                                                             if(Class == IDCMP_INACTIVEWINDOW)
  1279.                                                             {
  1280.                                                                 SkipLoop = TRUE;
  1281.  
  1282.                                                                 MarkArea(-1,-1,-1);
  1283.  
  1284.                                                                 break;
  1285.                                                             }
  1286.  
  1287.                                                                 /* We're finished! */
  1288.  
  1289.                                                             if(Class == IDCMP_MOUSEBUTTONS && (Code == SELECTUP || Code == MIDDLEUP))
  1290.                                                             {
  1291.                                                                 SkipLoop = TRUE;
  1292.  
  1293.                                                                     /* Did we get a reasonable mouse
  1294.                                                                      * position?
  1295.                                                                      */
  1296.  
  1297.                                                                 if(MyColumn != ThisColumn)
  1298.                                                                 {
  1299.                                                                         /* Preserve right order of
  1300.                                                                          * numbers.
  1301.                                                                          */
  1302.  
  1303.                                                                     if(MyColumn < ThisColumn)
  1304.                                                                     {
  1305.                                                                         LONG Help;
  1306.  
  1307.                                                                         Help        = ThisColumn;
  1308.                                                                         ThisColumn    = MyColumn;
  1309.                                                                         MyColumn    = Help;
  1310.                                                                     }
  1311.  
  1312.                                                                         /* Restore the line. */
  1313.  
  1314.                                                                     if(MyColumn < LastColumn)
  1315.                                                                         LastColumn = MyColumn;
  1316.  
  1317.                                                                     MarkArea(-1,-1,-1);
  1318.  
  1319.                                                                         /* Clip the contents of the line to
  1320.                                                                          * the clipboard.
  1321.                                                                          */
  1322.  
  1323.                                                                     SaveClip(&TheLine[ThisColumn],MyColumn - ThisColumn);
  1324.  
  1325.                                                                         /* Clipping on the buffer screen is to work
  1326.                                                                          * similar to clipping on the main screen,
  1327.                                                                          * i.e. feed the line into the input
  1328.                                                                          * stream if a shift key is held down.
  1329.                                                                          */
  1330.  
  1331.                                                                     if((Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) || Code == MIDDLEUP)
  1332.                                                                         Signal(ThisProcess,SIG_CLIP);
  1333.                                                                 }
  1334.  
  1335.                                                                 break;
  1336.                                                             }
  1337.  
  1338.                                                                 /* The mouse has moved. */
  1339.  
  1340.                                                             if(Class == IDCMP_MOUSEMOVE)
  1341.                                                             {
  1342.                                                                 STATIC LONG OldColumn = ~0;
  1343.  
  1344.                                                                     /* Determine new mouse position. */
  1345.  
  1346.                                                                 SomeColumn = MyColumn;
  1347.  
  1348.                                                                 MyColumn = Massage -> MouseX >> 3;
  1349.  
  1350.                                                                 if((Massage -> MouseY >> 3) < ThisLine)
  1351.                                                                     MyColumn = 0;
  1352.  
  1353.                                                                 if((Massage -> MouseY >> 3) > ThisLine)
  1354.                                                                     MyColumn = LastColumn;
  1355.  
  1356.                                                                     /* Don't redraw the line if nothing
  1357.                                                                      * has changed.
  1358.                                                                      */
  1359.  
  1360.                                                                 if(OldColumn != MyColumn)
  1361.                                                                 {
  1362.                                                                     OldColumn = MyColumn;
  1363.  
  1364.                                                                         /* Reasonable position? */
  1365.  
  1366.                                                                     if(MyColumn <= LastColumn)
  1367.                                                                     {
  1368.                                                                         if(MyColumn >= 0)
  1369.                                                                         {
  1370.                                                                                 /* Highlight the selected
  1371.                                                                                  * area (invert).
  1372.                                                                                  */
  1373.  
  1374.                                                                             if(MyColumn != ThisColumn)
  1375.                                                                             {
  1376.                                                                                 if(MyColumn < ThisColumn)
  1377.                                                                                     MarkArea(MyColumn,ThisLine,ThisColumn - MyColumn);
  1378.                                                                                 else
  1379.                                                                                     MarkArea(ThisColumn,ThisLine,MyColumn - ThisColumn);
  1380.                                                                             }
  1381.                                                                         }
  1382.                                                                     }
  1383.                                                                     else
  1384.                                                                         MyColumn = SomeColumn;
  1385.                                                                 }
  1386.                                                             }
  1387.                                                         }
  1388.                                                     }
  1389.  
  1390.                                                     ReportMouse(FALSE,BufferWindow);
  1391.                                                 }
  1392.                                             }
  1393.                                         }
  1394.  
  1395.                                         if(Class == IDCMP_MENUPICK)
  1396.                                         {
  1397.                                             struct MenuItem *MenuItem;
  1398.  
  1399.                                             while(Code != MENUNULL)
  1400.                                             {
  1401.                                                 MenuItem = ItemAddress(BufferMenuStrip,Code);
  1402.  
  1403.                                                 switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
  1404.                                                 {
  1405.                                                     case MEN_SEARCH:    BlockWindow(BufferWindow);
  1406.  
  1407. GetTheString:                                                            if(Lines)
  1408.                                                                 {
  1409.                                                                     if(GetSearchString(SearchBuffer))
  1410.                                                                     {
  1411.                                                                         FoundX = FoundY = 0;
  1412.  
  1413. SearchForIt:                                                                    LineNumber = -1;
  1414.  
  1415.                                                                         if(FoundY == 0 && CurrentLine != 0)
  1416.                                                                             FoundY = CurrentLine;
  1417.  
  1418.                                                                         ObtainSemaphore(BufferSemaphore);
  1419.  
  1420.                                                                         LineNumber = Search(SearchBuffer,&FoundX,&FoundY,&SaveX);
  1421.  
  1422.                                                                         ReleaseSemaphore(BufferSemaphore);
  1423.  
  1424.                                                                         if(LineNumber == -1)
  1425.                                                                         {
  1426.                                                                             BlockWindows();
  1427.  
  1428.                                                                             MyEasyRequest(BufferWindow,LocaleString(MSG_TERMBUFFER_DID_NOT_FIND_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SearchBuffer);
  1429.  
  1430.                                                                             ReleaseWindows();
  1431.  
  1432.                                                                             FlushIMsg(BufferWindow);
  1433.  
  1434.                                                                             FoundX = FoundY = 0;
  1435.  
  1436.                                                                             if(MarkedArea)
  1437.                                                                                 MarkArea(-1,-1,-1);
  1438.                                                                         }
  1439.                                                                         else
  1440.                                                                         {
  1441.                                                                             if(LineNumber < CurrentLine)
  1442.                                                                             {
  1443.                                                                                 if(MarkedArea)
  1444.                                                                                     MarkArea(-1,-1,-1);
  1445.  
  1446.                                                                                 DisplayedLines = RedrawScreen(CurrentLine = 0);
  1447.  
  1448.                                                                                 GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  1449.                                                                                     GTSC_Top,    CurrentLine,
  1450.                                                                                     GTSC_Total,    Lines,
  1451.                                                                                     GTSC_Visible,    BufLine,
  1452.                                                                                 TAG_DONE);
  1453.                                                                             }
  1454.                                                                             else
  1455.                                                                             {
  1456.                                                                                 if(LineNumber > CurrentLine + DisplayedLines - 1)
  1457.                                                                                 {
  1458.                                                                                     if(MarkedArea)
  1459.                                                                                         MarkArea(-1,-1,-1);
  1460.     
  1461.                                                                                     if(LineNumber >= Lines - BufLine)
  1462.                                                                                     {
  1463.                                                                                         LONG NewCurrentLine;
  1464.  
  1465.                                                                                         if((NewCurrentLine = Lines - BufLine) < 0)
  1466.                                                                                             NewCurrentLine = 0;
  1467.  
  1468.                                                                                         if(CurrentLine != NewCurrentLine)
  1469.                                                                                         {
  1470.                                                                                             DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
  1471.  
  1472.                                                                                             GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  1473.                                                                                                 GTSC_Top,    CurrentLine,
  1474.                                                                                                 GTSC_Total,    Lines,
  1475.                                                                                                 GTSC_Visible,    BufLine,
  1476.                                                                                             TAG_DONE);
  1477.                                                                                         }
  1478.                                                                                     }
  1479.                                                                                     else
  1480.                                                                                     {
  1481.                                                                                         DisplayedLines = RedrawScreen(CurrentLine = LineNumber);
  1482.  
  1483.                                                                                         GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
  1484.                                                                                             GTSC_Top,    CurrentLine,
  1485.                                                                                             GTSC_Total,    Lines,
  1486.                                                                                             GTSC_Visible,    BufLine,
  1487.                                                                                         TAG_DONE);
  1488.                                                                                     }
  1489.                                                                                 }
  1490.                                                                             }
  1491.  
  1492.                                                                             MarkArea(SaveX,LineNumber - CurrentLine,strlen(SearchBuffer));
  1493.                                                                         }
  1494.  
  1495.                                                                         FoundY = (FoundY + 1) % Lines;
  1496.                                                                     }
  1497.                                                                 }
  1498.                                                                 else
  1499.                                                                     MyEasyRequest(BufferWindow,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  1500.  
  1501.                                                                 ReleaseWindow(BufferWindow);
  1502.                                                                 break;
  1503.  
  1504.                                                     case MEN_REPEAT:    BlockWindow(BufferWindow);
  1505.  
  1506.                                                                 if(!SearchBuffer[0])
  1507.                                                                     goto GetTheString;
  1508.                                                                 else
  1509.                                                                     goto SearchForIt;
  1510.  
  1511.                                                     case MEN_GOTO:        BumpWindow(TopWindow);
  1512.                                                                 break;
  1513.  
  1514.                                                     case MEN_QUITBUF:
  1515.                                                     case MEN_CLOSEBUF:    BufferTerminated = TRUE;
  1516.                                                                 break;
  1517.  
  1518.                                                     case MEN_CLEARBUF:    if(Lines)
  1519.                                                                 {
  1520.                                                                     BlockWindows();
  1521.  
  1522.                                                                     BlockWindow(BufferWindow);
  1523.  
  1524.                                                                     if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1525.                                                                     {
  1526.                                                                         ClearBuffer();
  1527.  
  1528.                                                                         MarkedArea = FALSE;
  1529.  
  1530.                                                                         ReleaseWindow(BufferWindow);
  1531.  
  1532.                                                                         ReleaseWindows();
  1533.  
  1534.                                                                         FlushIMsg(BufferWindow);
  1535.  
  1536.                                                                         goto Restart;
  1537.                                                                     }
  1538.                                                                     else
  1539.                                                                     {
  1540.                                                                         if(MyEasyRequest(BufferWindow,LocaleString(MSG_TERMBUFFER_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines))
  1541.                                                                         {
  1542.                                                                             ClearBuffer();
  1543.  
  1544.                                                                             MarkedArea = FALSE;
  1545.  
  1546.                                                                             ReleaseWindow(BufferWindow);
  1547.  
  1548.                                                                             ReleaseWindows();
  1549.  
  1550.                                                                             FlushIMsg(BufferWindow);
  1551.  
  1552.                                                                             goto Restart;
  1553.                                                                         }
  1554.                                                                     }
  1555.  
  1556.                                                                     ReleaseWindow(BufferWindow);
  1557.  
  1558.                                                                     ReleaseWindows();
  1559.  
  1560.                                                                     FlushIMsg(BufferWindow);
  1561.                                                                 }
  1562.  
  1563.                                                                 break;
  1564.  
  1565.                                                     default:        break;
  1566.                                                 }
  1567.  
  1568.                                                 Code = MenuItem -> NextSelect;
  1569.                                             }
  1570.                                         }
  1571.                                     }
  1572.                                 }
  1573.  
  1574.                                 RemoveGList(BufferWindow,GadgetList,(UWORD)-1);
  1575.  
  1576.                                 BufferGadget = NULL;
  1577.                             }
  1578.  
  1579.                             FreeGadgets(GadgetList);
  1580.  
  1581.                             BumpWindow(TopWindow);
  1582.  
  1583.                             MarkArea(-1,-1,-1);
  1584.  
  1585.                             ScreenToBack(BufferScreen);
  1586.  
  1587.                             BufferWindow -> Flags |= WFLG_RMBTRAP;
  1588.  
  1589.                             ClearMenuStrip(BufferWindow);
  1590.  
  1591.                             CloseWindow(BufferWindow);
  1592.                         }
  1593.                     }
  1594.  
  1595.                     FreeMenus(BufferMenuStrip);
  1596.                 }
  1597.  
  1598.                 FreeVisualInfo(BufferVisualInfo);
  1599.             }
  1600.  
  1601.             CloseScreen(BufferScreen);
  1602.         }
  1603.     }
  1604.  
  1605.     Forbid();
  1606.  
  1607.     BufferProcess = NULL;
  1608.  
  1609.     Signal(ThisProcess,SIGBREAKF_CTRL_C);
  1610. }
  1611.