home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d8xx
/
d832
/
term.lha
/
Term
/
term-3.1-Source.lha
/
termMarker.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-12
|
15KB
|
687 lines
/*
** termMarker.c
**
** Text block marker routines
**
** Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#include "termGlobal.h"
/* BM_Draw():
*
* Redraw or remove marked regions.
*/
VOID
BM_Draw(struct BlockMarker *Marker,VOID (*Select)(struct BlockMarker *Marker,LONG Left,LONG Top,LONG Width,LONG Height))
{
/* Is the first line the same as the last line? If so,
* continue and mark only single characters. Else,
* determine first line and column to mark and last
* line and last column.
*/
if(Marker -> FirstLine != Marker -> LastLine)
{
LONG First = Marker -> FirstLine - Marker -> Top,
Last = Marker -> LastLine - Marker -> Top,
Lines;
/* Is the first line visible? If so, mark it. */
if(First >= 0)
(*Select)(Marker,Marker -> FirstColumn,First,Marker -> Width - Marker -> FirstColumn,1);
else
{
(*Select)(Marker,0,0,Marker -> Width,1);
First = 0;
}
/* Is the last line visible? If so, mark it. */
if(Last >= 0 && Last < Marker -> Height)
(*Select)(Marker,0,Last,Marker -> LastColumn,1);
else
Last = Marker -> Height;
/* Determine the number of lines the selection spans. */
if((Lines = Last - First - 1) > 0)
(*Select)(Marker,0,First + 1,Marker -> Width,Lines);
}
else
{
/* Is the first column different from the last column? */
if(Marker -> FirstColumn != Marker -> LastColumn)
{
/* Is the line visible? If so, mark it. */
if(Marker -> Top <= Marker -> LastLine && Marker -> LastLine < Marker -> Top + Marker -> Height)
(*Select)(Marker,Marker -> FirstColumn,Marker -> FirstLine - Marker -> Top,Marker -> LastColumn - Marker -> FirstColumn,1);
}
}
}
/* BM_ClearMark(struct BlockMarker *Marker):
*
* Free block marker memory.
*/
VOID
BM_ClearMark(struct BlockMarker *Marker)
{
BM_Draw(Marker,Marker -> Unselect);
FreeVec(Marker);
}
/* BM_SetMark():
*
* Create block marker structure.
*/
struct BlockMarker *
BM_SetMark(APTR Object,VPTR Select,VPTR Unselect,LONG Width,LONG Height,LONG LeftEdge,LONG TopEdge,LONG Top,LONG Lines,LONG X,LONG Y,WORD TextFontWidth,WORD TextFontHeight)
{
if(Height && Lines)
{
struct BlockMarker *Marker;
/* Allocate marker buffer. */
if(Marker = (struct BlockMarker *)AllocVec(sizeof(struct BlockMarker),MEMF_ANY | MEMF_CLEAR))
{
/* Fill in the object or canvas, usually a RastPort. */
Marker -> Object = Object;
/* Fill in the canvas left and top edge. */
Marker -> LeftEdge = LeftEdge;
Marker -> TopEdge = TopEdge;
/* Fill in the select and unselect routines. */
Marker -> Select = Select;
Marker -> Unselect = Unselect;
/* Fill in current display window top and number of
* lines in the buffer.
*/
Marker -> Top = Top;
Marker -> Lines = Lines;
/* Fill in width and height of the display window. */
Marker -> Width = Width;
Marker -> Height = Height;
/* Fill in the marker anchor point. */
Marker -> FirstColumn = X;
Marker -> LastColumn = X;
Marker -> FirstLine = Y + Top;
Marker -> LastLine = Y + Top;
/* Fill in current mouse position. */
Marker -> LastX = X;
Marker -> LastY = Y;
Marker -> OriginX = X;
Marker -> OriginY = Y + Top;
/* Remember text font dimensions. */
Marker -> TextFontWidth = TextFontWidth;
Marker -> TextFontHeight= TextFontHeight;
Marker -> WriteMask = ((struct RastPort *)Object) -> Mask;
}
/* Return marker buffer. */
return(Marker);
}
else
return(NULL);
}
/* BM_ExtendMark(struct BlockMarker *Marker,LONG X,LONG Y,LONG Delta):
*
* Extend current block marker. This routine was
* first written by me, but Martin Berndt rewrote it
* after we both realised that it would not work
* properly.
*/
VOID
BM_ExtendMark(struct BlockMarker *Marker,LONG X,LONG Y,LONG Delta)
{
if(Marker -> LastX != X || Marker -> LastY != Y)
{
LONG OldCharPos,NewCharPos,
CharStart,CharEnd,
CharOrigin,
OriginY,
Lines;
BYTE Crossed;
OriginY = Marker -> OriginY - Marker -> Top;
/* Deal with illegal X position. */
if(X < 0)
X = 0;
if(X > Marker -> Width)
X = Marker -> Width;
/* Deal with illegal Y position. */
if(Y < 0)
Y = 0;
if(Y >= Marker -> Height)
Y = Marker -> Height - 1;
if(Y + Marker -> Top >= Marker -> Lines)
Y = Marker -> Lines - Marker -> Top - 1;
/* Is the Y position larger than the last line? If so,
* truncate it.
*/
if(Y > Marker -> Lines - Marker -> Top)
Y -= Marker -> Lines - Marker -> Top;
/* Select the text. */
OldCharPos = (Marker -> LastY + Marker -> Top) * Marker -> Width + Marker -> LastX;
NewCharPos = (Y + Marker -> Top) * Marker -> Width + X;
CharStart = Marker -> FirstLine * Marker -> Width + Marker -> FirstColumn;
CharEnd = Marker -> LastLine * Marker -> Width + Marker -> LastColumn;
CharOrigin = Marker -> OriginY * Marker -> Width + Marker -> OriginX;
Crossed = (OldCharPos < CharOrigin) ^ (NewCharPos < CharOrigin);
if(NewCharPos > OldCharPos)
{
if(Delta && Y < OriginY)
(*Marker -> Select)(Marker,0,Y,Marker -> Width,1);
if(Crossed)
{
if((Lines = OriginY - Marker -> LastY - 1) >= 0)
{
(*Marker -> Unselect)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
if(Lines > 0)
(*Marker -> Unselect)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
if(Marker -> OriginX)
(*Marker -> Unselect)(Marker,0,OriginY,Marker -> OriginX,1);
}
else
{
if(Delta)
(*Marker -> Unselect)(Marker,0,OriginY,Marker -> LastX,1);
else
(*Marker -> Unselect)(Marker,Marker -> LastX,OriginY,Marker -> OriginX - Marker -> LastX,1);
}
Marker -> FirstColumn = Marker -> OriginX;
Marker -> FirstLine = Marker -> OriginY;
Marker -> LastX = Marker -> OriginX;
Marker -> LastY = OriginY;
}
else
{
if(OldCharPos < CharOrigin)
{
if((Lines = Y - Marker -> LastY - 1) >= 0)
{
(*Marker -> Unselect)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
if(Lines > 0)
(*Marker -> Unselect)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
(*Marker -> Unselect)(Marker,0,Y,X,1);
}
else
{
if(Delta)
(*Marker -> Unselect)(Marker,0,Y,X,1);
else
(*Marker -> Unselect)(Marker,Marker -> LastX,Y,X - Marker -> LastX,1);
}
Marker -> FirstColumn = X;
Marker -> FirstLine = Y + Marker -> Top;
}
}
if(NewCharPos > CharEnd)
{
if((Lines = Y - Marker -> LastY - 1) >= 0)
{
(*Marker -> Select)(Marker,Marker -> LastX,Marker -> LastY,Marker -> Width - Marker -> LastX,1);
if(Lines > 0)
(*Marker -> Select)(Marker,0,Marker -> LastY + 1,Marker -> Width,Lines);
(*Marker -> Select)(Marker,0,Y,X,1);
}
else
{
if(Delta)
(*Marker -> Select)(Marker,0,Y,X,1);
else
(*Marker -> Select)(Marker,Marker -> LastX,Y,X - Marker -> LastX,1);
}
Marker -> LastColumn = X;
Marker -> LastLine = Y + Marker -> Top;
}
}
else
{
if(Delta && Y > OriginY)
(*Marker -> Select)(Marker,0,Y,Marker -> Width,1);
if(Crossed)
{
if((Lines = Marker -> LastY - OriginY - 1) >= 0)
{
(*Marker -> Unselect)(Marker,0,Marker -> LastY,Marker -> LastX,1);
if(Lines > 0)
(*Marker -> Unselect)(Marker,0,OriginY + 1,Marker -> Width,Lines);
(*Marker -> Unselect)(Marker,Marker -> OriginX,OriginY,Marker -> Width - Marker -> OriginX,1);
}
else
{
if(Delta)
(*Marker -> Unselect)(Marker,Marker -> LastX,OriginY,Marker -> Width - Marker -> LastX,1);
else
(*Marker -> Unselect)(Marker,Marker -> OriginX,OriginY,Marker -> LastX - Marker -> OriginX,1);
}
Marker -> LastColumn = Marker -> OriginX;
Marker -> LastLine = Marker -> OriginY;
Marker -> LastX = Marker -> OriginX;
Marker -> LastY = OriginY;
}
else
{
if(OldCharPos > CharOrigin)
{
if((Lines = Marker -> LastY - Y - 1) >= 0)
{
if(Marker -> LastX)
(*Marker -> Unselect)(Marker,0,Marker -> LastY,Marker -> LastX,1);
if(Lines > 0)
(*Marker -> Unselect)(Marker,0,Y + 1,Marker -> Width,Lines);
(*Marker -> Unselect)(Marker,X,Y,Marker -> Width - X,1);
}
else
{
if(Delta)
(*Marker -> Unselect)(Marker,X,Y,Marker -> Width - X,1);
else
(*Marker -> Unselect)(Marker,X,Y,Marker -> LastX - X,1);
}
Marker -> LastColumn = X;
Marker -> LastLine = Y + Marker -> Top;
}
}
if(NewCharPos < CharStart)
{
if((Lines = Marker -> LastY - Y - 1) >= 0)
{
if(Marker -> LastX)
(*Marker -> Select)(Marker,0,Marker -> LastY,Marker -> LastX,1);
if(Lines > 0)
(*Marker -> Select)(Marker,0,Y + 1,Marker -> Width,Lines);
(*Marker -> Select)(Marker,X,Y,Marker -> Width - X,1);
}
else
{
if(Delta)
(*Marker -> Select)(Marker,X,Y,Marker -> Width - X,1);
else
(*Marker -> Select)(Marker,X,Y,Marker -> LastX - X,1);
}
Marker -> FirstColumn = X;
Marker -> FirstLine = Y + Marker -> Top;
}
}
Marker -> LastX = X;
Marker -> LastY = Y;
}
}
/* ToggleSelect(struct BlockMarker *Marker,LONG Left,LONG Top,LONG Width,LONG Height):
*
* Toggle selection subroutine.
*/
VOID
ToggleSelect(struct BlockMarker *Marker,LONG Left,LONG Top,LONG Width,LONG Height)
{
if(Width && Height)
ClipBlit(Marker -> Object,0,0,Marker -> Object,Marker -> LeftEdge + Left * Marker -> TextFontWidth,Marker -> TopEdge + Top * Marker -> TextFontHeight,Width * Marker -> TextFontWidth,Height * Marker -> TextFontHeight,0x50);
}
/* WriteTrimmedString(struct IFFHandle *Handle,STRPTR String,LONG Len):
*
* Write a string to the clipboard, sans trailing spaces.
*/
VOID __regargs
WriteTrimmedString(struct IFFHandle *Handle,STRPTR String,LONG Len)
{
while(Len > 0)
{
if(String[Len - 1] != ' ')
break;
else
Len--;
}
if(Len)
WriteChunkBytes(Handle,String,Len);
}
/* TrimLength(STRPTR String,LONG Len):
*
* Determine the length of a string, sans trailing spaces.
*/
LONG __regargs
TrimLength(STRPTR String,LONG Len)
{
while(Len > 0)
{
if(String[Len - 1] != ' ')
break;
else
Len--;
}
return(Len);
}
/* ClipPage(struct BlockMarker *Marker):
*
* Send the entire marked page to the clipboard.
*/
STATIC VOID __inline
ClipPage(struct BlockMarker *Marker)
{
struct IFFHandle *Handle;
if(Handle = AllocIFF())
{
if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config -> ClipConfig -> ClipboardUnit))
{
InitIFFasClip(Handle);
if(!OpenIFF(Handle,IFFF_WRITE))
{
if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
{
if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
{
LONG Lines = Marker -> LastLine - Marker -> FirstLine - 1,
i;
WriteTrimmedString(Handle,&Raster[RasterWidth * Marker -> FirstLine + Marker -> FirstColumn],Marker -> Width - Marker -> FirstColumn);
WriteChunkBytes(Handle,"\n",1);
if(Lines > 0)
{
STRPTR Line = &Raster[(Marker -> FirstLine + 1) * RasterWidth];
for(i = 0 ; i < Lines ; i++)
{
WriteTrimmedString(Handle,Line,Marker -> Width);
WriteChunkBytes(Handle,"\n",1);
Line += RasterWidth;
}
}
WriteTrimmedString(Handle,&Raster[RasterWidth * Marker -> LastLine],Marker -> LastColumn);
WriteChunkBytes(Handle,"\n",1);
PopChunk(Handle);
}
PopChunk(Handle);
}
CloseIFF(Handle);
}
CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
}
FreeIFF(Handle);
}
}
/* MarkWord(LONG MouseX,LONG MouseY):
*
* Mark a single word on the main screen (double-click).
*/
VOID
MarkWord(LONG MouseX,LONG MouseY)
{
LONG FirstX,FirstY;
FirstX = MouseX / TextFontWidth;
FirstY = MouseY / TextFontHeight;
if(FirstX > LastColumn)
FirstX = LastColumn;
if(FirstY > LastLine)
FirstY = LastLine;
ObtainSemaphore(RasterSemaphore);
if(Raster[FirstY * RasterWidth + FirstX] != ' ' && Raster[FirstY * RasterWidth + FirstX])
{
STRPTR Line = &Raster[FirstY * RasterWidth];
LONG LastX;
LastX = FirstX;
while(FirstX > 0 && Line[FirstX - 1] != ' ')
FirstX--;
while(LastX < LastColumn && Line[LastX + 1] != ' ')
LastX++;
if(WindowMarker = BM_SetMark(Window -> RPort,ToggleSelect,ToggleSelect,LastColumn + 1,LastLine + 1,WindowLeft,WindowTop,0,LastLine + 1,FirstX,FirstY,TextFontWidth,TextFontHeight))
{
ClearCursor();
SetWrMsk(RPort,DepthMask);
Marking = TRUE;
ReportMouse(TRUE,Window);
BM_ExtendMark(WindowMarker,LastX + 1,FirstY,0);
}
}
ReleaseSemaphore(RasterSemaphore);
}
/* SetMarker(LONG MouseX,LONG MouseY):
*
* Anchor a marker to the current mouse position.
*/
VOID
SetMarker(LONG MouseX,LONG MouseY)
{
LONG FirstX,FirstY;
FirstX = MouseX / TextFontWidth;
FirstY = MouseY / TextFontHeight;
if(FirstX > LastColumn)
FirstX = LastColumn;
if(FirstY > LastLine)
FirstY = LastLine;
if(WindowMarker = BM_SetMark(Window -> RPort,ToggleSelect,ToggleSelect,LastColumn + 1,LastLine + 1,WindowLeft,WindowTop,0,LastLine + 1,FirstX,FirstY,TextFontWidth,TextFontHeight))
{
ClearCursor();
SetWrMsk(RPort,DepthMask);
Marking = TRUE;
ReportMouse(TRUE,Window);
}
}
/* MoveMarker(LONG MouseX,LONG MouseY):
*
* Move the marker with the mouse.
*/
VOID
MoveMarker(LONG MouseX,LONG MouseY)
{
if(WindowMarker)
BM_ExtendMark(WindowMarker,(MouseX + TextFontWidth - 1) / TextFontWidth,MouseY / TextFontHeight,0);
}
/* DropMarker():
*
* Drop the window marker, restore the window contents.
*/
VOID
DropMarker()
{
if(WindowMarker)
{
struct RastPort *RPort = WindowMarker -> Object;
UBYTE Mask = WindowMarker -> WriteMask;
BM_ClearMark(WindowMarker);
SetWrMsk(RPort,Mask);
DrawCursor();
ReportMouse(FALSE,Window);
WindowMarker = NULL;
Marking = FALSE;
}
}
/* FreeMarker():
*
* Free the main window marker.
*/
VOID
FreeMarker()
{
if(WindowMarker)
{
struct RastPort *RPort = WindowMarker -> Object;
UBYTE Mask = WindowMarker -> WriteMask;
FreeVec(WindowMarker);
WindowMarker = NULL;
SetWrMsk(RPort,Mask);
ReportMouse(FALSE,Window);
Marking = FALSE;
}
}
/* ClipMarker():
*
* Transfer the marked area to the clipboard.
*/
VOID
ClipMarker()
{
if(WindowMarker)
{
ObtainSemaphore(RasterSemaphore);
SetWait(Window);
if(WindowMarker -> FirstColumn == WindowMarker -> Width)
{
WindowMarker -> FirstLine++;
WindowMarker -> FirstColumn = 0;
}
if(WindowMarker -> LastColumn == 0)
{
WindowMarker -> LastLine--;
WindowMarker -> LastColumn = WindowMarker -> Width;
}
if(WindowMarker -> FirstLine <= WindowMarker -> LastLine)
{
if(WindowMarker -> FirstLine != WindowMarker -> LastLine || WindowMarker -> FirstColumn != WindowMarker -> LastColumn)
{
if(WindowMarker -> FirstLine == WindowMarker -> LastLine)
SaveClip(&Raster[RasterWidth * WindowMarker -> FirstLine + WindowMarker -> FirstColumn],WindowMarker -> LastColumn - WindowMarker -> FirstColumn);
else
ClipPage(WindowMarker);
}
}
ClrWait(Window);
ReleaseSemaphore(RasterSemaphore);
DropMarker();
}
}