home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
396.lha
/
'Liner_v2.0
/
Source
/
mouse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-03
|
19KB
|
730 lines
#include "Globals.h"
char InvBuf[]=
{CSI,'7',0x6d,NULL,CSI,'0',0x6d};
char Inv[]=
{CSI,'7',0x6d,NULL};
char Norm[]=
{CSI,'0',0x6d,NULL};
struct LineItem *InvItem;
void MovedMouse(x,y) /*The mouse was moved! Record its new position*/
int x,y;
{
LastX=PtrX;
LastY=PtrY;
PtrY=(prefs.DS) ? (y/16)+1 : (y/8)+1;
PtrX=(x/8)+1;
}
HandleButton(Seconds,Micros) /*Handle a button press*/
int Seconds,Micros;
{
int status;
static int LastSeconds=1,LastMicros=1,DoubClicked=FALSE;
static UBYTE ButtonX,ButtonY;
/*If the user double-clicked (the mouse button), start or modify*/
/*a highlighted block*/
if(DoubleClick(LastSeconds,LastMicros,Seconds,Micros) &&
PtrY==ButtonY && !DoubClicked)
{
PtrX=ButtonX;
PtrY=ButtonY;
DoubClicked=TRUE;
HandleInvs();
BLastX=PtrX;
}
else /*Otherwise, just move the cursor accordingly*/
if(PtrY > 0 && PtrY <= SCRNHEIGHT)
{
ButtonX=PtrX;
ButtonY=PtrY;
DoubClicked=FALSE;
if(PtrY != InvY && InvsMode > NOINV) /*End text highlighting*/
EndLineInvs(); /*if the cursor is moved to a new line*/
if(PtrY-CurY < 0) /*move the cursor to a new line*/
status=MoveBack(-(PtrY-CurY));
else
status=MoveForward(PtrY-CurY);
if(status==FALSE)
return(FALSE);
if(PtrX > MaxX(CurrentItem)) /*Move the cursor to a new*/
CurX=MaxX(CurrentItem); /*X position*/
else
if(PtrX < MinX(CurrentItem))
CurX=MinX(CurrentItem);
else
CurX=PtrX;
PlotCursor(CurX,PtrY);
}
LastSeconds=Seconds;
LastMicros=Micros;
}
void HandleInvs() /*Handle a modification or creation of a highlighted block*/
{
if(InvsMode==NOINV)
if(PtrX >= MinX(CurrentItem) && PtrX <= MaxX(CurrentItem))
HandleLineInvs();
else
HandleBlockInvs();
else
if(InvsMode > NOINV)
HandleLineInvs(); /*Highlighting on one line*/
else
HandleBlockInvs(); /*Block highlighting*/
}
HandleBlockInvs() /*Handle the inverse of a block of lines*/
{
int X,Y;
if(InvsMode==NOINV) /*If nothing is highlighted*/
{
InvY=EndIY=CurY;
WriteConsole(Inv,-1);
PlotCursor(1,CurY);
PrintItem(CurrentItem);
WriteConsole(Norm,-1);
EndIItem=StartIItem=(struct LineItem *)CurrentItem;
PlotCursor(MinX(CurrentItem),CurY);
InvsMode=BLOCK_PENDING;
return(TRUE);
}
if(InvsMode==BLOCK_PENDING) /*If one line is highlighted*/
{
if(StartIItem == CurrentItem) /*Same line? End highlighting*/
{
EndBlockInvs();
return(TRUE);
}
else /*Else, highlight a block (up or down, depending)*/
if(IsAfter(CurrentItem,StartIItem)) /*down*/
{
EndIItem=(struct LineItem *)CurrentItem;
if((Y=IsOnScreen(StartIItem->NextItem)))
{
PlotCursor(1,Y);
RvsBlock(StartIItem->NextItem,EndIItem);
}
else
{
PlotCursor(1,1);
RvsBlock(FirstScrnItem,EndIItem);
}
EndIY=CurY=PtrY;
InvsMode=BLOCK_DOWN;
PlotCursor(MinX(EndIItem),CurY);
}
else /*up*/
if(IsBefore(CurrentItem,StartIItem))
{
EndIItem=(struct LineItem *)CurrentItem;
EndIY=CurY;
if( (Y=IsOnScreen(StartIItem->PrevItem)) )
RvsBlock(EndIItem,StartIItem->PrevItem);
else
RvsBlock(EndIItem,ScrnBtm);
PlotCursor(MinX(EndIItem),EndIY);
InvsMode=BLOCK_UP;
}
return(TRUE);
}
if(InvsMode == BLOCK_DOWN) /*If highlighting is down*/
{
if((IsAfter(CurrentItem,EndIItem)) && CurrentItem != EndIItem)
{ /*Highlight more*/
if( (Y=IsOnScreen(EndIItem->NextItem)))
{
PlotCursor(1,Y);
RvsBlock(EndIItem->NextItem,CurrentItem);
}
else
{
PlotCursor(1,1);
RvsBlock(FirstScrnItem,CurrentItem);
}
EndIY=CurY=PtrY;
EndIItem=(struct LineItem *)CurrentItem;
PlotCursor(MinX(EndIItem),IsOnScreen(CurrentItem));
}
if((IsBefore(CurrentItem,EndIItem)) && CurrentItem != EndIItem)
{ /*Unhighlight some*/
if(IsBefore(CurrentItem,StartIItem))
{
EndBlockInvs(FALSE);
return(TRUE);
}
EndIY=Y=CurY;
X=CurX;
PlotCursor(CurX,CurY+1);
NormBlock(CurrentItem->NextItem,EndIItem);
PlotCursor(X,Y);
EndIItem=(struct LineItem *)CurrentItem;
}
}
else /*The higlighting goes up*/
{
if((IsBefore(CurrentItem,EndIItem)) && CurrentItem != EndIItem)
{ /*Highlight*/
EndIY=Y=CurY;
if( (Y=IsOnScreen(EndIItem->PrevItem)) )
RvsBlock(CurrentItem,EndIItem->PrevItem);
else
RvsBlock(CurrentItem,ScrnBtm);
PlotCursor(MinX(CurrentItem),IsOnScreen(CurrentItem));
EndIItem=(struct LineItem *)CurrentItem;
}
/*Normalize*/
if((IsAfter(CurrentItem,EndIItem)) && CurrentItem != EndIItem)
{
if((CurrentItem==StartIItem)||(IsAfter(CurrentItem,StartIItem)))
{
EndBlockInvs();
return(TRUE);
}
Y=CurY;
PlotCursor(CurX,EndIY);
NormBlock(EndIItem,CurrentItem->PrevItem);
EndIItem=(struct LineItem *)CurrentItem;
PlotCursor(MinX(CurrentItem),IsOnScreen(CurrentItem));
EndIY=CurY;
}
}
}
void NormIt(Start,End,Start_y) /*Un-highlight an area on screen*/
struct LineItem *Start,*End;
int Start_y;
{
struct LineItem *CurItem;
CurItem=(struct LineItem *)Start;
WriteConsole(Norm,-1);
PlotCursor(1,Start_y);
CurY--;
while(CurItem != End->NextItem) /*Go down the screen*/
{
PlotCursor(1,CurY+1);
PrintItem(CurItem);
CurItem=(struct LineItem *)CurItem->NextItem;
}
}
void NormBlock(Start,End) /*Unhighlight a block of text, keeping it to*/
struct LineItem *Start,*End; /*what is on screen currently*/
{
int beg_y,end_y,old_y,old_x;
old_y=CurY;
old_x=CurX;
if((beg_y=IsOnScreen(Start))) /*If 'Start' is on the screen*/
if((end_y=IsOnScreen(End))) /*If 'End' is on screen*/
NormIt(Start,End,beg_y); /*Normalize a block in the normal way*/
else
NormIt(Start,ScrnBtm,beg_y);/*Normalize from 'Start' to end of screen*/
else
if(IsBefore(Start,FirstScrnItem)) /*If 'Start' is above the screen*/
if(IsAfter(End,ScrnBtm)) /*and 'End' is below it*/
NormIt(FirstScrnItem,ScrnBtm,1); /*Unhighlight the whole screen*/
else
if((IsOnScreen(End))) /*If the end is on the screen*/
NormIt(FirstScrnItem,End,1); /*Unhighlight from top to End*/
/*That's it (any other possibilities cause nothing to happen)*/
PlotCursor(old_x,old_y);
}
void RvsBlock(Start,End) /*Highlight a block*/
struct LineItem *Start,*End;
{
struct LineItem *CurItem;
int y;
CurItem=(struct LineItem *)Start; /*Start at the start*/
WriteConsole(Inv,-1); /*Activate inversed text*/
CurY--;
while(CurItem != End->NextItem) /*Go through list*/
{
if(y=IsOnScreen(CurItem)) /*Only do lines on screen*/
{
PlotCursor(1,y);
PrintItem(CurItem);
}
CurItem=(struct LineItem *)CurItem->NextItem;
}
WriteConsole(Norm,-1);
}
void EndBlockInvs() /*End the highlight of a block of lines*/
{
struct WhichOne which;
FindStartEnd(StartIItem,EndIItem,&which);
NormBlock(which.Start,which.End);
PlotCursor(MinX(CurrentItem),CurY);
InvsMode=NOINV;
}
HandleLineInvs() /*Handle the inverse of individual characters*/
{
int NewEnd;
if(PtrX < MinX(CurrentItem))
PtrX=MinX(CurrentItem);
else
if(PtrX > MaxX(CurrentItem))
PtrX=MaxX(CurrentItem);
if(InvsMode==NOINV) /*If nothing is highlighted, start highlighting*/
{
InvBuf[3]=CurrentItem->Text[PosInText(CurrentItem->Level)];
WriteConsole(InvBuf,7);
StartChar=EndChar=PosInText(CurrentItem->Level);
PlotCursor(CurX,CurY);
InvsMode=LINE_PENDING;
InvY=CurY;
InvItem=(struct LineItem *)CurrentItem;
return(TRUE);
}
if(InvsMode==LINE_PENDING) /*If one character only*/
{
if(PtrX == BLastX) /*Same character? Cancel highlighting*/
{
EndLineInvs();
return(TRUE);
}
if(PtrX > BLastX) /*After the character*/
{
EndChar=PosInText(InvItem->Level);
PlotCursor(BLastX,CurY);
RvsText(StartChar,EndChar);
CurX=CurX+EndChar-StartChar;
InvsMode=LINE_FWD;
PlotCursor(CurX,CurY);
return(TRUE);
}
if(PtrX < BLastX) /*Before the character*/
{
EndChar=PosInText(InvItem->Level);
RvsText(EndChar,StartChar-1);
PlotCursor(PtrX,CurY);
InvsMode=LINE_BACK;
}
return(TRUE);
}
else
if(InvsMode==LINE_FWD) /*Left to right highlighting*/
{
if(PtrX > BLastX) /*Forward (highlight more)*/
{
NewEnd=PtrX-MinX(InvItem);
PlotCursor(EndChar+MinX(InvItem),CurY);
RvsText(EndChar,NewEnd);
CurX=NewEnd+MinX(InvItem);
PlotCursor(CurX,CurY);
EndChar=NewEnd;
}
if(PtrX < BLastX) /*Backward (un-highlight)*/
if(PtrX-MinX(InvItem)<=StartChar)
EndLineInvs();
else
{
NewEnd=PtrX-MinX(InvItem);
NormText(NewEnd+1,EndChar);
PlotCursor(CurX,CurY);
EndChar=NewEnd;
}
}
else /*Right to left highlighting*/
{
if(PtrX < BLastX) /*Backward (highlight more)*/
{
NewEnd=PtrX-MinX(InvItem);
RvsText(NewEnd+1,EndChar);
PlotCursor(CurX,CurY);
EndChar=NewEnd;
}
if(PtrX > BLastX) /*Forward (un-highlight some)*/
if(PtrX-MinX(InvItem)>=StartChar)
EndLineInvs();
else
{
NewEnd=PtrX-MinX(InvItem)-1;
PlotCursor(EndChar+MinX(InvItem),CurY);
NormText(EndChar,NewEnd);
CurX=NewEnd+MinX(InvItem);
EndChar=NewEnd;
PlotCursor(CurX+1,CurY);
}
}
}
void RvsText(Start,End) /*Highlight a block of text*/
int Start,End;
{
char Buffer[80];
int c,l;
strcpy(Buffer,Inv);
l=strlen(Buffer);
for(c=l; c-l < End-Start+1 ; c++)
{
Buffer[c]=InvItem->Text[c+Start-l];
}
Buffer[c]=0;
strcat(Buffer,Norm);
WriteConsole(Inv,-1);
WriteConsole(Buffer,c);
WriteConsole(Norm,-1);
}
MoveBack(Number) /*Move back in the item list a specified number of times*/
int Number;
{
int c;
for(c=0;c<Number;c++)
{
if(CurrentItem->PrevItem==NULL)
return(FALSE);
else
CurrentItem=(struct LineItem *)CurrentItem->PrevItem;
}
return(TRUE);
}
MoveForward(Number) /*Move forward in the item list a specifiecd*/
int Number; /*number of times*/
{
int c;
struct LineItem *OrigItem;
OrigItem=(struct LineItem *)CurrentItem;
for(c=0;c<Number;c++)
{
if(CurrentItem->NextItem==NULL)
{
CurrentItem=(struct LineItem *)OrigItem;
return(FALSE);
}
else
CurrentItem=(struct LineItem *)CurrentItem->NextItem;
}
return(TRUE);
}
void EndLineInvs() /*End text inverse*/
{
if(StartChar < EndChar)
NormText(StartChar,EndChar);
else
NormText(EndChar,StartChar);
InvsMode=NOINV;
}
void NormText(Start,End) /*Un-reverse text*/
int Start,End;
{
int TempX,c;
char Buffer[80];
for(c=Start;c<=End;c++)
Buffer[c-Start]=InvItem->Text[c];
Buffer[c-Start]=0;
TempX=CurX;
PlotCursor(MinX(InvItem)+Start,InvY);
WriteConsole(Buffer,-1);
PlotCursor(TempX,InvY);
}
HandleDelBlock() /*Delete a block of lines*/
{
struct WhichOne which;
struct LineItem *temp;
BOOL stat;
/*If you're deleting everything, just call New*/
if((StartIItem->PrevItem==NULL && EndIItem->NextItem==NULL) ||
(StartIItem->NextItem==NULL && EndIItem->PrevItem==NULL))
{
NewAll();
return(TRUE);
}
/*Otherwise, find the true start and end and delete the block*/
FindStartEnd(StartIItem,EndIItem,&which);
if(which.Start->NextItem != NULL && which.Start->NextItem->cont &&
!which.Start->cont && which.Start==which.End) /*TRUE==parent*/
return(FALSE);
InvsMode=NOINV;
/*Find the end (last child)*/
if(which.End->NextItem->cont && (which.Start!=which.End))
{
temp=(struct LineItem *)which.End->PrevItem;
stat=FALSE;
while(temp!=which.Start)
{
if(!temp->cont)
stat=TRUE;
temp=(struct LineItem *)temp->PrevItem;
}
if(stat)
which.End=(struct LineItem *)FindNextNonCont(which.End);
}
DelBlock(which.Start,which.End,IsOnScreen(which.Start),
IsOnScreen(which.End));
return(TRUE);
}
/*When dealing with highlighted blocks, it is not guaranteed that*/
/*StartIItem comes before EndIItem in the linked list. This function*/
/*sorts out which is which and puts each pointer in an appropriate*/
/*space in a WhichOne structure (created especially for this function)*/
/*A kludge, I know. But 'Liner's grown up around this technique. It*/
/*would take more work than it is worth to change it*/
void FindStartEnd(Start,End,which)
struct LineItem *Start,*End;
struct WhichOne *which;
{
if(IsBefore(Start,End))
{
which->Start=(struct LineItem *)Start;
which->End=(struct LineItem *)End;
}
else
{
which->Start=(struct LineItem *)End;
which->End=(struct LineItem *)Start;
}
}
void DelBlock(Start,End,StartY,EndY) /*Delete a block of lines*/
struct LineItem *Start,*End;
int StartY,EndY;
{
int TOS;
if(!Start->cont)
{
Start=(struct LineItem *)FindPrevNonCont(Start);
End=(struct LineItem *)FindNextNonCont(End);
}
StartY=IsOnScreen(Start);
EndY=IsOnScreen(End);
if(!StartY) /*If the start of the inversed block isn't on*/
{ /*the screen, put it on the screen and then delete*/
FirstScrnItem=CurrentItem=(struct LineItem *)Start;
PrintItemList(Start,(StartY=1));
}
if(!EndY) /*Handle when the end isn't on screen*/
EndY=SCRNHEIGHT;
if(Start==FirstScrnItem)
TOS=TRUE;
else
TOS=FALSE;
if(Start->PrevItem == NULL) /*If there is nothing before 'Start'*/
{ /*Make 'End' the start of everything*/
CurrentItem=FirstItem=FirstScrnItem=
(struct LineItem *)End->NextItem;
CurrentItem->PrevItem=NULL;
RemItem(CurrentItem);
AddItem(CurrentItem);
TOS=FALSE;
}
else
if(End->NextItem==NULL) /*If 'End' is the end of everything, make*/
{ /*'Start'->PrevItem the start of everything*/
CurrentItem=LastItem=
(struct LineItem *)Start->PrevItem;
LastItem->NextItem=NULL;
if(Start==FirstScrnItem)
{
FirstScrnItem=ScrnBtm=(struct LineItem *)CurrentItem;
StartY=1;
}
else
StartY--;
TOS=FALSE;
}
else
{
CurrentItem=Start->PrevItem->NextItem=(struct LineItem *)
End->NextItem;
End->NextItem->PrevItem=
(struct LineItem *)Start->PrevItem;
}
if(TOS) /*If the Start was at the top of the screen...*/
CurrentItem=FirstScrnItem=(struct LineItem *)End->NextItem;
/*Free the deleted block's memory*/
FreeListMem(Start,End);
/*Update some ItemNumbers*/
RemItem(CurrentItem);
AddItem(CurrentItem);
BackSearchRefresh(CurrentItem);
PrintItemList(CurrentItem,StartY);
PlotCursor(MinX(CurrentItem),StartY);
}
void FreeListMem(Start,End) /*Free several Items at once*/
struct LineItem *Start,*End;
{
struct LineItem *Item,*Next;
Next=(struct LineItem *)Start;
do
{
Item=(struct LineItem *)Next;
Next=(struct LineItem *)Item->NextItem;
RemItem(Item);
if(Item->PrevItem !=NULL)
Item->PrevItem->NextItem=(struct LineItem *)Item->NextItem;
if(Item->NextItem != NULL)
Item->NextItem->PrevItem=(struct LineItem *)Item->PrevItem;
FreeMem(Item,sizeof(struct LineItem));
}
while(Item != End && Next != NULL);
}
void DelTextBlock() /*Delete the highlighted text*/
{
int c,Start,End,len;
char Buffer[2];
if(StartChar < EndChar) /*Find the start of the highlighted block*/
{
Start=StartChar;
End=EndChar;
}
else
{
Start=EndChar;
End=StartChar;
}
len=strlen(InvItem->Text);
for(c=0;c <= len-End; c++)
InvItem->Text[c+Start]=InvItem->Text[c+End+1];
PlotCursor(1,InvY);
Buffer[0]=CSI;
Buffer[1]=0x4b;
WriteConsole(Buffer,2);
PrintItem(InvItem);
PlotCursor(MinX(InvItem)+Start,InvY);
InvsMode=NOINV;
}
CancelLineInvs() /*Cancel an inversed text section*/
{
if(NOINV == InvsMode)
return(FALSE);
else
if(InvsMode > NOINV)
EndLineInvs();
}
CancelInvs() /*Cancel inversed text or lines*/
{
if(NOINV == InvsMode)
return(FALSE);
else
if(InvsMode > NOINV)
EndLineInvs();
else
EndBlockInvs();
return(TRUE);
}
DelInvs() /*Delete the highlighted block or text*/
{
if(InvsMode==NULL)
return(FALSE);
if(InvsMode > NOINV)
DelTextBlock();
else
HandleDelBlock();
return(TRUE);
}
void TitleError(string) /*Display 'string' in the title bar*/
char *string;
{
DisplayBeep(Screen);
ErrorInTitle = TRUE;
SetWindowTitles(Window,-1,string);
}
void TitleErrorCancel() /*Set the title bar text to normal (with the */
{ /*current filename in the title bar*/
static char Title[85];
strcpy(Title,ScreenTitle);
if(FileName[0])
strncat(Title,FileName,65);
else
strcat(Title,"Untitled");
if(Modified==TRUE) /*If the outline has been modified*/
Title[0]='*'; /*Put a '*' before "'Liner"*/
ErrorInTitle = FALSE;
SetWindowTitles(Window,-1,Title);
}
void BackSearchRefresh(Base) /*Do a refresh of ItemNumbers by searching*/
struct LineItem *Base; /*back through the item list*/
{
struct LineItem *Work,Dummy;
Dummy.PrevItem=(struct LineItem *)Base->PrevItem;
Dummy.NextItem=(struct LineItem *)Base->NextItem;
for(Dummy.Level=Base->Level;Dummy.Level > 0;Dummy.Level--)
if((Work=(struct LineItem *)FindPrev(&Dummy))!=NULL)
{
RemItem(Work);
AddItem(Work);
}
}
/*End of mouse.c*/