/*
 * rawcon.c
 *
 * Shell 2.07M  17-Jun-87
 * console handling, command line editing support for Shell
 * using new console packets from 1.2.
 * Written by Steve Drew. (c) 14-Oct-86.
 * 16-Dec-86 Slight mods to rawgets() for Disktrashing.
 *
 * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
 * Version 5.00L by Urban Mueller 17-Feb-91
 *
 */

#include "shell.h"

static int myget( void );
static void myunget(int c);
static void setrawcon( long flag, int ievent );
static int get_seq( long *param );
static int bkspcword( int i, int max, int cnt );


#if RAW_CONSOLE

static char *tyahdptr, *lasttya;
static int tabctr, qcdctr, histctr, occurctr, unget, oldmax;

#define SETRAW setrawcon(-1L,1);
#define SETCON setrawcon( 0L,1);

int w_width;
extern char *MenuCommand[MAXMENUS][MAXITEMS];

#define CTRL  -64
#define SHIFT 512
#define ESC   1024

#define CUP   256
#define CDN   257
#define CRT   258
#define CLT   259
#define TAB   9

static int Curmap;
static USHORT *Keymap[8];
static USHORT DefKeymap0[]={
       CLT,  0, /* CursLt = Move.Left  */
       CRT,  1, /* CursRt = Move.Right */
 SHIFT+CLT,  2, /* SCursLt= Move.WordL */
 SHIFT+CRT,  3, /* SCursRt= Move.WordR */
   ESC+CLT,  4, /* ESC-CLt= Move.SOL   */
   ESC+CRT,  5, /* ESC-CRt= Move.EOL   */
  CTRL+'A',  4, /* ^A     = Move.SOL   */
  CTRL+'E',  5, /* ^E     = Move.EOL   */
  CTRL+'Z',  4, /* ^Z     = Move.SOL   */
         8, 10, /* BackSp = Del.BackSp */
       127, 11, /* Delete = Del.Delete */
   ESC+  8, 12, /* ESC-BkS= Del.WordL  */
   ESC+127, 13, /* ESC-Del= Del.WordR  */
  CTRL+'W', 12, /* ^W     = Del.WordL  */
  CTRL+'B', 14, /* ^B     = Del.SOL    */
  CTRL+'K', 15, /* ^K     = Del.EOL    */
   ESC+'x',513, /* ESC-x  = Setmap 1   */
   ESC+'d', 16, /* ESC-d  = Del.Line   */
  CTRL+'X', 16, /* ^X     = Del.Line   */
       CUP, 20, /* CursUp = Hist.Back  */
       CDN, 21, /* CursDn = Hist.Forw  */
   ESC+CUP, 22, /* ECursUp= Hist.Beg   */
   ESC+CDN, 23, /* ECursDn= Hist.End   */
 SHIFT+CUP, 24, /* SCursUp= Hist.Compl */
   ESC+CUP, 24, /* ESC-!  = Hist.Compl */
   ESC+ 13, 25, /* ESC-Ret= Hist.Exec  */
  CTRL+'T', 26, /* ^T     = Hist.Tail  */
 SHIFT+CDN, 27, /* SCursDn= Hist.Clr   */
  CTRL+'P', 28, /* ^P     = Hist.DupWrd*/
       TAB, 30, /* Tab    = Comp.Norm  */
 SHIFT+TAB, 31, /* STab   = Comp.Part  */
   ESC+TAB, 32, /* ESC-TAB= Comp.All   */
   ESC+'*', 32, /* ESC-*  = Comp.All   */
   ESC+'c', 33, /* ESC-c  = Comp.CD    */
   ESC+'~', 34, /* ESC-~  = Comp.LastCD*/
  CTRL+'D', 35, /* CTRL-D = Comp.Dir   */
   ESC+'=', 35, /* ESC-=  = Comp.Dir   */
   ESC+'i', 40, /* ESC-i  = Spec.Insert*/
  CTRL+'L', 43, /* ^L     = Spec.Refr  */
        10, 44, /* Enter  = Spec.Accept*/
        13, 44, /* ^Enter = Spec.Accept*/
  CTRL+'N', 45, /* ^N     = Spec.Next  */
  CTRL+'O', 48, /* ^O     = Spec.EchoO */
 CTRL+'\\', 46, /* ^\     = Spec.EOF   */
       260, 42, /* Help   = Misc.Help  */
       271, 51, /* Menu   = Menu       */
  CTRL+'U', 52, /* Undo   = Spec.Undo  */
  CTRL+'R', 53, /* Repeat = Spec.Repeat*/
         0,  0
};

