/* ---------------------------- Ue20.c ---------------------------- */

#include "uedit.h"

static short pixels;
static short pixellinelen;
static short spaceLen,lineLen = 0;

static UCHAR pixeltable[256];

FtypeChar()
{
register short    i,j,rtn;

	rtn = FALSE;
	if (!canChange(curBuf)) goto RTN;
	j = args[0];
	if (j==eLine_)	i = eol;
	else 			i = *longPtrArgs[0];
	i &= 255;
	gcol = -1;
	rtn = insertChar(i);
RTN:
	return(rtn);
}

insertChar(register short ichar)
{
register UCHAR  	   *fP;
register struct CB     *curB;
register short  	   rtn;
register ULONG  	   i,j,p;

	wrap = 0;
	curB = curBuf;
	colTrack = -1;

	i = curB->LineLength;
	if (i!=lineLen) {
		pixellinelen =  (i << 3) + (i << 4);		/* i*24 = i*8 + i*16 */
		lineLen = i;
	}
	if (spaceLen == 0) {
		fP = openOld("UEP.table");
		if (fP==NULL) fP = openOld(fileName(sss,"UEP.table"));
		if (fP!=NULL) {
			if (Read(fP,pixeltable,256L)!=256L) {
				Close(fP);
BOMBOUT:
				oneOk("UEP.table not found or corrupt.  Aborting.");
				badQuit();
			}
			Close(fP);
		} else goto BOMBOUT;
		spaceLen = pixeltable[32];
	}
	i = curB->Flags;
	if (i & (READONLY | LOCKED)) return(FALSE);
	if (ISWEIRD(ichar)) {
		if (i & MAPCHARS) ichar = charMappings[ichar];
		else return(FALSE);
	}	 
	untakeFast();
	fP = fastP;
	stickMode = 0;
	if (gcol < 1) gcol = getcol();
	rtn = TRUE;
	displayFlag |= SHOWCURSOR_;
	if (*fP==EOFILE)  displayFlag |= SHOWEOS_;
	if (ichar==eol || ichar==12) {
		rtn = stickeol(ichar);
		goto OUT;
	}
	if (ichar==DEL) goto DELCHAR;	 /* delete character UNDER cursor */
	if (ichar==BS && !reformatting) {			   /* delete character to LEFT of cursor */
		if (fP!=curB->NextBlock->Data) {
			--gcol;
			fP = decFast();
			if (*fP==TAB) gcol = -1;
DELCHAR:	if (*fP==EOFILE) goto OUT;
			if (*fP==eol || *fP==12) {
				fastB->eols = 255;
				if (ichar==BS) { --oldCursorLine; gcol = -1; }
				if (oldCursorLine<1) {
					oldCursorLine = 1;
					saveFast();
					fastB = curB->PBlock; fastP = curB->PPtr;
					curB->PPtr = sLineFast();
					curB->PBlock = fastB;
					unsaveFast();
					displayFlag |= (PAGE_ << curSplit);
				} else displayFlag |= SHOWEOS_;
			}
			*fP = 0x00;
			p = (ULONG)fP;
			fP = incFast();
			matchPtrs((UCHAR **)curB,(ULONG)fastB,p,(ULONG)fP);
		}
		goto OUT;
	}
											 /* insert char, space or TAB */
	if (curB->Flags & WORDWRAP) goto WRAPIT;
STICKIT:								
	pixels += pixeltable[ichar];
	j = 1;
	if (gcol<1) gcol = getcol();
	if (ichar==TAB) {
		curTable = tabTables[curBuf->tabTable];
										   /* col is based on tabs so far */
		curCol = gcol;
		j = tabcalc() & 0x00ff;
		if (columnar) {
			if (!(curB->Flags & TRUETABS)) {
				j = 1;
				goto TABSPACE;
			}
			goto NOTTAB;
		}
							 /* no next tab column, maybe none at all set */
		if (j==0) { 						   /* no more or not any tabs */
			if (*curTable) {			 /* very first tab col */
				j = curB->Flags;
				curB->Flags &= ~AUTOINDENT;
				rtn = stickeol((short)eol); 				/* resets gcol to -1 */
				if (!rtn) goto OUT;
				if (gcol<1) gcol = getcol();
				curB->Flags = j;
				curCol = 1;
				j = tabcalc() & 0x00ff; 	 /* delta to tabcol */
			} else goto NOTTAB;
		}
		if ((curB->Flags & TRUETABS) || primitive==2) goto NOTTAB;
TABSPACE:
		while (j-- > 0) {
			rtn = stickChar(32);
			if (!rtn) break;
			gcol++;
		}
		goto OUT;
	}
NOTTAB:
	stickMode = (curB->Flags & OVERSTRIKE) ? 1 : 0;
	rtn = stickChar(ichar);  /* ========= goes OUT from here stickMode ok */
	if (!rtn) goto OUT;
	if (j<1) j = 1;
	gcol += j;
	if (*curB->PPtr!=EOFILE) goto OUT;   /* so can type into mty buf */
	saveFast();
	fastB = curB->PBlock; fastP = curB->PPtr;
	curB->PPtr = sLineFast();
	curB->PBlock = fastB;
	unsaveFast();
	goto OUT;
WRAPIT:
	j = gcol;
	i = curB->LineLength + 1;
	if (pixels<=pixellinelen) goto STICKIT;
BACKUP:
	j--;
	rtn = *decFast(); pixels -= pixeltable[rtn]; 
	if (j<1)   goto NOWRAP;
	if (pixels <= pixellinelen ) {
		if (rtn <=' ') {
			rtn = *decFast();
			if (rtn!=' ') incFast();
			else pixels -= spaceLen; 
			goto DOWRAP;
		}
		if ((rtn=='-' || rtn=='/') && pixels <= (pixellinelen-24) )  { incFast(); goto DOWRAP; }
	}
	goto BACKUP;
DOWRAP:
	j++;
	wrap = rtn = TRUE;
	i = gcol - j;
	if (j>1) rtn = stickeol((short)eol);						  /* resets gcol */
	if (visible) {
		oldCursorLine--;
		display();
		displayFlag = SHOWCURSOR_;
	}
NOWRAP:
	untakeFast();
	if (ichar!=' ' || i>0 ||  !wrap) goto STICKIT;

OUT:
	takeFast();
	curB->Flags |= (CHANGED | NEEDPACK);
	if (gcol<1) gcol = getcol();
	oldCursorCol = gcol - curB->PageCol;

NOWORK:
	fixSOF(curB);
	return(rtn);
}

