home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
comm
/
term23_2.lha
/
Source_Code
/
termSource
/
termMarker.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-22
|
14KB
|
635 lines
/*
** $Id: termMarker.c,v 1.4 92/08/15 20:14:43 olsen Sta Locker: olsen $
** $Revision: 1.4 $
** $Date: 92/08/15 20:14:43 $
**
** Text block marker routines
**
** Copyright © 1990-1992 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,WORD Left,WORD Top,WORD Width,WORD 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)
{
WORD 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,APTR Select,APTR Unselect,WORD Width,WORD Height,WORD Top,WORD Lines,WORD X,WORD 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 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;
}
/* Return marker buffer. */
return(Marker);
}
else
return(NULL);
}
/* BM_ExtendMark(struct BlockMarker *Marker,WORD X,WORD Y,WORD 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,WORD X,WORD Y,WORD 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,WORD Left,WORD Top,WORD Width,WORD Height):
*
* Toggle selection subroutine.
*/
VOID
ToggleSelect(struct BlockMarker *Marker,WORD Left,WORD Top,WORD Width,WORD Height)
{
if(Width && Height)
ClipBlit(Marker -> Object,0,0,Marker -> Object,Left * Marker -> TextFontWidth,Top * Marker -> TextFontHeight,Width * Marker -> TextFontWidth,Height * Marker -> TextFontHeight,0x50);
}
/* WriteTrimmedString(struct IFFHandle *Handle,STRPTR String,WORD Len):
*
* Write a string to the clipboard, sans trailing spaces.
*/
VOID __regargs
WriteTrimmedString(struct IFFHandle *Handle,STRPTR String,WORD Len)
{
while(Len > 0)
{
if(String[Len - 1] != ' ')
break;
else
Len--;
}
if(Len)
WriteChunkBytes(Handle,String,Len);
}
/* TrimLength(STRPTR String,WORD Len):
*
* Determine the length of a string, sans trailing spaces.
*/
WORD __regargs
TrimLength(STRPTR String,WORD 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 __regargs
ClipPage(struct BlockMarker *Marker)
{
struct IFFHandle *Handle;
if(Handle = AllocIFF())
{
if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config . ClipboardUnit))
{
InitIFFasClip(Handle);
if(!OpenIFF(Handle,IFFF_WRITE))
{
if(!PushChunk(Handle,'FTXT','FORM',IFFSIZE_UNKNOWN))
{
if(!PushChunk(Handle,0,'CHRS',IFFSIZE_UNKNOWN))
{
WORD 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);
}
}
/* MarkClip(BYTE SingleChar,BYTE Xerox):
*
* The Big One. Mark areas of the main screen and send them
* to the clipboard.
*/
VOID
MarkClip(BYTE SingleChar,BYTE Xerox)
{
WORD FirstX = Window -> MouseX / TextFontWidth,
FirstY = Window -> MouseY / TextFontHeight;
if(SingleChar)
{
UBYTE Char;
Char = Raster[FirstY * RasterWidth + FirstX];
if(Char && Char != ' ')
{
SerWrite(&Char,1);
if(Xerox)
{
switch(Config . SendCR)
{
case CR_IGNORE: break;
case CR_ASCR: SerWrite("\r",1);
break;
case CR_ASCRLF: SerWrite("\r\n",2);
break;
}
}
}
}
else
{
struct BlockMarker *Marker;
BYTE HasMouse = FALSE;
ClearCursor();
if(Marker = BM_SetMark(Window -> RPort,ToggleSelect,ToggleSelect,LastColumn + 1,LastLine + 1,0,LastLine + 1,Window -> MouseX / TextFontWidth,Window -> MouseY / TextFontHeight,TextFontWidth,TextFontHeight))
{
struct IntuiMessage *Massage;
ULONG Code,Class;
BYTE Done = FALSE;
UBYTE Mask = RPort -> Mask;
WORD PlusX = TextFontWidth - 1;
WORD MouseX,MouseY;
SetWrMsk(RPort,0xFF);
while(!Done)
{
WaitPort(Window -> UserPort);
while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
{
Class = Massage -> Class;
Code = Massage -> Code;
MouseX = Massage -> MouseX;
MouseY = Massage -> MouseY;
GT_ReplyIMsg(Massage);
if(Class == IDCMP_MOUSEBUTTONS && (Code & IECODE_UP_PREFIX))
{
BM_Draw(Marker,Marker -> Unselect);
if(Code == MIDDLEUP)
Xerox = TRUE;
Done = TRUE;
break;
}
if(Class == IDCMP_MOUSEMOVE)
{
if(!HasMouse)
{
SetMarker(Window);
HasMouse = TRUE;
}
BM_ExtendMark(Marker,(MouseX + PlusX) / TextFontWidth,MouseY / TextFontHeight,0);
}
}
}
SetWrMsk(RPort,Mask);
if(FirstX != Window -> MouseX / TextFontWidth || FirstY != Window -> MouseY / TextFontHeight)
{
SetWait(Window);
if(Marker -> FirstColumn == Marker -> Width)
{
Marker -> FirstLine++;
Marker -> FirstColumn = 0;
}
if(Marker -> LastColumn == 0)
{
Marker -> LastLine--;
Marker -> LastColumn = Marker -> Width;
}
if(Marker -> FirstLine <= Marker -> LastLine)
{
if(Marker -> FirstLine != Marker -> LastLine || Marker -> FirstColumn != Marker -> LastColumn)
{
if(Marker -> FirstLine == Marker -> LastLine)
SaveClip(&Raster[RasterWidth * Marker -> FirstLine + Marker -> FirstColumn],Marker -> LastColumn - Marker -> FirstColumn);
else
ClipPage(Marker);
if(Xerox)
{
if(!ClipInput)
{
if(!OpenClip())
ClipInput = ClipXerox = TRUE;
else
ClipInput = ClipXerox = FALSE;
}
}
}
}
}
FreeVec(Marker);
}
ClearPointer(Window);
SetCursor();
}
}