static USHORT DefKeymap1[]={
         8, 14,
       127, 15
};

static char *Line, *Prompt;
static int Pl;
static char LastDir[128];
static char Undo[256];

void
initmap(void)
{
	if( !Keymap[0] )
		Keymap[0]=DefKeymap0, Keymap[1]=DefKeymap1;
}

char *
rawgets( char line[], char prompt[] )
{
	static int inslen, lastrecall=-1;
	static int lastfn, lastkey;

	int    n, pl, max, i, c, key, fn, cnt;
	USHORT *p;
	char   *s, *ps, typeahd[256], *src, tmp;
	int    savn, insert=1, recall, undo_i, undo_max;
	struct HIST *hist;
	char   **eav=NULL, *ret, fake;
	int    eac, eactr=0;
	long   param[10], *par;

	typeahd[0]=0;
	tyahdptr=lasttya=typeahd;

	newwidth();

	if ( o_noraw || !isconsole(Input()) ) {
		if( isconsole(Input())) {
			printf("%s",prompt);
			fflush(stdout);
		}
		return(gets(line));
	}

	if (WaitForChar((long)Input(), 100L) ||   /* don't switch to 1L ...*/
	        CHARSWAIT(stdin)) {               /* else causes read err's*/
		gets(line);
		return(line);
	}

	SETRAW;
begin:
	printf("\015%s\033[6n",prompt);
	fake= savn = pl = n = 0;
	tyahdptr = typeahd;

	while( (typeahd[n]=getchar()) != 'R') {
		if (typeahd[n] == 155) savn = n;
		if (typeahd[n] == 27 && getchar()=='[')
			typeahd[n] =155, savn=n;
		n++;
	}
	/* typeahd now contains possible type a head chars
	   followed by <CSI> cursor position report. */

	if (typeahd[n-2] != ';') pl = (typeahd[n-2] -'0') * 10;
	pl += typeahd[n-1] - 49;
	ps = line + pl;
	typeahd[savn ] = 0;
	line[max=i=pl] = 0;
	undo_i=undo_max=pl;

	Line=line; Prompt=prompt; Pl=pl;

	if (s = get_var (LEVEL_SET, "_insert")) insert = atoi(s) ? 1 : 0;

	if( (recall=lastrecall)>=0 ) {
		lastrecall=-1;
		goto recallh;
	}

	while( (c=myget()) != -1) {
		int esc=0;
		key=-1;
		if( c==27 ) {
			esc=ESC;
			if((c=myget())=='[')
				c=155,esc=0;
		}
		switch(c) {
		case 155:
			switch(c=myget()) {
			case 'A': key=256;       break; /* CursUp */
			case 'B': key=257;       break; /* CursDn */
			case 'C': key=258;       break; /* CursRt */
			case 'D': key=259;       break; /* CursLt */
			case 'T': key=256+SHIFT; break; /* SCursUp */
			case 'S': key=257+SHIFT; break; /* SCursDn */
			case ' ':
				switch( myget() ) {
				case '@': key=258+SHIFT; break; /* SCursRt */
				case 'A': key=259+SHIFT; break; /* SCursLt */
				}
				break;
			case 'Z': key= 9+SHIFT;       break; /* STab    */
			case '?': key= 260; myget();  break; /* Help    */
			default :
				myunget(c);
				par=param;
				do {
					for( *par=0; (c=myget())>='0' && c<='9';  )
						*par=10* *par + c-'0';
					par++;
				} while( c==';' );
				if( c=='~' ) {
					key=param[0]+261;
					if( key>270 ) key+=SHIFT-10;
				}
				if( c=='|' ) key=271;
			} break;
		default: key=c; break;
		}
		key+=esc;

		for( fn=-1, p=Keymap[Curmap]; *p; p+=2 )
			if( *p==key )
				{ fn=p[1]; break; }
		if( fn==-1 && key>=261 && key<=270 || key>=261+SHIFT && key<=270+SHIFT )
			fn=50;

		if( fn!=52 && !*lasttya) {
			memcpy( Undo+pl, line+pl, max-pl );
			undo_i=i; undo_max=max;
		}

		switch( fn/512 ) {
		case 1:
			fn&=511;
			if( fn<8 && Keymap[fn] ) Curmap=fn;
			fn=-2;
			break;
		case 2:
			key=fn&511, fn=-1;
			break;
		}

		if( fn!=-2 )
			Curmap=0;

		if( fn!=53 && !*lasttya )
			lastfn=fn, lastkey=key;

dofn:
		switch( fn ) {
		case -2:
			break;

		case 0:                                 /* cursor left  */
			if (i > pl) 
				i--, printf("\033[D");
			break;
		case 1:                                 /* cursor right */
			if (i < max)
				i++, printf("\033[C");
			break;
		case 2:                                 /* word left    */
			for (cnt=0; i>pl && line[i-1] == ' '; cnt++,i--); 
			for (     ; i>pl && line[i-1] != ' '; cnt++,i--);
			if( cnt ) printf("\033[%dD",cnt);
			break;
		case 3:                                 /* word right   */
			for( cnt=0; i<max && line[i] != ' '; i++,cnt++) ;
			for(      ; i<max && line[i] == ' '; i++,cnt++) ;
			if( cnt ) printf("\033[%dC",cnt);
			break;
		case 4:                                 /* beg of line  */
			if (i>pl) printf("\033[%dD",i-pl);
			i = pl;
			break;
		case 5:                                 /* end of line  */
			if (i!=max) printf("\033[%dC",max - i);
			i = max;
			break;

		case 10:                                /* backspace    */
			if (i > pl) {
				i--;
				printf("\010");
			} else break;
		case 11:                                /* delete       */
			if (i < max) {
				int j,t,l = 0;
				memmove(&line[i],&line[i+1],max-i);
				--max;
				printf("\033[P");
				j = w_width - i % w_width - 1;  /* amount to end */
				t = max/w_width - i/w_width;    /* no of lines   */
				for(n = 0; n < t; n++) {
					l += j;                     /* # of char moved*/
					if (j) printf("\033[%dC",j);/* goto eol       */
					printf("%c\033[P",line[w_width*(i/w_width+n+1)-1]);
					j = w_width-1;
				}
				if (t)
					printf("\033[%dD",l+t);     /* get back       */
			}
			break;
		case 12:                                /* bkspc word     */
			cnt= bkspcword(i,max,-1);
			max-=cnt; i-=cnt;
			break;
		case 13:
			for( cnt=0; i<max && line[i]!=' '; i++,cnt++ ) ;
			for(      ; i<max && line[i]==' '; i++,cnt++ ) ;
			if ( cnt ) printf("\033[%dC",cnt);
			cnt=bkspcword(i,max,cnt);
			i-=cnt; max-=cnt;
			break;
		case 14:
			cnt=bkspcword(i,max,i-pl);
			i-=cnt; max-=cnt;
			break;
		case 16:                                /* delete line    */
			if (i>pl) printf("\033[%dD",i-pl);
			i = pl;
		case 15:                                /* delete to EOL  */
			printf("\033[J");
			max = i;
			line[i] = '\0';
			break;


		case 20:                                /* history up   */
			++recall;
		case 21:                                /* history down */
recallh:
			line[pl] = '\0';
			if (recall >= 0 || fn==20) {
				if ( fn==21 ) --recall;
				n=recall;
				if (recall >= 0) {
					for(hist = H_head; hist && n--;
					hist = hist->next);
					if (hist) strcpy(&line[pl],hist->line);
					else recall = H_len;
				}
			}
			if (i != pl)
				printf("\033[%dD",i-pl);
			printf("\033[J%s",ps);
			i = max = strlen(ps) + pl;
			break;
		case 22:                                /* beg of hist */
			recall = H_len-1;
		case 23:                                /* end of hist */
			line[pl] = '\0';
			if (fn == 23) {
				recall = 0;
				if (H_head) strcpy(&line[pl], H_head->line);
			} else if (H_tail)
				strcpy(&line[pl], H_tail->line);
			printf("\015\033[J%s%s", prompt, ps);
			i = max = strlen(ps) + pl;
			break;
		case 24:                                /* complete hist */
			if( histctr )
				occurctr=0, oldmax=max;
			occurctr++, histctr=1, max=oldmax;
			line[max]=0;
			if( s=get_history(&line[pl-1],2,occurctr )) {
				if (i>pl) printf("\033[%dD\033[J",i-pl);
				line[i=max=pl]=0;
				strncpy(typeahd,s,256);
				tyahdptr=typeahd;
			}
			break;
		case 25:                                /* exec hist  */
			lastrecall= recall;
			goto done;
		case 26:                                /* tail of prev */
			if( H_head && (s=H_head->line) && (s=index(s,' ')) )
				tyahdptr=s;
			break;
		case 27:                                /* botton   */
			recall=-1;
			goto recallh;
		case 28:                                /* duplicate word */
			for(s=line+i; s>ps && *(s-1)==' '; --s ) ;
			tmp=*s; *s=0;
			if( !(src=rindex(ps,' '))) src="";
			strcpy(tyahdptr=typeahd,src);
			*s=tmp;
			break;

		case 32:                                /* complete all     */
		case 35: tabctr=1;                      /* show files       */
		case 30:                                /* complete         */
		case 31:                                /* complete partial */
		case 33: {                              /* do quick cd      */
			static int lastcompl;
			int j, k, n, e, cnt, len, radlen;
			char *name, q, abbrev;

			abbrev= fn==31;
complete:
			tyahdptr="";
			if( tabctr!=0 ) {
				char *dest=typeahd, *lcd;

				lastcompl=fn;
				for( cnt=0; i<max && line[i]!=' '; ++i, ++cnt ) ;
				if(cnt) printf("\033[%dC",cnt);
				for( e=i, j=i-1, cnt=0; j>=pl && line[j]!=' ' && line[j]!='<' &&
				                 line[j]!='>' && line[j]!=';' ; --j ) cnt++;
				++j;

				if( line[j]=='~' && (lcd=get_var(LEVEL_SET,v_lcd))) {
					strcpy(dest,lcd);
					dest+=strlen(dest);
					j++;
				}
				memcpy(dest,&line[j],e-j);
				dest+=e-j;
				if( fn!=33 )
					*dest++='*';
				*dest=0;
				if( eav ) free_expand( eav ), eav=NULL;
				breakreset();
				tabctr=1;
				if( fn==33 ) {
					strncpy(LastDir,typeahd,128);
					if( !quick_cd( name=typeahd+128, LastDir, 0))
						{ putchar(7); break; }
				} else {
					eav =expand(typeahd,&eac);
					if( eac==0 ) { putchar(7); break; }
					QuickSort(eav, eac);
					if( fn==30 )
						name=eav[ eactr=0 ];
					else
						name=compile_av(eav,0,eac,' ',1), tabctr=0;
				} 
				inslen=cnt;
			} else {
				abbrev=0, tabctr=1;
				if( lastcompl==33 ) {
					quick_cd( name=typeahd+128, LastDir, 1);
				} else {
					if( !eac ) break;
					name=eav[eactr=++eactr % eac];
				}
			}
			if( fn==35 ) {
				if (i!=max) printf("\033[%dC",max - i);
				putchar('\n');
				for( j=0; j<eac; j++ )
					printf("%s ",BaseName(eav[j]));
				putchar('\n');
				goto refresh;
			}
			len=bkspcword(i,max,inslen);
			i-=len; max-=len;
			if( abbrev && eac>1) {
				strcpy( typeahd, eav[0] );
				radlen= 9999;
				for( k=0; k<eac; k++ ) {
					if ( (n=strlen(eav[k])) < radlen ) radlen=n;
					for( n=0; n<radlen&& tolower(eav[0][n])==tolower(eav[k][n]);
					     n++ ) ;
					if ( n<radlen ) radlen=n;
				}
				typeahd[radlen]=0;
				eactr--;
			} else {
				if( lastcompl==32 ) {
					strncpy( typeahd,name,250 );
					name[250]=0;
				} else {
					strcpy(typeahd,(q=hasspace(name)) ? "\"" : "" );
					strcat(typeahd,name);
					if( q ) strcat(typeahd,"\"");
					if( lastcompl==33 || isdir(name) )
						appendslash( typeahd );
					else 
						strcat( typeahd, " " );
				}
			}
			tyahdptr=typeahd;
			inslen=strlen(typeahd);
			}
			break;
		case 34:
			strncpy(typeahd,get_var( LEVEL_SET, v_lcd ),230);
			appendslash(tyahdptr=typeahd);
			break;

		case 40:                      /* ins/ovr */
			insert ^= 1;
			break;
		case 41:                      /* quit */
			strcpy(ps,"quit");
			goto done;
		case 42:                      /* help */
			strcpy(ps,"help");
			goto done;
		case 43:                      /* refresh   */
refresh:
			if ((n = i/w_width)) printf("\033[%dF",n);
			printf("\015\033[J%s%s",prompt,ps);
			if( fn!=54 ) i= max;
			else if(i!=max) printf("\033[%dD",max-i);
			break;
		case 44:
			line[max] = '\0';
done:		printf("\033[%dC\n",max - i);
			strcpy(line, ps);
			ret=line;
			if( fake ) goto begin;
			goto end;
		case 45:                      /* leave   */
			line[max] = '\0';
			add_history( ps );
			fake=1;
			goto done;
		case 46:                      /* EOF */
			ret=NULL;
			goto end;
		case 47:
			break;
		case 48:
			printf("\017");
			break;
		case 49:
			printf("\07");
			break;

		case 50: {
			char fkeys[8];
			sprintf(fkeys,"%c%d",param[0]>=10?'F':'f',param[0]%10+1);
			if (s = get_var(LEVEL_SET, fkeys)) {
				tyahdptr = strcpy(typeahd,s);
				a0tospace( tyahdptr );
			}
			break;
			}
		case 51: {
			int class=param[0], code=param[2];
			if( class==10 ) {
				int num=MENUNUM( code ), item=ITEMNUM( code );
				tyahdptr="";
				if( num>=0 && num<MAXMENUS && item>=0 && item<=MAXITEMS )
					tyahdptr=MenuCommand[num][item];                                 
			}
			if( class==11 ) {
				strcpy(ps,"quit");
				goto done;
			}
			}
		case 52: {
			int t;

			if ((n = i/w_width)) printf("\033[%dF",n);
			swapmem( Undo+pl, line+pl, MAX( max, undo_max)-pl );
			t=max; max=undo_max; undo_max=t;
			t=i;   i  =undo_i;   undo_i  =t;
			line[max]=0;
			printf("\015\033[J%s%s",prompt,ps);
			if( i<max ) printf("\033[%dD",max-i);
			}
			break;
		case 53:
			fn=lastfn; key=lastkey;
			goto dofn;
		case 54:
			if( i>pl+1 ) {
				char t;
				t=line[i-2]; line[i-2]=line[i-1]; line[i-1]=t;
			}
			goto refresh;

		default:
			key&=255;
			if (key == 9) key = 32;
			if (key > 31 && (insert?max:i) < 256) {
				if (i < max && insert) {
					int j,t,l = 0;
					memmove(&line[i+1], &line[i], max - i);
					printf("\033[@%c",key);
					t = max/w_width - i/w_width;
					j = w_width - i % w_width - 1;
					for(n = 0; n < t; n++) {
						l += j;
						if (j) printf("\033[%dC",j);
						printf("\033[@%c",line[w_width*(i/w_width+n+1)]);
						j = w_width-1;
					}
					if (t) printf("\033[%dD",l + t);
					++max;
				}
				else {
					if(i == pl && max == i) printf("\015%s%s",prompt,ps);
					putchar(key);
				}
				line[i++] = key;
				if (max < i) max = i;
				line[max] = '\0';
			}
		}
	}
	ret=NULL;
end:
	newwidth();
	if( eav ) free_expand(eav);
	SETCON;
	return ret;
}