stickeol(short ch)	/* copes with autoIndent */
{
register UCHAR  		  *fP;
register struct CB  	  *curB;
register short  		  i,j,rtn;
register ULONG  		  flags;

	fastB->eols = 255;
	curB = curBuf;
	rtn = FALSE;
	flags = curB->Flags;
	getcol();
	if (curB->LeftMargin>0) indent = curB->LeftMargin - 1;
	stickMode = 0;
	if (!stickChar(ch)) goto BREAKOUT;
	pixels = 0;
	gcol = -1;
	i = indent + 1;
	if ((flags & AUTOINDENT) && i>1) {
		  if (flags & TRUETABS) {
			fP = tabTables[curB->tabTable];
			j = 1;
			while (*fP && i>=*fP) {
				if (!stickChar(TAB)) goto BREAKOUT;
				j = *(fP++);
			}
			i -= (j - 1);
		 }
		 j = spaceLen;
		 while (--i > 0) {
			if (!stickChar(32)) goto BREAKOUT;
			pixels += j;
		 }
	}
	rtn = TRUE;
BREAKOUT:
	fP = fastP;
	while (*fP==' ' || *fP==TAB) {		/* remove unwanted leading spaces */
	  *fP = 0x00;
	  incFast();
	  matchPtrs((UCHAR **)curB,(ULONG)fastB,(ULONG)fP,(ULONG)fastP);
	  fP = fastP;
	}
	if ((flags & RIGHTJUSTIFY) && wrap) rtn = justify();
										   /* make onScreen col-test fail */
	if (oldCursorLine>=(stopSplit[0] - 1)) {
	   curB->PageCol = 0;
	   displayFlag |= PAGE_;					   /* force onscreen test */
	   curB->EPtr = curB->PPtr;
	   curB->EBlock = curB->PBlock; 			/* FORCE onscreen to fail */
	} else displayFlag |= SHOWEOS_;
	return(rtn);
}

