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 >
Wrap
C/C++ Source or Header
|
1991-11-01
|
39KB
|
1,622 lines
/* $Revision Header * Header built automatically - do not edit! *************
*
* (C) Copyright 1991 by Olaf 'Olsen' Barthel & MXM
*
* Name .....: TermBuffer.c
* Created ..: Monday 21-Jan-91 20:12
* Revision .: 0
*
* Date Author Comment
* ========= ======== ====================
* 21-Jan-91 Olsen Created this file!
*
* $Revision Header ********************************************************/
#include "TermGlobal.h"
/* Some private data (render info & window). */
STATIC struct Window *BufferWindow;
STATIC struct Screen *BufferScreen;
struct Gadget *BufferGadget;
STATIC struct RastPort *BPort;
STATIC APTR BufferVisualInfo;
STATIC LONG BufLine,BufCols;
STATIC BYTE MarkedArea;
STATIC BYTE BufferTerminated;
enum { MEN_SEARCH,MEN_REPEAT,MEN_GOTO,MEN_CLEARBUF,MEN_CLOSEBUF,MEN_QUITBUF };
enum { MEN_OKAY=1,MEN_CANCEL,MEN_QUITPANEL=4 };
STATIC struct NewMenu BufferMenu[] =
{
{ NM_TITLE, "Project", 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Search...", "S", 0, 0, (APTR)MEN_SEARCH},
{ NM_ITEM, "Repeat Search", "R", 0, 0, (APTR)MEN_REPEAT},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Go To Main Screen", "B", 0, 0, (APTR)MEN_GOTO},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Clear Buffer", "K", 0, 0, (APTR)MEN_CLEARBUF},
{ NM_ITEM, "Close Buffer", "C", 0, 0, (APTR)MEN_CLOSEBUF},
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, (APTR)0},
{ NM_ITEM, "Quit", "Q", 0, 0, (APTR)MEN_QUITBUF},
{ NM_END, 0, 0 , 0, 0, (APTR)0}
};
/* AllocString(UBYTE *String,WORD Len):
*
+ Allocate space for a string.
*/
STATIC UBYTE *
AllocString(UBYTE *String,WORD Len)
{
ULONG *Mem;
if(Mem = AllocMem(sizeof(ULONG) + Len,MEMF_PUBLIC))
{
*Mem++ = Len;
CopyMem(String,Mem,Len);
String = (UBYTE *)Mem;
return(String);
}
return(NULL);
}
/* FreeString(UBYTE *String):
*
* Free the space occupied by a string.
*/
STATIC VOID
FreeString(UBYTE *String)
{
FreeMem(&((ULONG *)String)[-1],((ULONG *)String)[-1] + sizeof(ULONG));
}
/* AddLine(UBYTE *Line,LONG Size):
*
* Add a line to the display buffer.
*/
VOID
AddLine(UBYTE *Line,LONG Size)
{
if(!BufferClosed)
{
ULONG Signals = 0;
/* Is the buffer array initialized? */
if(BufferLines)
{
/* Pick up the global access semaphore
* (two tasks are sharing the data).
*/
ObtainSemaphore(BufferSemaphore);
/* We've reached the last line in the buffer. */
if(Lines == MaxLines)
{
UBYTE **MoreBuffer;
LONG i;
/* Allocate space for some more lines. */
if(MoreBuffer = (UBYTE **)AllocVec((MaxLines + 100) * sizeof(UBYTE *),MEMF_PUBLIC|MEMF_CLEAR))
{
/* Copy the old lines to the new
* buffer.
*/
for(i = 0 ; i < Lines ; i++)
MoreBuffer[i] = BufferLines[i];
/* Free the old lines. */
FreeVec(BufferLines);
/* Set the new buffer. */
MaxLines += 100;
BufferLines = MoreBuffer;
}
else
{
/* We couldn't get enough memory
* to extend the number of lines
* in the buffer, so we'll have
* to wrap the contents of the
* buffer around.
*/
if(Lines)
{
BufferSpace -= ((ULONG *)BufferLines[0])[-1];
FreeString(BufferLines[0]);
for(i = 1 ; i < MaxLines ; i++)
BufferLines[i - 1] = BufferLines[i];
Lines--;
/* Tell the buffer task to
* refresh the display.
*/
Signals = SIGBREAKF_CTRL_F;
}
}
}
/* Allocate a new line and copy the buffer contents
* into it.
*/
if(BufferLines[Lines++] = AllocString(Line,Size))
BufferSpace += Size;
ReleaseSemaphore(BufferSemaphore);
/* Tell the buffer task to update the display. */
if(!Signals)
Signals = SIGBREAKF_CTRL_E;
if(BufferProcess)
Signal(BufferProcess,Signals);
}
}
}
/* ClearBuffer():
*
* Clear the current display buffer and flush the contents
* of the buffered capture file handles.
*/
VOID
ClearBuffer()
{
LONG i;
if(BufferProcess)
{
Signal(BufferProcess,SIGBREAKF_CTRL_C);
Wait(SIGBREAKF_CTRL_C);
}
if(PrinterCapture)
Flush(PrinterCapture);
/* Free the contents of the display buffer. */
if(BufferLines)
{
for(i = 0 ; i < Lines ; i++)
{
if(BufferLines[i])
FreeString(BufferLines[i]);
}
FreeVec(BufferLines);
BufferLines = NULL;
Lines = 0;
MaxLines = 100;
BufferLines = (UBYTE **)AllocVec(MaxLines * sizeof(UBYTE *),MEMF_PUBLIC|MEMF_CLEAR);
}
BufferSpace = 0;
}
/* StoreBuffer(APTR Buffer,LONG Size):
*
* Store data in the display buffer.
*/
VOID
StoreBuffer(APTR Buffer,LONG Size)
{
STATIC UBYTE LineBuffer[200];
STATIC LONG BufferCount = 0;
UBYTE *CharBuffer = Buffer;
LONG i;
for(i = 0 ; i < Size ; i++)
{
/* Look which char we are to handle. */
switch(CharBuffer[i])
{
/* Ignore the following characters. */
case FFD:
case BEL:
case DEL:
case VTB:
case XON:
case XOF: continue;
/* Move the cursor to the next tab
* stop.
*/
case TAB: if(BufferCount + 8 < LastColumn)
{
strcpy(&LineBuffer[BufferCount]," ");
BufferCount += 8;
break;
}
continue;
/* Move the cursor one step back. */
case BKS: if(BufferCount)
BufferCount--;
continue;
/* Terminate the current line. */
case ENT:
case RET: AddLine(LineBuffer,BufferCount);
BufferCount = 0;
continue;
/* Stuff the character into the buffer. */
default: LineBuffer[BufferCount++] = CharBuffer[i];
break;
}
/* The line is full, add it to the display buffer. */
if(BufferCount > LastColumn)
{
AddLine(LineBuffer,BufferCount);
BufferCount = 0;
}
}
}
/* FlushIMsg(struct Window *Window):
*
+ Clear the MsgPort of a window.
*/
STATIC VOID
FlushIMsg(struct Window *Window)
{
struct IntuiMessage *Massage;
while(Massage = GT_GetIMsg(Window -> UserPort))
GT_ReplyIMsg(Massage);
}
/* CreateAllGadgets():
*
* Create all the gadgets required by the
* buffer screen (i.e. the scroller gadget).
*/
STATIC struct Gadget *
CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList)
{
struct Gadget *Gadget;
struct NewGadget NewGadget;
memset(&NewGadget,0,sizeof(struct NewGadget));
if(Gadget = CreateContext(GadgetList))
{
NewGadget . ng_Width = 16;
NewGadget . ng_Height = BufferWindow -> Height;
NewGadget . ng_TextAttr = &DefaultFont;
NewGadget . ng_VisualInfo = BufferVisualInfo;
NewGadget . ng_GadgetID = 0;
NewGadget . ng_LeftEdge = BufferWindow -> Width - 16;
NewGadget . ng_TopEdge = 0;
GadgetArray[0] = Gadget = CreateGadget(SCROLLER_KIND,Gadget,&NewGadget,
GTSC_Arrows, (Config . DisplayMode & LACE) ? 16 : 8,
PGA_Freedom, LORIENT_VERT,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
TAG_DONE);
}
return(Gadget);
}
/* GetSearchString(UBYTE *Buffer):
*
* Prompt user for a string to search the buffer for.
*/
STATIC BYTE
GetSearchString(UBYTE *Buffer)
{
struct Gadget *GadgetList = NULL;
struct Gadget *GadgetArray[4];
struct Window *PanelWindow;
struct Menu *PanelMenu;
LONG Width;
UBYTE OtherBuffer[256];
BYTE Success = FALSE;
strcpy(OtherBuffer,Buffer);
if(CreateAllGetsGadgets(FALSE,OtherBuffer,"Enter Search String",&Width,&GadgetArray[0],&GadgetList,BufferVisualInfo,BufferScreen -> WBorTop + BufferScreen -> Font -> ta_YSize + 1,BufferScreen))
{
if(PanelMenu = CreateMenus(GetsMenu,
GTMN_FrontPen, 0,
TAG_DONE))
{
if(LayoutMenus(PanelMenu,VisualInfo,
GTMN_TextAttr,&DefaultFont,
TAG_DONE))
{
if(PanelWindow = OpenWindowTags(NULL,
WA_Width, Width,
WA_Height, 58,
WA_Left, (BufferScreen -> Width - Width) >> 1,
WA_Top, (BufferScreen -> Height - 56) >> 1,
WA_Activate, TRUE,
WA_DragBar, TRUE,
WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE,
WA_RMBTrap, TRUE,
WA_CustomScreen,BufferScreen,
WA_IDCMP, IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_MENUPICK,
WA_Title, "Enter Search String",
TAG_DONE))
{
struct IntuiMessage *Massage;
ULONG Class,Code;
struct Gadget *Gadget;
BYTE Terminated = FALSE;
ULONG SignalSet;
AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
GT_RefreshWindow(PanelWindow,NULL);
SetMenuStrip(PanelWindow,PanelMenu);
PanelWindow -> Flags &= ~WFLG_RMBTRAP;
ActiveGadget = GadgetArray[0];
ActivateGadget(GadgetArray[0],PanelWindow,NULL);
while(!Terminated)
{
SignalSet = Wait((1 << PanelWindow -> UserPort -> mp_SigBit) | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_C);
if(SignalSet & SIGBREAKF_CTRL_D)
{
BumpWindow(PanelWindow);
ActivateGadget(GadgetArray[0],PanelWindow,NULL);
}
if(SignalSet & SIGBREAKF_CTRL_C)
{
BufferTerminated = TRUE;
Terminated = TRUE;
}
if(SignalSet & (1 << PanelWindow -> UserPort -> mp_SigBit))
{
while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
{
Class = Massage -> Class;
Code = Massage -> Code;
Gadget = (struct Gadget *)Massage -> IAddress;
GT_ReplyIMsg(Massage);
if(Class == IDCMP_MENUPICK)
{
struct MenuItem *MenuItem;
while(Code != MENUNULL)
{
MenuItem = ItemAddress(PanelMenu,Code);
switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
{
case MEN_CANCEL:
case MEN_QUITPANEL: Class = IDCMP_CLOSEWINDOW;
break;
case MEN_OKAY: strcpy(Buffer,((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer);
Success = TRUE;
Terminated = TRUE;
break;
}
Code = MenuItem -> NextSelect;
}
if(ActiveGadget)
ActivateGadget(ActiveGadget,PanelWindow,NULL);
}
if(Class == IDCMP_ACTIVEWINDOW)
ActivateGadget(GadgetArray[0],PanelWindow,NULL);
if(Class == IDCMP_CLOSEWINDOW)
Terminated = TRUE;
if(Class == IDCMP_GADGETUP)
{
switch(Gadget -> GadgetID)
{
case 0:
case 1: if(((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer[0])
{
strcpy(Buffer,((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer);
Success = TRUE;
}
Terminated = TRUE;
break;
case 3: Terminated = TRUE;
break;
}
}
}
}
}
PanelWindow -> Flags |= WFLG_RMBTRAP;
ClearMenuStrip(PanelWindow);
RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
CloseWindow(PanelWindow);
}
}
FreeMenus(PanelMenu);
}
}
FreeGadgets(GadgetList);
return(Success);
}
/* PrintLine(UBYTE *Buffer,LONG LineNumber):
*
* Print a line at a given line number in the displayed area.
*/
STATIC VOID
PrintLine(UBYTE *Buffer,LONG LineNumber)
{
WORD Length = ((ULONG *)Buffer)[-1];
/* The line doesn't exactly fill the displayed line,
* so erase the remaining columns.
*/
if(Length < BufCols)
{
SetAPen(BPort,0);
RectFill(BPort,Length << 3,LineNumber << 3,(BufCols << 3) - 1,((LineNumber + 1) << 3) - 1);
SetAPen(BPort,1);
}
/* Print the text. */
if(Length)
{
Move(BPort,0,(LineNumber << 3) + 6);
if(Length > BufCols)
Text(BPort,Buffer,BufCols);
else
Text(BPort,Buffer,Length);
}
}
/* RedrawScreen(LONG FirstLine):
*
* Redraw the contents of the entire screen and return the
* number of lines actually drawn.
*/
STATIC LONG
RedrawScreen(LONG FirstLine)
{
LONG i,Last,Line = 0;
/* Determine last line to display. */
if((Last = FirstLine + BufLine) >= Lines)
Last = Lines;
/* Obtain the access semaphore and display the single
* lines.
*/
ObtainSemaphore(BufferSemaphore);
for(i = FirstLine ; i < Last ; i++)
PrintLine(BufferLines[i],Line++);
ReleaseSemaphore(BufferSemaphore);
/* We didn't fill the whole screen, so clear the rest. */
if(Line < BufLine)
{
SetAPen(BPort,0);
RectFill(BPort,0,Line << 3,BufferWindow -> Width - (1 + 16),BufferWindow -> Height - 1);
SetAPen(BPort,1);
}
return(Line);
}
/* MarkArea(WORD Column,WORD Line,WORD Length):
*
* Mark an area in the term Buffer window.
*/
STATIC VOID
MarkArea(WORD Column,WORD Line,WORD Length)
{
STATIC WORD OldColumn = -1,OldLine = -1,OldLength = -1;
if(OldColumn != Column || OldLine != Line || OldLength != Length)
{
if(OldColumn != -1)
ClipBlit(BPort,0,0,BPort,OldColumn << 3,OldLine << 3,OldLength << 3,8,0x50);
MarkedArea = TRUE;
if(Column != -1)
ClipBlit(BPort,0,0,BPort,Column << 3,Line << 3,Length << 3,8,0x50);
else
MarkedArea = FALSE;
}
OldColumn = Column;
OldLine = Line;
OldLength = Length;
}
/* Search():
*
* String search function, based on the Boyer-Moore search
* algorithm.
*/
STATIC LONG
Search(UBYTE *Pattern,LONG *FoundX,LONG *FoundY,LONG *SaveX)
{
UBYTE Distance[256],NewPattern[256],PatternWidth,SearchWidth;
LONG LineNumber = -1,i;
WORD j,k,l;
/* Determine length of search pattern. */
PatternWidth = strlen(Pattern);
/* Convert search pattern to upper cse. */
for(i = 0 ; i <= PatternWidth ; i++)
NewPattern[i] = ToUpper(Pattern[i]);
/* Create distance table. */
for(i = 0 ; i < 256 ; i++)
Distance[i] = PatternWidth;
for(i = 0 ; i < PatternWidth - 1 ; i++)
Distance[NewPattern[i]] = PatternWidth - i - 1;
/* Run down the buffer. */
for(i = *FoundY ; i < Lines ; i++)
{
/* Is there anything to search for? */
if(SearchWidth = ((ULONG *)BufferLines[i])[-1])
{
/* Casteth the magick spelle of
* Boyer-Moore...
*/
j = PatternWidth;
do
{
k = PatternWidth;
l = j;
do
{
k--;
l--;
}
while(k >= 0 && NewPattern[k] == ToUpper(BufferLines[i][l]));
j += Distance[ToUpper(BufferLines[i][j - 1])];
}
while(k >= 0 && j <= SearchWidth);
/* Found first occurence, set up the
* data and quit.
*/
if(k < 0)
{
*FoundX = l + 1;
*FoundY = LineNumber = i;
*SaveX = l + 1;
if(BufferLines[i][*FoundX + 1])
*FoundX++;
else
{
if(*FoundY - 1 < Lines)
{
*FoundX = 0;
*FoundY++;
}
}
return(LineNumber);
}
else
*FoundX = 0;
}
}
return(LineNumber);
}
/* BufferServer():
*
* Asynchronous task to display the data stored in the
* scrollback display buffer.
*/
VOID __saveds
BufferServer()
{
struct ColorSpec ColorSpec[3];
ULONG SignalSet;
struct IntuiMessage *Massage;
ULONG Class,Code,Qualifier;
UBYTE Char,LastChar = 0;
LONG CurrentLine,DisplayedLines;
UBYTE PercentBuffer[80];
struct Menu *BufferMenuStrip;
STATIC UBYTE SearchBuffer[256];
LONG LineNumber,SaveX,FoundX = 0,FoundY = 0;
ULONG DisplayMode;
struct Rectangle DisplayClip;
UWORD SomeColour;
struct Gadget *GadgetList = NULL;
struct Gadget *GadgetArray[1];
BYTE Scrolling = FALSE;
BufferTerminated = FALSE;
/* Set up the startup colours for our buffer screen. */
ColorSpec[0] . ColorIndex = 0;
ColorSpec[0] . Red = (Config . Colours[0] >> 8) & 0xF;
ColorSpec[0] . Green = (Config . Colours[0] >> 4) & 0xF;
ColorSpec[0] . Blue = (Config . Colours[0] ) & 0xF;
switch(Config . ColourMode)
{
case COLOUR_EIGHT: SomeColour = Config . Colours[7];
break;
case COLOUR_SIXTEEN: SomeColour = Config . Colours[15];
break;
case COLOUR_AMIGA:
default: SomeColour = Config . Colours[1];
break;
}
ColorSpec[1] . ColorIndex = 1;
ColorSpec[1] . Red = (SomeColour >> 8) & 0xF;
ColorSpec[1] . Green = (SomeColour >> 4) & 0xF;
ColorSpec[1] . Blue = (SomeColour ) & 0xF;
ColorSpec[2] . ColorIndex = -1;
/* We'll use a fixed screen width, only the
* height is adapted from the main screen.
*/
DisplayMode = Config . DisplayMode;
/* Inquire the text overscan dimensions. */
if(QueryOverscan(DisplayMode,&DisplayClip,OSCAN_TEXT))
{
/* Centre the buffer screen. */
if(DisplayClip . MaxX - DisplayClip . MinX + 1 > 640 + 16)
{
WORD Differ = ((DisplayClip . MaxX - DisplayClip . MinX + 1) - (640 + 16)) >> 1;
DisplayClip . MinX += Differ;
DisplayClip . MaxX -= Differ;
}
/* Open a single bitplane clone of the main screen. */
if(BufferScreen = (struct Screen *)OpenScreenTags(NULL,
SA_Title, "term Buffer",
SA_Depth, 1,
SA_DClip, &DisplayClip,
SA_DisplayID, DisplayMode,
SA_Font, &DefaultFont,
SA_Behind, TRUE,
SA_AutoScroll, TRUE,
SA_Colors, ColorSpec,
TAG_END))
{
if(BufferVisualInfo = GetVisualInfo(BufferScreen,TAG_DONE))
{
if(BufferMenuStrip = CreateMenus(BufferMenu,
GTMN_FrontPen, 0,
TAG_DONE))
{
if(LayoutMenus(BufferMenuStrip,BufferVisualInfo,
GTMN_TextAttr,&DefaultFont,
TAG_DONE))
{
/* Open a cute window on our buffer screen. */
if(BufferWindow = OpenWindowTags(NULL,
WA_Top, BufferScreen -> BarHeight + 2,
WA_Left, 0,
WA_Width, BufferScreen -> Width,
WA_Height, BufferScreen -> Height - (Screen -> BarHeight + 2),
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_SmartRefresh,FALSE,
WA_CustomScreen,BufferScreen,
WA_RMBTrap, TRUE,
WA_RptQueue, 1,
WA_IDCMP, ARROWIDCMP | SCROLLERIDCMP | IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK,
TAG_DONE))
{
if(CreateAllGadgets(&GadgetArray[0],&GadgetList))
{
/* Signal our father process that
* we're running.
*/
Signal(ThisProcess,SIGBREAKF_CTRL_C);
SetMenuStrip(BufferWindow,BufferMenuStrip);
BufferGadget = GadgetArray[0];
AddGList(BufferWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
RefreshGList(GadgetList,BufferWindow,NULL,(UWORD)-1);
GT_RefreshWindow(BufferWindow,NULL);
Restart: /* Set the IBM font if necessary. */
BPort = BufferWindow -> RPort;
if(Config . Font == FONT_IBM && IBM)
SetFont(BPort,IBM);
/* Determine maximum dimensions of
* the buffer screen (in rows and
* columns).
*/
BufCols = (BufferWindow -> Width - 16) >> 3;
BufLine = BufferWindow -> Height >> 3;
/* Bring the screen to the front. */
BumpWindow(BufferWindow);
/* Set the drawing pens for the window. */
SetAPen(BPort,1);
SetBPen(BPort,0);
SetDrMd(BPort,JAM2);
/* Initial creation of the buffer display. */
DisplayedLines = RedrawScreen(CurrentLine = 0);
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, 0,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
BufferWindow -> Flags &= ~WFLG_RMBTRAP;
while(!BufferTerminated)
{
/* Show where we are. */
if(Lines)
{
SetAPen(BufferScreen -> BarLayer -> rp,0);
SetBPen(BufferScreen -> BarLayer -> rp,1);
SetDrMd(BufferScreen -> BarLayer -> rp,JAM2);
SPrintf(PercentBuffer,"%04ld/%04ld (%3ld%%) %ld Bytes Total ",CurrentLine,Lines > BufLine ? Lines - BufLine : 0,(100 * (CurrentLine + DisplayedLines)) / Lines,BufferSpace);
Move(BufferScreen -> BarLayer -> rp,101,7);
Text(BufferScreen -> BarLayer -> rp,PercentBuffer,strlen(PercentBuffer));
}
SignalSet = Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F | (1 << BufferWindow -> UserPort -> mp_SigBit));
/* Leave the town? */
if(SignalSet & SIGBREAKF_CTRL_C)
BufferTerminated = TRUE;
/* Bring our window to the front. */
if(SignalSet & SIGBREAKF_CTRL_D)
BumpWindow(BufferWindow);
/* We've got one more line in the
* buffer.
*/
if(SignalSet & SIGBREAKF_CTRL_E)
{
if(Lines - CurrentLine > DisplayedLines && DisplayedLines < BufLine)
{
ObtainSemaphore(BufferSemaphore);
PrintLine(BufferLines[CurrentLine + DisplayedLines],DisplayedLines++);
ReleaseSemaphore(BufferSemaphore);
}
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
/* The contents of the buffer have moved
* up a line.
*/
if(SignalSet & SIGBREAKF_CTRL_F)
{
if(DisplayedLines)
ScrollRaster(BPort,0,-8,0,0,(BufCols << 3) - 1,(DisplayedLines << 3) - 1);
CurrentLine--;
ObtainSemaphore(BufferSemaphore);
PrintLine(BufferLines[CurrentLine],0);
ReleaseSemaphore(BufferSemaphore);
if(DisplayedLines < BufLine)
DisplayedLines++;
if(FoundY)
FoundY--;
}
/* Process the incoming window
* input.
*/
while(!BufferTerminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(BufferWindow -> UserPort)))
{
Class = Massage -> Class;
Code = Massage -> Code;
Qualifier = Massage -> Qualifier;
/* This hack is necessary to obtain the
* character codes generated for the cursor
* keys. A control or alternate qualifier
* would spoil the result (i.e. we would
* not get a valid key code).
*/
Massage -> Qualifier = NULL;
Char = KeyConvert(Massage,NULL);
/* Just in case anybody needs it... */
Massage -> Qualifier = Qualifier;
GT_ReplyIMsg(Massage);
if(Class == IDCMP_GADGETUP)
Scrolling = FALSE;
if(Class == IDCMP_GADGETDOWN)
Scrolling = TRUE;
if((Class == IDCMP_MOUSEMOVE && Scrolling) || Class == IDCMP_GADGETDOWN)
{
if(Code != CurrentLine)
{
if(ABS(CurrentLine - Code) == 1)
{
Qualifier = NULL;
Class = IDCMP_RAWKEY;
if(Code > CurrentLine)
Code = CDN;
else
Code = CUP;
goto UseKey;
}
else
{
if(MarkedArea)
MarkArea(-1,-1,-1);
DisplayedLines = RedrawScreen(CurrentLine = Code);
}
}
}
if(Class == IDCMP_RAWKEY)
{
if(LastChar && (Code & IECODE_UP_PREFIX))
{
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, CurrentLine,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
if(LastChar = Char)
{
/* Use the numeric keypad keys to
* move through the buffer.
*/
UseKey: if(Qualifier & IEQUALIFIER_NUMERICPAD)
{
/* Remove the numpad qualifier. */
Qualifier &= ~IEQUALIFIER_NUMERICPAD;
switch(Char - '0')
{
/* Jump to bottom. */
case 1: Char = CDN;
Qualifier |= IEQUALIFIER_CONTROL;
break;
/* Jump to top. */
case 7: Char = CUP;
Qualifier |= IEQUALIFIER_CONTROL;
break;
/* Move one page down. */
case 3: Char = CDN;
Qualifier |= IEQUALIFIER_LSHIFT;
break;
/* Move one page up. */
case 9: Char = CUP;
Qualifier |= IEQUALIFIER_LSHIFT;
break;
/* Move one line down. */
case 2: Char = CDN;
break;
/* Move one line up. */
case 8: Char = CUP;
break;
}
}
/* Check cursor keys. */
switch(Char)
{
/* Scroll the buffer up. */
case CUP: if(Qualifier & IEQUALIFIER_CONTROL)
{
if(MarkedArea)
MarkArea(-1,-1,-1);
if(CurrentLine)
{
DisplayedLines = RedrawScreen(CurrentLine = 0);
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, 0,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
break;
}
if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
LONG NewCurrentLine;
if((NewCurrentLine = CurrentLine - BufLine) < 0)
NewCurrentLine = 0;
if(MarkedArea)
MarkArea(-1,-1,-1);
if(NewCurrentLine != CurrentLine)
{
DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, CurrentLine,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
break;
}
if(CurrentLine)
{
if(MarkedArea)
MarkArea(-1,-1,-1);
if(DisplayedLines)
ScrollRaster(BPort,0,-8,0,0,(BufCols << 3) - 1,(DisplayedLines << 3) - 1);
CurrentLine--;
ObtainSemaphore(BufferSemaphore);
PrintLine(BufferLines[CurrentLine],0);
ReleaseSemaphore(BufferSemaphore);
if(DisplayedLines < BufLine)
DisplayedLines++;
}
break;
/* Scroll the buffer down. */
case CDN: if(Qualifier & IEQUALIFIER_CONTROL)
{
LONG NewCurrentLine;
if((NewCurrentLine = Lines - BufLine) < 0)
NewCurrentLine = 0;
if(MarkedArea)
MarkArea(-1,-1,-1);
if(CurrentLine != NewCurrentLine)
{
DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, CurrentLine,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
break;
}
if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
LONG NewCurrentLine;
if((NewCurrentLine = CurrentLine + (2 * BufLine)) > Lines)
NewCurrentLine = Lines;
if((NewCurrentLine = NewCurrentLine - BufLine) < 0)
NewCurrentLine = 0;
if(MarkedArea)
MarkArea(-1,-1,-1);
if(NewCurrentLine != CurrentLine)
{
DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, CurrentLine,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
break;
}
if(CurrentLine + BufLine < Lines)
{
if(MarkedArea)
MarkArea(-1,-1,-1);
if(DisplayedLines)
ScrollRaster(BPort,0,8,0,0,(BufCols << 3) - 1,(DisplayedLines << 3) - 1);
ObtainSemaphore(BufferSemaphore);
PrintLine(BufferLines[CurrentLine + BufLine],BufLine - 1);
ReleaseSemaphore(BufferSemaphore);
CurrentLine++;
if(DisplayedLines < BufLine)
DisplayedLines++;
}
break;
default: break;
}
}
continue;
}
/* User hit a mouse button. */
if(Class == IDCMP_MOUSEBUTTONS)
{
BYTE SkipLoop = FALSE;
LONG ThisLine,ThisColumn,MyColumn,LastColumn,SomeColumn;
UBYTE *TheLine;
/* Remember initial mouse position. */
ThisColumn = Massage -> MouseX >> 3;
ThisLine = Massage -> MouseY >> 3;
if(MarkedArea)
MarkArea(-1,-1,-1);
/* Reasonable dimensions? */
if(ThisLine < DisplayedLines)
{
/* Find the approriate line and its length. */
TheLine = BufferLines[CurrentLine + ThisLine];
LastColumn = ((ULONG *)BufferLines[CurrentLine + ThisLine])[-1];
/* Resonable dimensions? */
if(ThisColumn < LastColumn)
{
MyColumn = ThisColumn;
ReportMouse(TRUE,BufferWindow);
/* Loop until left mouse button is release. */
while(!SkipLoop)
{
SignalSet = Wait(SIGBREAKF_CTRL_F | (1 << BufferWindow -> UserPort -> mp_SigBit));
/* Contents of the buffer has changed! */
if(SignalSet & SIGBREAKF_CTRL_F)
{
if(FoundY)
FoundY--;
DisplayBeep(BufferScreen);
break;
}
while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
{
Class = Massage -> Class;
Code = Massage -> Code;
ReplyMsg(Massage);
/* We're finished! */
if(Class == IDCMP_MOUSEBUTTONS && Code == SELECTUP)
{
SkipLoop = TRUE;
/* Did we get a reasonable mouse
* position?
*/
if(MyColumn != ThisColumn)
{
/* Preserve right order of
* numbers.
*/
if(MyColumn < ThisColumn)
{
LONG Help;
Help = ThisColumn;
ThisColumn = MyColumn;
MyColumn = Help;
}
/* Restore the line. */
if(MyColumn < LastColumn)
LastColumn = MyColumn;
MarkArea(-1,-1,-1);
/* Clip the contents of the line to
* the clipboard.
*/
SaveClip(&TheLine[ThisColumn],MyColumn - ThisColumn);
}
break;
}
/* The mouse has moved. */
if(Class == IDCMP_MOUSEMOVE)
{
STATIC LONG OldColumn = ~0;
/* Determine new mouse position. */
SomeColumn = MyColumn;
MyColumn = Massage -> MouseX >> 3;
if((Massage -> MouseY >> 3) < ThisLine)
MyColumn = 0;
if((Massage -> MouseY >> 3) > ThisLine)
MyColumn = LastColumn;
/* Don't redraw the line if nothing
* has changed.
*/
if(OldColumn != MyColumn)
{
OldColumn = MyColumn;
/* Reasonable position? */
if(MyColumn <= LastColumn)
{
if(MyColumn >= 0)
{
/* Highlight the selected
* area (invert).
*/
if(MyColumn != ThisColumn)
{
if(MyColumn < ThisColumn)
MarkArea(MyColumn,ThisLine,ThisColumn - MyColumn);
else
MarkArea(ThisColumn,ThisLine,MyColumn - ThisColumn);
}
}
}
else
MyColumn = SomeColumn;
}
}
}
}
ReportMouse(FALSE,BufferWindow);
}
}
}
if(Class == IDCMP_MENUPICK)
{
struct MenuItem *MenuItem;
while(Code != MENUNULL)
{
MenuItem = ItemAddress(BufferMenuStrip,Code);
switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
{
case MEN_SEARCH: BufferWindow -> Flags |= WFLG_RMBTRAP;
SetWait(BufferWindow);
GetTheString: if(Lines)
{
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GA_Disabled,TRUE,
TAG_DONE);
if(GetSearchString(SearchBuffer))
{
FoundX = FoundY = 0;
SearchForIt: LineNumber = -1;
if(FoundY == 0 && CurrentLine != 0)
FoundY = CurrentLine;
ObtainSemaphore(BufferSemaphore);
LineNumber = Search(SearchBuffer,&FoundX,&FoundY,&SaveX);
ReleaseSemaphore(BufferSemaphore);
if(LineNumber == -1)
{
BlockWindows();
MyEasyRequest(BufferWindow,"Didn't find \"%s\".","Continue",SearchBuffer);
ReleaseWindows();
FlushIMsg(BufferWindow);
FoundX = FoundY = 0;
if(MarkedArea)
MarkArea(-1,-1,-1);
}
else
{
if(LineNumber < CurrentLine)
{
if(MarkedArea)
MarkArea(-1,-1,-1);
DisplayedLines = RedrawScreen(CurrentLine = 0);
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, CurrentLine,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
else
{
if(LineNumber > CurrentLine + DisplayedLines - 1)
{
if(MarkedArea)
MarkArea(-1,-1,-1);
if(LineNumber >= Lines - BufLine)
{
LONG NewCurrentLine;
if((NewCurrentLine = Lines - BufLine) < 0)
NewCurrentLine = 0;
if(CurrentLine != NewCurrentLine)
{
DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, CurrentLine,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
}
else
{
DisplayedLines = RedrawScreen(CurrentLine = LineNumber);
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GTSC_Top, CurrentLine,
GTSC_Total, Lines,
GTSC_Visible, BufLine,
TAG_DONE);
}
}
}
MarkArea(SaveX,LineNumber - CurrentLine,strlen(SearchBuffer));
}
FoundY = (FoundY + 1) % Lines;
}
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GA_Disabled,FALSE,
TAG_DONE);
}
else
MyEasyRequest(BufferWindow,"There isn't anything in the\nbuffer right now.","Continue");
BufferWindow -> Flags &= ~WFLG_RMBTRAP;
ClearPointer(BufferWindow);
break;
case MEN_REPEAT: BufferWindow -> Flags |= WFLG_RMBTRAP;
SetWait(BufferWindow);
if(!SearchBuffer[0])
goto GetTheString;
else
{
GT_SetGadgetAttrs(BufferGadget,BufferWindow,NULL,
GA_Disabled,TRUE,
TAG_DONE);
goto SearchForIt;
}
case MEN_GOTO: BumpWindow(TopWindow);
break;
case MEN_QUITBUF:
case MEN_CLOSEBUF: BufferTerminated = TRUE;
break;
case MEN_CLEARBUF: if(Lines)
{
BlockWindows();
SetWait(BufferWindow);
BufferWindow -> Flags |= WFLG_RMBTRAP;
if(MyEasyRequest(BufferWindow,"The buffer still holds %ld lines,\ndo you wish to discard them?","Yes|No",Lines))
{
ClearBuffer();
MarkedArea = FALSE;
ClearPointer(BufferWindow);
BufferWindow -> Flags &= ~WFLG_RMBTRAP;
ReleaseWindows();
FlushIMsg(BufferWindow);
goto Restart;
}
ClearPointer(BufferWindow);
BufferWindow -> Flags &= ~WFLG_RMBTRAP;
ReleaseWindows();
FlushIMsg(BufferWindow);
}
break;
default: break;
}
Code = MenuItem -> NextSelect;
}
}
}
}
RemoveGList(BufferWindow,GadgetList,(UWORD)-1);
BufferGadget = NULL;
}
FreeGadgets(GadgetList);
BumpWindow(TopWindow);
MarkArea(-1,-1,-1);
ScreenToBack(BufferScreen);
BufferWindow -> Flags |= WFLG_RMBTRAP;
ClearMenuStrip(BufferWindow);
CloseWindow(BufferWindow);
}
}
FreeMenus(BufferMenuStrip);
}
FreeVisualInfo(BufferVisualInfo);
}
CloseScreen(BufferScreen);
}
}
Forbid();
BufferProcess = NULL;
Signal(ThisProcess,SIGBREAKF_CTRL_C);
}