int
bkspcword( int i, int max, int cnt )
{
	int o=i;

	if( !cnt ) return 0;

	if( cnt==-1 ) {
		cnt=0;
		while( i>Pl && Line[i-1]==' ' )  i--, cnt++;
		while( i>Pl && Line[i-1]!=' ' )  i--, cnt++;
	} else 
		i-=cnt;

	if( cnt ) printf("\033[%dD",cnt);
	memmove( Line+i, Line+o, max-o );
	memset ( Line+max-cnt, ' ', cnt  );
    
	printf("%s",Line+i);
    
	if( max-i ) printf("\033[%dD", max-i );
	fflush(stdout);
	Line[max-=cnt]=0;

	return cnt;
}

void
setrawcon( long flag, int ievent ) /* -1L=RAW:, 0L=CON: */
{
	static char menuon, button;
	long packargs[8];

	if( !o_nowindow && ievent && flag==0 && menuon)
		printf("\033[10}"), menuon=0;

	packargs[0]=flag;
	SendPacket(994L, packargs, (void *)Myprocess->pr_ConsoleTask);

	if( !o_nowindow && ievent && flag==-1 ) {
		if( !menuon )
			printf("\033[10{"), menuon=1;
		if( !button )
			printf("\033[11{"), button=1;
	}
	fflush(stdout);
}



