home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 500-599 / ff589.lza / Term / TermSrc.lha / termBuffer.c < prev    next >
C/C++ Source or Header  |  1991-11-01  |  39KB  |  1,622 lines

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