
/*------------------------------------------------------------------------- */
/*             POSITIONAL AND WINDOW OVERLAY                                */
/*------------------------------------------------------------------------- */

#include "pcstdio.h"
#include "pcdefs.h"             /* header containing all #defines */
#include "pcglobal.h"           /* global variable declarations */

/*      Function table here is compiled ONLY IF overlays are activated. */

#ifdef OVLON
int KLock();
int KRLock();
int KUnlock();
int KRUnlock();
int KEdit();
int KWin2();
int KWin1();
int KWhere();
int KUpdate();
int KTitles();
int KF1Hlp();				/* XXX */
int KSF1Hlp();				/* XXX */
int KAF1Hlp();				/* XXX */
int KCF1Hlp();				/* XXX */
int KHelp();
int KMHelp();
int KXHelp();
int KExit();

extern  int KLabel();
extern  int KFormula();
extern  int KNumber();
extern  int KBackSpace();
extern  int KNewline();
extern  int KBottom();
extern  int KFarRight();
extern  int KFarLeft();
extern  int KTop();
extern  int KDown();
extern  int KUp();
extern  int KRight();
extern  int KLeft();
extern  int KExchange();
extern  int KSetMark();
extern  int KUnivArg();
extern  int KAbort;
extern  int KReDraw();
extern  int KReCalc();
extern  int KOther();

int (*Functions[])() =   {
	&KBackSpace,
	&KNewline,
	&KDown,
	&KUp,
	&KRight,
	&KLeft,

	&KLabel,                /* These functions are mainly in PCCOMD.C       */
	&KFormula,
	&KNumber,
	&KBottom,
	&KFarRight,
	&KFarLeft,
	&KTop,
	&KExchange,
	&KSetMark,
	&KUnivArg,
	&KAbort,
	&KReDraw,
	&KReCalc,

	0,0,0,0,0,0,0,0,0,0,
	/*                      these functions are overlay PCREPLI.C
	        &KErase,
	        &KRErase,
	        &KPick,
	        &KRPick,
	        &KPut,
	        &KRPut,
	        &KInsLine,
	        &KDelLine,
	        &KInsColumn,
	        &KDelColumn,
	*/
	1,1,1,1,1,1,1,1,1,1,1,1,
	/*                         these functions are in overlay PCIO.C
	        &KPosition,
	        &KNxtUnlkd,
	        &KWidth,
	        &KFormat,
	        &KFormat,
	        &KJust,
	        &KPrint,
	        &KRPrint,
	        &KRead,
	        &KWrite,
	        &KSave,
	        &KZap,
	                        these functions are in this overlay */
	&KLock,
	&KRLock,
	&KUnlock,
	&KRUnlock,
	&KEdit,
	&KWin2,
	&KWin1,
	&KWhere,
	&KUpdate,
	&KTitles,
	&KF1Hlp,				/* XXX */
	&KSF1Hlp,				/* XXX */
	&KAF1Hlp,				/* XXX */
	&KCF1Hlp,				/* XXX */
	&KHelp,
	&KMHelp,
	&KXHelp,
	&KExit,

	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
	/*                      these functions are in overlay PCBUF.C
	        &BSwap,
	        &BReDraw,
	        &KSwitchBuf,
	        &KKillBuf,
	        &KStatBuf,
	        &KFind,
	        &KAssocBuf,
	        &KWinOther,
	        &KDnPage,
	        &KUpPage,
	        &KRtPage,
	        &KLtPage,
	        &KDnOPage,
	        &KUpOPage,
	        &KRtOPage,
	        &KLtOPage,
	*/
	&KOther    };
#endif

extern int GotForm;     /* comm. from KEdit() to KFormula() */