static int row, height, cnt, noquick=1;
static char scrollstr[10];


extern BPTR OldCin;

static int FromTee;

extern struct MsgPort *Console;

int
isconsole( BPTR fh )
{
	return ((struct FileHandle *)(4*fh))->fh_Type == Console;
}


static UBYTE
mygetchar(void)
{
	UBYTE c;
	Read( Input(), &c, 1 );
	return c;
}

void
prepscroll( int fromtee )
{
	BPTR truecin=0;
	long param[8];

	row=height=0;
	FromTee=fromtee;

	if(( noquick=!o_scroll || o_noraw || o_nofastscr))
		return;
	if(( noquick=!isconsole(Myprocess->pr_COS) && !fromtee ))
		return;
	if( !isconsole(Myprocess->pr_CIS)) {
		truecin=Myprocess->pr_CIS;

		if( noquick=!isconsole(OldCin) )
			return;

		Myprocess->pr_CIS = DEVTAB(stdin) = OldCin;
	}

	if( !CHARSWAIT(stdin) ) {
		SETRAW;
		Write(OldCin,"\033[ q",4);
		get_seq( param );
		height=param[2];
		while( mygetchar()!='r') ;

		Write(OldCin,"\033[6n",4);
		get_seq( param );
		row=param[0];

		SETCON;

		cnt= height-row+1;
		noquick= height<o_minrows;
	}

	sprintf(scrollstr,"\033[%cS\033[%cA", o_scroll+'0', o_scroll+'0');

	if( truecin )
		Myprocess->pr_CIS = DEVTAB(stdin) = truecin;
}