justify()
{
register UCHAR  	*fP;
register struct CB  *curB;
register short  	inc,dir,rtn;
register UCHAR  	eoline;
register ULONG  	saveB,saveP;

	rtn = TRUE;
	eoline = eol;
	curB = curBuf;
	curTable = tabTables[curB->tabTable];
	solFast();
	saveP = (ULONG)decFast();
	saveB = (ULONG)fastB;									  /* end of LAST line */
	fP = decFast();  					 /* end char of LAST wrapped line */
	while (*fP==' ' || *fP==TAB) {
	   *fP = 0x00;  							   /* delete trail spaces */
	   matchPtrs((UCHAR **)curB,saveB,(ULONG)fP,saveP);
	   fP = decFast();
	}
	dir = inc = 1;
	
	fP = sLineFast(); pixels = pixeltable[*fP]; 
	while (*fP != eoline && *fP != 12 && *fP!=EOFILE) {
	   if (*fP==TAB) {
			if (dir) {
				curCol = inc;
				inc += tabcalc() & 0x00ff;
				goto NEXTHIT;
			}
			else *fP=' ';  /* replace embedded tabs!!!! */
	   }
	   if (*fP>' ') dir = 0;	/* no longer indenting */
	   pixels += pixeltable[*fP];  inc++;
NEXTHIT:
	   fP = incFast();
	}
	/* now fP is at END of line will be working on */
	dir = curB->LineLength; inc = 1 + (pixels/24); 
	if (--inc>=dir) goto DONE;
	if (inc >= (dir - (dir >> 2)) ) {
	   inc = dir - inc;
	   fP = sLineFast();									   /* goto sol */
	   while (*fP==' ' || *fP==TAB) fP = incFast();    /* skip indentation */
	   while (*fP!=' ' && *fP!=eoline && *fP!=12 && *fP!=EOFILE)
								fP = incFast();
													   /* after FIRST WORD */
										/* one large word or PROBLEM!!!!!! */
	   if (*fP==eoline || *fP==12 || *fP==EOFILE) goto DONE;
	   *fP = TRACE; 					/* mark where to stop scanning */
	   if (flipRight & 1) {
		   dir = 0; 										   /* backward */
		   fP = eLineFast();
	   } else dir = 1;  										/* forward */
	   flipRight ^= 1;
	   while (inc>0) {
		   if (*fP==' ' || *fP==TRACE) {
			   if (!stickChar(32)) { rtn = FALSE; break; }
			   inc--;
		   }
		   if (dir) {											/* forward */
			   fP = incFast();
			   while (*fP==' ') fP = incFast();
			   while (*fP!=' ' && *fP!=eoline && *fP!=12 && *fP!=EOFILE)
								fP = incFast();
			   if (*fP==eoline || *fP==12 || *fP==EOFILE) {
				   dir ^= 1;
				   goto BACKWARD;
			   }
		   } else { 										   /* backward */
BACKWARD:	   while (*fP==' ') fP = decFast();
			   while (*fP!=' ' && *fP!=TRACE
					 && fP!=curB->NextBlock->Data) fP = decFast();
			   if (*fP==TRACE || fP==curB->NextBlock->Data) dir ^=1;
		   }
	   }
	   fP = incFast();
	   while (*fP != TRACE && fP!=curB->NextBlock->Data) fP = decFast();
	   while (*fP!=TRACE && *fP!=EOFILE) fP = incFast();
	   if (*fP==TRACE) *fP = ' ';
	}
DONE:
	return(rtn);
}

getcol()
{
register UCHAR  		  *sP,*ff,spaces,j,ch;
register short  		  i;

	sP = fastP;
	j = eol;
	ff = (UCHAR *)fastBufPtr->NextBlock->Data;
	pixels = 0;
FINDSOL:
	if (fastP==ff) goto GOTSOL;
	ch = *decFast();
	if (ch==j || ch==12) {
		incFast();
		goto GOTSOL;
	}
	goto FINDSOL;
GOTSOL:
	indent = 0; i = spaces = j = 1;
	curTable = tabTables[fastBufPtr->tabTable];
	ch = *fastP;
EQLOOP:
	if (sP==fastP) return(i);
	if (ch>' ') spaces = 0;
	if (ch==TAB) {
		curCol = i;
		j = tabcalc() & 0x00ff;
		if (j==0) j=1;
	} else j=1;
	i += j;
	pixels += pixeltable[ch];
	if (spaces) indent = i - 1;
	ch = *incFast();
	goto EQLOOP;
}

tabcalc()			/* upper byte = tabcol t/f, lower = inserttabs */
{
register	UCHAR		*t,j,maxtabs;
register	short		tabCol,col;

	tabCol = 0; 	/* not tab col, none to insert */
	col = curCol;
	if (columnar || col<1 || col>255) goto RTP;
	t = curTable;
	maxtabs = MAXTABS;
	
	j = 0;
TABLOOP:
	if (j>=maxtabs) goto TABDONE;
	if (*t == 0)	goto RTP;
	if (col == *t || col==1) tabCol = 0x0100;
	if (col<*t) goto TABDONE;
	j++;
	t++;
	goto TABLOOP;
TABDONE:
	if (j>=maxtabs) goto RTP;
	tabCol |= (*t - col);
RTP:
	return(tabCol);
}