KLock()  {   
	MakSRegion();  
	ChgLock(1);   
}
KRLock() {   
	MakRegion();  
	ChgLock(1);   
}
KUnlock() {   
	MakSRegion();  
	ChgLock(0);   
}
KRUnlock() {   
	MakRegion();  
	ChgLock(0);   
}
ChgLock(set_lock)
int set_lock;
{   
	int x, y, *ip, locked;  
	char *elt, *GetElt(), *GetVElt();
	for (x=rangex[0]; x<=rangex[1]; x++)
		for (y=rangey[0]; y<=rangey[1]; y++)
		{   
			if (*((elt=GetElt(x,y))+TYPE) == FORMULA)
			{   
				ip = (int *) (elt+RELABS);  
				locked = *ip & 0x8000;
				if (set_lock && !locked)
				{   
					*ip |= 0x8000;  
					goto mk;   
				}
				if (!set_lock && locked)
				{   
					*ip &= 0x7FFF;
mk:
					modified = 1;
				}
			}
		}
	CmdStart((set_lock)? "Locked " : "Unlocked ");
	if (rangex[0] == rangex[1] && rangey[0] == rangey[1]) 
		outloc(curx,cury); 
	else TellRegion(rangex,rangey);
	LvCmdLine();
}

KEdit()         /* edit an existing formula at the cursor location */
{   
	char *elt, *fp, *ifp, *last, e_type;
	if (!(elt=GetElt(curx,cury)) || (e_type = *(elt+TYPE)) == NUMBER
	    || IsLocked(curx,cury))
	{   
		CmdStart("\007Cannot edit this entry");  
		LvCmdLine();  
		return;   
	}
	CmdStart("EDIT: ");
	if (e_type == LABEL) copystr(elt+VALUE, EntBuf);
	else DecForm(elt, EntBuf, 0);
	fp = last = EntBuf;  
	while (*last) ++last;
	while (1)
	{   
		Tposn(Tlines,7);  
		format(EntBuf);  
		Tputch(' ');
		Tposn(Tlines, fp-EntBuf+7);
		switch (NextFunc())
		{   
		case 0:     
			if (--fp < EntBuf) goto rt;             /* Backspace */
			if (last <= EntBuf) break;
			--last;  
			copystr(fp+1, fp);  
			break;
		case 1:     
			if (e_type == LABEL) MakLElt(last-EntBuf);
			else {
				keybuf = Keys[FORMCOMD];  
				gotkey=GotForm=1;
			}
			return;
		case 4:     
			if (fp >= EntBuf+77) {
				BEEP;  
				break;
			}
			if (++fp >= last) {
				*last++ = ' ';  
				*last = 0;
			}
			break;
		case 5:     
			if (fp > EntBuf) --fp;  
			break;
		default:    
			switch (keybuf) {
			case BEL:   
				BEEP;  
				goto rt;             /* Abort */
			case 001:   
				fp = EntBuf;  
				break;        /* C-A */
			case 004:   
				if (fp >= last) break;      /* C-D */
				--last;  
				copystr(fp+1, fp);  
				break;
			case 005:   
				fp = last;  
				break;          /* C-E */
			default:    
				if (keybuf < ' ' || last >= EntBuf+77)
				{   
					BEEP;  
					break;   
				}
				for (ifp = ++last; ifp > fp; --ifp)
					*ifp = *(ifp-1);
				Tputch(*fp++ = keybuf);
				if (fp >= last) *++last = 0;  
				break;
			} 
			break;
		}
	}
rt:
	ZapCmdLine();
}                                                       