static int
get_seq( long *param )
{
	int c;

	while( (c=mygetchar())!=155 ) ;
	do {
		*param=0;
		while( (c=mygetchar())>='0' && c<='9' )
			*param=10* *param + c-'0';
		param++;
	} while( c==';' );

	return c;
}


void
quickscroll( void )
{
	if( noquick ) return;

	if( --cnt<=0 ) {
		cnt=o_scroll;
		fprintf( FromTee ? stderr : stdout, "%s",scrollstr);
	}
}

int
do_keymap( void )
{
	int i, n, len;
	USHORT *tmp, *put, *get, *map;
	char   *ind;

	n=myatoi(av[1],0,7);
	if( atoierr ) return 20;

	map=Keymap[n]; len=0;
	if( map )
		for( len=0; map[2*len]; len++ ) ;

	put=tmp=salloc((len+ac)*2*sizeof(USHORT));
	for( i=2; i<ac; i++ ) {
		if( !(ind=index(av[i],'='))) {
			ierror( av[i],500);
			free( tmp );
			return 20;
		}
		*put++=atoi(av[i]);
		*put++=atoi(ind+1);
	}

	for( i=0; i<len; i++ ) {
		for( get=tmp; get<put; get+=2 )
			if( *get==map[2*i] )
				break;
		if( get==put ) {
			*put++=map[2*i];
			*put++=map[2*i+1];
		}
	}

	if( map && map!=DefKeymap0 && map!=DefKeymap1 )
		free( map );
	Keymap[n]=tmp;
	Curmap=0;

	return 0;
}

static int
myget( void )
{
	int c;

	lasttya=tyahdptr;
	if( unget )
		c=unget, unget=0;
	else if( tyahdptr && *tyahdptr)
		c=*tyahdptr++;
	else {
#ifndef AZTEC_C
		fflush(stdout);
#endif
		if( (c=getchar())!=155 )
			tabctr--, qcdctr--, histctr--;
	}

	return c;
}

static void
myunget(int c)
{
	unget=c;
}

int
newwidth( void )
{
	extern struct Window *Win;

	w_width=80;
	if( !o_nowindow && Win )
		w_width=(Win->Width-(Win->BorderLeft+Win->BorderRight))/
		         Win->RPort->TxWidth;
	if( w_width<1 ) w_width=1;          /* crash after resizing was reported */
	return w_width;
}



#else

prepscroll(){}
quickscroll(){}

#endif