KWin2()
{   
	int line_edge, col_edge, type_split;  
	struct window *twp;

	if (w2->active)
	{   
		CmdStart("\007Already have 2 windows");  
		LvCmdLine();  
		return;   
	}
	line_edge = curx == w->homex || curx == w->homex + w->lines - 1;
	col_edge = cury == w->homey || cury == w->homey + w->cols - 1;
	if (line_edge && col_edge)
	{   
		CmdStart("\007Cannot put a window there");  
		LvCmdLine();  
		return;
	}
	if (line_edge) type_split = 'v';
	else if (col_edge) type_split = 'h';  
	else
	{
gs:
		CmdStart("Vertical or Horizontal? ");
		switch (type_split=tolower(NextKey()))
		{   
		case BEL:
		case DEL:  
			ZapCmdLine();  
			return;
		case 'v':
		case 'h':   
			break;
		default:    
			BEEP;  
			goto gs;
		}
	}
	synch = confirm("Synchronize windows? ");
	ClrWindow(w);       /* zap whole screen */
	/* first, set up common parameters of *w2 */
	w2->active = TRUE;  
	w2->fullscreen = w->fullscreen = FALSE;
	w2->cx = w2->homex = curx;  
	w2->cy = w2->homey = cury;
	w2->colwidth = w->colwidth;  
	w2->decpl = w->decpl;
	w2->just = w->just;  
	w2->minx = w2->miny = 1;
	w2->markx = w->markx;  
	w2->marky = w->marky;
	w->cx = curx;  
	w->cy = cury;
	w2->curbuf = w->curbuf;  
	w2->prevbuf = w->prevbuf;

	if (type_split == 'h')      /* process horizontal split */
	{   
		w->lines = curx - w->homex;
		w->tlines = w->lines + w->minx;
		w->OK_EOS = FALSE;  
		--(w->cx);
		w2->homey = w->homey;
		w2->tlines = Tlines - w->tlines - 2;
		w2->toffy = 1;  
		w2->toffx = w->tlines + 2;
		w2->tdispx = w2->toffx + 1;  
		w2->tdispy = YAXWIDTH+1;
		w2->tcols = w->tcols;
		w2->OK_EOL = w2->OK_EOS = TRUE;
	} 
	else      /* vertical split */
	{   
		w->tcols = colpos(w,cury) - 1;
		w->OK_EOL = w->OK_EOS = FALSE;  
		--(w->cy);
		w2->homex = w->homex;
		w2->tlines = w->tlines;
		w2->tcols = Tcols - w->tcols - 1;
		w2->toffx = 1;  
		w2->toffy = w->tcols + 2;
		w2->tdispx = 2;  
		w2->tdispy = w2->toffy + YAXWIDTH;
		w2->OK_EOL = TRUE;  
		w2->OK_EOS = FALSE;
	}
	w2->lines = w2->tlines - 1;
	twp = w;  
	w = w2;  
	w2 = twp;        /* leave in 2nd window */
	/* let automatic ReDraw(w) take care of rest */
}

KWin1()
{   
	w2->active = w->fullscreen = FALSE;
	w->tlines = Tlines - 1;  
	w->tcols = Tcols;
	w->lines = Tlines - 2;  
	w->OK_EOL = w->OK_EOS = TRUE;
	w->toffx = w->toffy = 1;
	w->tdispx = w->minx + 1;  
	w->tdispy = (w->miny-1)*colwth(w,1)+YAXWIDTH+1;
	/* let automatic ReDraw(w) take care of rest */
}

KWhere()
{   
	int i;  
	struct buffer *Madr(), *cb;
	CmdStart("Last=");  
	outloc(lastx,lasty);
	format(" Region=");  
	MakRegion();  
	TellRegion(rangex,rangey);
	format(" Update=");  
	format((updform)? "auto" : "man");
	cb = Madr(Buff[w->curbuf]);
	if (cb->updx[0]) {
		putchar('/');  
		TellRegion(cb->updx, cb->updy);
	}
	if (pickbuf) {
		format(" Kill=");  
		TellRegion(pickx, picky);
	}
	format(" Mem=%d");  
	printf(freespace);  
	LvCmdLine();
} /*printf((freespace+512)/1024);  */

TellRegion(rx, ry)
int rx[2], ry[2];
{   
	outloc(rx[0], ry[0]);  
	format(":");  
	outloc(rx[1], ry[1]);   
}

KUpdate()       /* Choose type of formula updating */
{   
	int newdir, newform;  
	struct buffer *cb;
	CmdStart("recalculation Mode: ");  
	cb = Madr(Buff[w->curbuf]);
u1: 
	switch (tolower(NextKey()))
	{   
	case 'a':     
		updform = 1;  
		CmdStart("Automatic mode");  
		break;
	case 'm':     
		updform = 0;  
		CmdStart("Manual mode");  
		break;
	case 'r':     
		MakRegion();
		if (rangex[0] == rangex[1] && rangey[0] == rangey[1])
			cb->updx[0] = 0; 
		else
		{   
			cb->updx[0] = rangex[0];  
			cb->updx[1] = rangex[1];
			cb->updy[0] = rangey[0];  
			cb->updy[1] = rangey[1];
		}
		CmdStart("Update Region = ");
		if (cb->updx[0]) TellRegion(cb->updx, cb->updy);
		else format("entire spreadsheet");  
		break;
	case BEL:
	case DEL:     
		ZapCmdLine();  
		return;
	default:      
		CmdStart("\007Auto, Manual, or Region? ");
		goto u1;
	}
	LvCmdLine();
}

KTitles()
{   
	int fix;
	CmdStart("fix Titles: ");
gt:
	switch (fix=NextKey())
	{   
	case BEL:
	case DEL:  
		goto rt;
	case 'b':
	case 'a':   
		w->tdispx = w->toffx+2;  
		w->minx = 2;
		w->lines = w->tlines-2;  
		if (fix == 'a') break;
	case 'd':   
		w->tdispy = w->toffy+colwth(w,1)+YAXWIDTH;
		w->miny = 2;  
		break;
	case '\r':  
		w->tdispx = w->toffx+1;  
		w->tdispy = w->toffy+YAXWIDTH;
		w->minx = w->miny = 1;  
		w->lines = w->tlines-1;  
		break;
	default:    
		CmdStart("\007Across, Down, Both, or <CR>? ");  
		goto gt;
	}
	curx = w->homex = w->minx;  
	cury = w->homey = w->miny;  
	ReDraw(w);
rt:
	ZapCmdLine();
}


KF1Hlp ()
{
	FKeysHlp(F1HlpPge);
}
KSF1Hlp ()
{
	FKeysHlp(SF1HlpPge);
}

KAF1Hlp ()
{
	FKeysHlp(AF1HlpPge);
}

KCF1Hlp ()
{
	FKeysHlp(CF1HlpPge);
}

FKeysHlp (choice)
int	choice;
{
	if (fseek(swpfp, 0L, 0) == -1){
		BEEP;
		return;
	}
	if(fseek(swpfp, HELPPL*choice*256L, 0) != -1){
		OutHlpPge();
		CmdStart("Next key continues operation");
		LvCmdLine();
	} 
	else
		KReDraw();
}

KMHelp() {
	KHelp();
}
KXHelp() {
	KHelp();
}
KHelp()
{
	int choice;

	if (fseek(swpfp, HELPPL*FHlpPages*256L, 0) == -1){
		BEEP;
		return;
	}
	OutHlpPge();
	CmdStart("Your choice 1-%d: ");
	printf(NUMHELP);
	if((choice=getint(0)) > 0 && choice <= NUMHELP
	    && fseek(swpfp, HELPPL*(choice + FHlpPages)*256L, 0) != -1){
		OutHlpPge();
		CmdStart("Next key continues operation");
		LvCmdLine();
	} 
	else
		KReDraw();
}

OutHlpPge()
{   
	int c;
	Tcolor(C_HELP);  
	Tnorm();  
	Tposn(Tlines-HELPLINES,1);  
	TCLEOS();
	while (c=getc(swpfp)) Tputch(c);
}

KExit()
{   
	int i, change;
	for (i=change=0; i<MAXBUF; i++)
		if (Buff[i] && Madr(Buff[i])->bmod) ++change;
	if ((modified || change) && !confirm("Ignore changes this session? "))
	{   
		ZapCmdLine();  
		return;   
	}
	CleanUp();  
	exit();
}
