Esempio n. 1
0
/*-----------------------------------------------------------------------------------*/
static void
add_text(char *text)
{
  unsigned char i;
  unsigned int len;
  
  len = (unsigned int)strlen(text);

  i = 0;
  while(len > 0) {
    if(*text == '\n') {
      scrollup();
      i = 0;
    } else if(*text == '\r') {
      i = 0;
    } else if(*text >= ' ') {
      telnettext[(TELNET_TEXTAREA_HEIGHT - 1) * TELNET_WINDOW_WIDTH + i] = *text;
      ++i;
      if(i == TELNET_WINDOW_WIDTH) {
	scrollup();
	i = 0;
      }
    }
    ++text;
    --len;
  }

  /*  if(strlen(text) > 37) {
      memcpy(&telnettext[9 * 38], text, 37);
      } else {
      memcpy(&telnettext[9 * 38], text, strlen(text));
      }
  */
}
Esempio n. 2
0
void putcar(uchar c)
{
	unsigned char *video;
	int i;

	if (c == 10) {		/* CR-NL */
		kX = 0;
		kY++;
	} else if (c == 9) {	/* TAB */
		kX = kX + 8 - (kX % 8);
	} else if (c == 13) {	/* CR */
		kX = 0;
	} else {		/* autres caracteres */
		video = (unsigned char *) (RAMSCREEN + 2 * kX + 160 * kY);
		*video = c;
		*(video + 1) = kattr;

		kX++;
		if (kX > 79) {
			kX = 0;
			kY++;
		}
	}

	if (kY > 24)
		scrollup(kY - 24);
}
Esempio n. 3
0
/* Print a C string (NUL-terminated) */
void cswprint(const char *str, char attr, char left)
{
    char page = getdisppage();
    char newattr = 0, cha, chb;
    char row, col;
    char nr, nc;

    nr = getnumrows();
    nc = getnumcols();
    getpos(&row, &col, page);
    while (*str) {
	switch (*str) {
	case '\b':
	    --col;
	    break;
	case '\n':
	    ++row;
	    col = left;
	    break;
	case '\r':
	    //col=left;
	    break;
	case BELL:		// Bell Char
	    beep();
	    break;
	case CHRELATTR:	// change attribute (relatively)
	case CHABSATTR:	// change attribute (absolute)
	    cha = *(str + 1);
	    chb = *(str + 2);
	    if ((((cha >= '0') && (cha <= '9')) || ((cha >= 'A') && (cha <= 'F'))) && (((chb >= '0') && (chb <= '9')) || ((chb >= 'A') && (chb <= 'F'))))	// Next two chars are legal
	    {
		if ((cha >= 'A') && (cha <= 'F'))
		    cha = cha - 'A' + 10;
		else
		    cha = cha - '0';
		if ((chb >= 'A') && (chb <= 'F'))
		    chb = chb - 'A' + 10;
		else
		    chb = chb - '0';
		newattr = (cha << 4) + chb;
		attr = (*str == CHABSATTR ? newattr : attr ^ newattr);
		str += 2;	// Will be incremented again later
	    }
	    break;
	default:
	    putch(*str, attr, page);
	    ++col;
	}
	if (col >= nc) {
	    ++row;
	    col = left;
	}
	if (row > nr) {
	    scrollup();
	    row = nr;
	}
	gotoxy(row, col, page);
	str++;
    }
}
Esempio n. 4
0
File: font.c Progetto: nssilva/SDL
void newline(bc *bc)
{
	bc->txpos = 0;
	if(bc->typos < bc->tysize-1)
		++bc->typos;
	else
		scrollup(bc);
}
Esempio n. 5
0
void
sigwinch(int sig)
{
	scrollup(cursor_y);
	cursor_y = 0;
	fprintf(stdout, "%c[2K\r", 0x1b);
	clrtobot();
	termio_update(); /* XXX: this is probably a bad idea */
}
Esempio n. 6
0
int scrollbbk(void)
{
if(wn[cwin].scb==0)return 0;
wn[cwin].scb--;
if(wn[cwin].scb==0)dowindinfo(cwin);
scrollup(cwin,1);
drawvslid();
return 0;
}
Esempio n. 7
0
/*-----------------------------------------------------------------------------------*/
void
telnet_sent(struct telnet_state *s)
{
  petsciiconv_topetscii(sendline, sizeof(sendline));
  scrollup();
  add_text(sendline);
  CTK_TEXTENTRY_CLEAR(&telnetlinetextentry);
  ctk_window_redraw(&telnetwindow);
}
Esempio n. 8
0
static void newline(int n) {
	consoles[n].cur_x = 0;
	consoles[n].cur_y++;
	if (consoles[n].cur_y >= consoles[n].lines) {
		scrollup(n, consoles[n].attr);
		consoles[n].cur_y--;
	}
	cursor_position_video(n, consoles[n].cur_x, consoles[n].cur_y);
}
Esempio n. 9
0
int kernel_main() {
    init_gdt();
    init_idt();
    init_video();

    setcolor(make_color(COLOR_GREEN, COLOR_BLACK));
    printf("Hello, World!");
    newline(5);
    setcolor(make_color(COLOR_ORANGE, COLOR_BLACK));
    printf("                          ,--.\n");
    printf("                   _/ <`-'\n");
    printf("               ,-.' \\--\\_\n");
    printf("              ((`-.__\\   )\n");
    printf("               \\`'    @ (_\n");
    printf("               (        (_)\n");
    printf("              ,'`-._(`-._/\n");
    printf("           ,-'    )&&) ))\n");
    printf("        ,-'      /&&&%-'\n");
    printf("      ,' __  ,- {&&&&/\n");
    printf("     / ,'  \\|   |\\&&'\\\n");
    printf("    (       |   |' \\  `--.\n");
    printf("(%--'\\   ,--.\\   `-.`-._)))\n");
    printf(" `---'`-/__)))`-._)))\n\n");

    int count = 0;

    //Some delay before bouncing
    while (count < 10) {
        sleep(100000000);
        count++;
    }
    count = 0;
    while (true) {

        while (count < 5) {
            sleep(100000000);
            scrolldown();
            count++;
        }

        while (count < 10) {
            sleep(100000000);
            scrollup();
            count++;

        }

        if (count % 10 == 0) {
            count = 0;
        }

    }
    printf("Exiting...");


    return 0;
}
Esempio n. 10
0
void _start()
{
 scrollup(25);

  kY = 0;
	kattr = 0x4E;
	print("The kernel has started\n");

  while(1);
}
Esempio n. 11
0
File: tty.c Progetto: cosmos72/twin
INLINE void lf(void) {
    /* don't scroll if above bottom of scrolling region, or
     * if below scrolling region
     */
    if (Y+1 == Bottom)
	scrollup(Top, Bottom, 1);
    else if (Y < SizeY - 1) {
	Y++;
	Pos += SizeX;
	if (Pos >= Split) Pos -= Split - Base;
    }
    *Flags &= ~TTY_NEEDWRAP;
}
Esempio n. 12
0
void Console::WriteChar(char c)
{
	int t;
	switch(c)
	{
	case '\r':                         //-> carriage return
		m_xPos = 0;
		break;

	case '\n':                         // -> newline (with implicit cr)
		m_xPos = 0;
		m_yPos++;
		break;

	case 8:                            // -> backspace
		t = m_xPos + m_yPos * m_ScreenWidth;    // get linear address
		if(t > 0) t--;
									   // if not in home position, step back
		if(m_xPos > 0)
		{
			m_xPos--;
		}
		else if(m_yPos > 0)
		{
			m_yPos--;
			m_xPos = m_ScreenWidth - 1;
		}

		*(m_pVideoMemory + t) = ' ' | (m_Color << 8); // put space under the cursor
		break;

	default:						// -> all other characters
		if(c < ' ') break;				// ignore non printable ascii chars
		*(m_pVideoMemory + m_xPos + m_yPos * m_ScreenWidth) = c | (m_Color << 8);
		m_xPos++;							// step cursor one character
		if(m_xPos == m_ScreenWidth)			// to next line if required
		{
			m_xPos = 0;
			m_yPos++;
		}
		break;
	}

	if(m_yPos == m_ScreenHeight)			// the cursor moved off of the screen?
	{
		scrollup();					// scroll the screen up
		m_yPos--;						// and move the cursor back
	}
									// and finally, set the cursor
	MoveCursor(m_xPos+1, m_yPos);
}
Esempio n. 13
0
void kputch(u8int ch, u8int attr) {
	u8int* where = (u8int*)(vga_text_buffer.addr + 2*(vga_text_buffer.pos.row*vga_text_buffer.cols + vga_text_buffer.pos.col));
	*where = ch;
	*(where+1) = attr;
	vga_text_buffer.pos.col++;
	if(vga_text_buffer.pos.col >= vga_text_buffer.cols) {
		vga_text_buffer.pos.col=0;
		vga_text_buffer.pos.row++;
		if(vga_text_buffer.pos.row >= vga_text_buffer.rows) {
			vga_text_buffer.pos.row--;
			scrollup(vga_text_buffer);
		}
	}
}
Esempio n. 14
0
/*
 * Delete backwards. This is quite easy too, because it's all done with other
 * functions. Just move the cursor back, and delete forwards. Like delete
 * forward, this actually does a kill if presented with an argument. Bound to
 * both "RUBOUT" and "C-H".
 */
int
backdel(int f, int n)
{
    register int    s;

    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    if (n < 0)
      return (forwdel(f, -n));

    if(TERM_OPTIMIZE && curwp->w_dotp != curwp->w_bufp->b_linep){
	int l;
	
	if(worthit(&l) && curwp->w_doto == 0 &&
	   lback(curwp->w_dotp) != curwp->w_bufp->b_linep){
	    if(l == curwp->w_toprow)
	      scrollup(curwp, l+1, 1);
	    else if(llength(lback(curwp->w_dotp)) == 0)
	      scrollup(curwp, l-1, 1);
	    else
	      scrollup(curwp, l, 1);
	}
    }

    if (f != FALSE) {                       /* Really a kill.       */
	if ((lastflag&CFKILL) == 0)
	  kdelete();

	thisflag |= CFKILL;
    }

    if ((s=backchar(f, n)) == TRUE)
      s = ldelete((long) n, f ? kinsert : NULL);

    return (s);
}
Esempio n. 15
0
/* attr[0] is non-hilite attr, attr[1] is highlight attr */
void printmenuitem(const char *str,char* attr)
{
    char page = getdisppage();
    char row,col;
    int hlite=NOHLITE; // Initially no highlighting

    getpos(&row,&col,page);
    while ( *str ) {
      switch (*str) 
	{
	case '\b':
	  --col;
	  break;
	case '\n':
	  ++row;
	  break;
	case '\r':
	  col=0;
	  break;
	case BELL: // No Bell Char
	  break;
	case ENABLEHLITE: // Switch on highlighting
	  hlite = HLITE;
	  break;
	case DISABLEHLITE: // Turn off highlighting
	  hlite = NOHLITE;
	  break;
	default:
	  putch(*str, attr[hlite], page);
	  ++col;
	}
      if (col > getnumcols())
	{
	  ++row;
	  col=0;
	}
      if (row > getnumrows())
	{
	  scrollup();
	  row= getnumrows();
	}
      gotoxy(row,col,page);
      str++;
    }
}
Esempio n. 16
0
int putchar(char a )
{
  int color = 0x07;
	volatile char *video = (volatile char*)(video_vm);
  if(position>=ROW*COLUMN)
    scrollup(1);
  if(a=='\n')
  {
    position = ((position/80)+1)*80; 
    update_cursor(position/COLUMN, position%COLUMN);
    return 0;
  }
  *(video++ + 2*position) = a;
	*video++ = color;
  position++;
  update_cursor(position/COLUMN, position%COLUMN);
  return 1;
}
Esempio n. 17
0
/*
void con_putc(char ch)
{
	if(ch == '\n'){
		goto roll0;
	}
	*posn++ = ch;
	*posn++ = attr;
	px++;
	if(px == 80){
roll0:
		px = 0;
		if(py == 24)
			scrollup();
		else
			py++;
		posn = screen + (py*80+px)*2;
	}
}
*/
void con_puts(char *s)
{
    while(*s){
        if(*s == '\n'){
            s++;
            goto roll1;
        }
        *posn++ = *s++;
        *posn++ = attr;
        px++;
        if(px == 80){
          roll1:
            px = 0;
            if(py == 24)
                scrollup();
            else
                py++;
            posn = screen + (py*80+px)*2;
        }
    }
}
Esempio n. 18
0
/*
 * killtext - delete the line that the cursor is currently in.
 *	      a greatly pared down version of its former self.
 */
int
killtext(int f, int n)
{
    register int chunk;
    int		 opt_scroll = 0;

    if (curbp->b_mode&MDVIEW)		/* don't allow this command if  */
      return(rdonly());			/* we are in read only mode     */

    if ((lastflag&CFKILL) == 0)		/* Clear kill buffer if */
      kdelete();			/* last wasn't a kill.  */

    if(gmode & MDDTKILL){		/*  */
	if((chunk = llength(curwp->w_dotp) - curwp->w_doto) == 0){
	    chunk = 1;
	    if(TERM_OPTIMIZE)
	      opt_scroll = 1;
	}
    }
    else{
	gotobol(FALSE, 1);		/* wack from bol past newline */
	chunk = llength(curwp->w_dotp) + 1;
	if(TERM_OPTIMIZE)
	  opt_scroll = 1;
    }

    /* optimize what motion we can */
    if(opt_scroll && (curwp->w_dotp != curwp->w_bufp->b_linep)){
	int l;

	if(worthit(&l))
	  scrollup(curwp, l, 1);
    }

    thisflag |= CFKILL;
    return(ldelete((long) chunk, kinsert));
}
Esempio n. 19
0
/*
 * Delete forward. This is real easy, because the basic delete routine does
 * all of the work. Watches for negative arguments, and does the right thing.
 * If any argument is present, it kills rather than deletes, to prevent loss
 * of text if typed with a big argument. Normally bound to "C-D".
 */
int
forwdel(int f, int n)
{
    if (curbp->b_mode&MDVIEW)	/* don't allow this command if	*/
      return(rdonly());	/* we are in read only mode	*/

    if (n < 0)
      return (backdel(f, -n));

    if(TERM_OPTIMIZE && (curwp->w_dotp != curwp->w_bufp->b_linep)){
	int l;

	if(worthit(&l) && curwp->w_doto == llength(curwp->w_dotp))
	  scrollup(curwp, l+1, 1);
    }

    if (f != FALSE) {                       /* Really a kill.       */
	if ((lastflag&CFKILL) == 0)
	  kdelete();
	thisflag |= CFKILL;
    }

    return (ldelete((long) n, f ? kinsert : NULL));
}
Esempio n. 20
0
void sendout(char *ps,int hand,short coll)
{
int junk;
char *dp;
int dolen=(int)strlen(ps);
int lcount=0,offset=0;
long effects=0;
int eff[3],dist[5],cellw;
int chof=0,howmany=0;
BOOLEAN bd=FALSE;
if(hand==-1)return;
vst_font(ws.handle,(WORD)winfont);
vst_point(ws.handle,(WORD)winpoint,&junk,&junk,&junk,&junk);

dp=ps;
dolen=(int)strlen(ps);
eff[0]=0;
vst_effects(ws.handle,0);
while(offset<dolen){
vqt_width(ws.handle,*(dp+lcount),&cellw,&junk,&junk);
cellw=cellw+eff[0];

if(*(dp+lcount)==2){
cellw=0;
if(bd){bd=FALSE;eff[0]=0;}
else{bd=TRUE;
effects=THICKENED;
vst_effects(ws.handle,effects);
vqt_fontinfo(ws.handle,&junk,&junk,&dist[0],&junk,&eff[0]);
}
}
if(*(dp+lcount)==3)cellw=0;
if(*(dp+lcount)==15){cellw=0;bd=FALSE;eff[0]=0;}
if(*(dp+lcount)==22)cellw=0;
if(*(dp+lcount)==31)cellw=0;

chof=chof+cellw;

if(chof>wn[hand].wwa.g_w-NLW-1 || lcount>148){
wn[hand].clc[wn[hand].clcnt]=coll;
stccpy(wn[hand].cl[wn[hand].clcnt++],dp,lcount+1);
tlog(wn[hand].cl[wn[hand].clcnt-1]);
if(wn[hand].clcnt==150)wn[hand].clcnt=0;
cellw=0;chof=0;offset--;
dp=dp+lcount;
lcount=-1;
howmany++;
}
offset++;
lcount++;
}

if(strlen(dp)){
wn[hand].clc[wn[hand].clcnt]=coll;
stccpy(wn[hand].cl[wn[hand].clcnt++],dp,lcount+1);
tlog(wn[hand].cl[wn[hand].clcnt-1]);
if(wn[hand].clcnt==150)wn[hand].clcnt=0;
howmany++;
}

scrollup(hand,howmany);
}
Esempio n. 21
0
	void
normal()
{
	register u_char	c;
	long 			n;
	int				flag = FALSE;
	int 			type = 0;		/* used in some operations to modify type */
	int 			dir = FORWARD;	/* search direction */
	u_char			nchar = NUL;
	int				finish_op;
	linenr_t		Prenum1;
	char			searchbuff[CMDBUFFSIZE];		/* buffer for search string */
	FPOS			*pos;
	register char	*ptr;
	int				command_busy = FALSE;

	static linenr_t	redo_Quote_nlines;
	static int		redo_Quote_type;
	static long		redo_Quote_col;

	Prenum = 0;
	/*
	 * If there is an operator pending, then the command we take this time
	 * will terminate it. Finish_op tells us to finish the operation before
	 * returning this time (unless the operation was cancelled).
	 */
	finish_op = (operator != NOP);

	if (!finish_op && !yankbuffer)
		opnum = 0;

	if (vpeekc() == NUL || KeyTyped == TRUE)
		premsg(NUL, NUL);
	State = NORMAL_BUSY;
	c = vgetc();

	/* Pick up any leading digits and compute 'Prenum' */
	while ((c >= '1' && c <= '9') || (Prenum > 0 && (c == DEL || c == '0')))
	{
		if (c == DEL)
				Prenum /= 10;
		else
				Prenum = Prenum * 10 + (c - '0');
		premsg(' ', NUL);
		c = vgetc();
	}

	/*
	 * If we're in the middle of an operator (including after entering a yank
	 * buffer with ") AND we had a count before the
	 * operator, then that count overrides the current value of Prenum. What
	 * this means effectively, is that commands like "3dw" get turned into
	 * "d3w" which makes things fall into place pretty neatly.
	 * If you give a count before AND after the operator, they are multiplied.
	 */
	if (opnum != 0)
	{
			if (Prenum)
				Prenum *= opnum;
			else
				Prenum = opnum;
			opnum = 0;
	}

	Prenum1 = (Prenum == 0 ? 1 : Prenum);		/* Prenum often defaults to 1 */
	premsg(c, NUL);

	/*
	 * get an additional character if we need one
	 */
	if (strchr("@zZtTfF[]rm'`\"", c) || (c == 'v' && Recording == FALSE))
	{
		State = NOMAPPING;
		nchar = vgetc();		/* no macro mapping for this char */
		premsg(c, nchar);
	}
	flushbuf();			/* flush the premsg() characters onto the screen so we can
							see them while the command is being executed */

	if (c != 'z')	/* the 'z' command gets another character */
	{
		State = NORMAL;
		script_winsize_pp();
	}
	if (nchar == ESC)
	{
		CLEAROP;
		goto normal_end;
	}
	switch (c)
	{

/*
 * 0: Macros
 */
	  case 'v': 		/* (stop) recording into a named buffer */
		CHECKCLEAROP;
		if (!dorecord(nchar))
				CLEAROPBEEP;
		break;

	 case '@':			/* execute a named buffer */
		CHECKCLEAROP;
		while (Prenum1--)
			if (!doexecbuf(nchar))
			{
				CLEAROPBEEP;
				break;
			}
		break;

/*
 * 1: Screen positioning commands
 */
	  case CTRL('D'):
		flag = TRUE;

	  case CTRL('U'):
		CHECKCLEAROP;
		if (Prenum)
			p_scroll = (Prenum > Rows - 1) ? Rows - 1 : Prenum;
		n = (p_scroll < Rows) ? p_scroll : Rows - 1;
		if (flag)
		{
				scrollup(n);
				onedown(n);
		}
		else
		{
				scrolldown(n);
				oneup(n);
		}
		updateScreen(VALID);
		break;

	  case CTRL('B'):
	  case K_SUARROW:
		dir = BACKWARD;

	  case CTRL('F'):
	  case K_SDARROW:
		CHECKCLEAROP;
		onepage(dir, Prenum1);
		break;

	  case CTRL('E'):
		CHECKCLEAROP;
		scrollup(Prenum1);
		updateScreen(VALID);
		break;

	  case CTRL('Y'):
		CHECKCLEAROP;
		scrolldown(Prenum1);
		updateScreen(VALID);
		break;

	  case 'z':
		CHECKCLEAROP;
		if (isdigit(nchar))
		{
			/*
			 * we misuse some variables to be able to call premsg()
			 */
			operator = c;
			opnum = Prenum;
			Prenum = nchar - '0';
			for (;;)
			{
				premsg(' ', NUL);
				nchar = vgetc();
				State = NORMAL;
				script_winsize_pp();
				if (nchar == DEL)
					Prenum /= 10;
				else if (isdigit(nchar))
					Prenum = Prenum * 10 + (nchar - '0');
				else if (nchar == CR)
				{
					set_winsize((int)Columns, (int)Prenum, TRUE);
					break;
				}
				else
				{
					CLEAROPBEEP;
					break;
				}
			}
			operator = NOP;
			break;
		}

		if (Prenum)		/* line number given */
		{
			if (Prenum > line_count)
				Curpos.lnum = line_count;
			else
				Curpos.lnum = Prenum;
		}
		State = NORMAL;
		script_winsize_pp();
		switch (nchar)
		{
		  case NL:				/* put Curpos at top of screen */
		  case CR:
			Topline = Prenum;
			updateScreen(VALID);
			break;

		  case '.': 			/* put Curspos in middle of screen */
			n = Rows / 2;
			goto dozcmd;

		  case '-': 			/* put Curpos at bottom of screen */
			n = Rows - 1;
			/* FALLTHROUGH */

	dozcmd:
			{
				register linenr_t	lp = Prenum;
				register long		l = 0;

				while ((l < n) && (lp != 0))
				{
					l += plines(lp);
					Topline = lp;
					--lp;
				}
			}
			updateScreen(VALID);
			break;

		  default:
			CLEAROPBEEP;
		}
		break;

/*
 *	  2: Control commands
 */
	  case ':':
	    if (Quote.lnum)
			goto dooperator;
		CHECKCLEAROP;
		docmdline(NULL);
		break;

	  case K_HELP:
		CHECKCLEAROP;
		help();
		break;

	  case CTRL('L'):
		CHECKCLEAROP;
		updateScreen(CLEAR);
		break;

	  case CTRL('G'):
		CHECKCLEAROP;
		fileinfo();
		break;

	  case K_CCIRCM:			/* shorthand command */
		CHECKCLEAROPQ;
		if (getaltfile((int)Prenum, (linenr_t)0, TRUE))
			emsg(e_noalt);
		break;

	  case 'Z': 		/* write, if changed, and exit */
		CHECKCLEAROPQ;
		if (nchar != 'Z')
		{
			CLEAROPBEEP;
			break;
		}
		stuffReadbuff(":x\n");
		break;

	  case CTRL(']'):			/* :ta to current identifier */
		CHECKCLEAROPQ;
	  case '*': 				/* / to current identifier */
	  case '#': 				/* ? to current identifier */
	  case 'K':					/* run program for current identifier */
		{
			register int 	col;

			ptr = nr2ptr(Curpos.lnum);
			col = Curpos.col;

			/*
			 * skip to start of identifier.
			 */
			while (ptr[col] != NUL && !isidchar(ptr[col]))
				++col;

			/*
			 * Back up to start of identifier. This doesn't match the
			 * real vi but I like it a little better and it shouldn't bother
			 * anyone.
			 */
			while (col > 0 && isidchar(ptr[col - 1]))
				--col;

			if (!isidchar(ptr[col]))
			{
				CLEAROPBEEP;
				break;
			}

			if (Prenum)
				stuffnumReadbuff(Prenum);
			switch (c)
			{
				case '*':
					stuffReadbuff("/");
					break;
				case '#':
					stuffReadbuff("?");
					break;
				case 'K':
					stuffReadbuff(":! ");
					stuffReadbuff(p_kp);
					stuffReadbuff(" ");
					break;
				default:
					stuffReadbuff(":ta ");
			}

			/*
			 * Now grab the chars in the identifier
			 */
			while (isidchar(ptr[col]))
			{
				stuffReadbuff(mkstr(ptr[col]));
				++col;
			}
			stuffReadbuff("\n");
		}
		break;

	  case CTRL('T'):		/* backwards in tag stack */
			CHECKCLEAROPQ;
	  		dotag("", 2, (int)Prenum1);
			break;

/*
 * Cursor motions
 */
	  case 'G':
		mtype = MLINE;
		setpcmark();
		if (Prenum == 0 || Prenum > line_count)
				Curpos.lnum = line_count;
		else
				Curpos.lnum = Prenum;
		beginline(TRUE);
		break;

	  case 'H':
	  case 'M':
		if (c == 'M')
				n = Rows / 2;
		else
				n = Prenum;
		mtype = MLINE;
		Curpos.lnum = Topline;
		while (n && onedown((long)1))
				--n;
		beginline(TRUE);
		break;

	  case 'L':
		mtype = MLINE;
		Curpos.lnum = Botline - 1;
		for (n = Prenum; n && oneup((long)1); n--)
				;
		beginline(TRUE);
		break;

	  case 'l':
	  case K_RARROW:
	  case ' ':
		mtype = MCHAR;
		mincl = FALSE;
		n = Prenum1;
		while (n--)
		{
			if (!oneright())
			{
				if (operator == NOP)
					beep();
				else
				{
					if (lineempty(Curpos.lnum))
						CLEAROPBEEP;
					else
					{
						mincl = TRUE;
						if (n)
							beep();
					}
				}
				break;
			}
		}
		set_want_col = TRUE;
		break;

	  case 'h':
	  case K_LARROW:
	  case CTRL('H'):
	  case DEL:
		mtype = MCHAR;
		mincl = FALSE;
		n = Prenum1;
		while (n--)
		{
			if (!oneleft())
			{
				if (operator != DELETE && operator != CHANGE)
					beep();
				else if (Prenum1 == 1)
					CLEAROPBEEP;
				break;
			}
		}
		set_want_col = TRUE;
		break;

	  case '-':
		flag = TRUE;
		/* FALLTHROUGH */

	  case 'k':
	  case K_UARROW:
	  case CTRL('P'):
		mtype = MLINE;
		if (!oneup(Prenum1))
			CLEAROPBEEP;
		else if (flag)
			beginline(TRUE);
		break;

	  case '+':
	  case CR:
		flag = TRUE;
		/* FALLTHROUGH */

	  case 'j':
	  case K_DARROW:
	  case CTRL('N'):
	  case NL:
		mtype = MLINE;
		if (!onedown(Prenum1))
			CLEAROPBEEP;
		else if (flag)
			beginline(TRUE);
		break;

		/*
		 * This is a strange motion command that helps make operators more
		 * logical. It is actually implemented, but not documented in the
		 * real 'vi'. This motion command actually refers to "the current
		 * line". Commands like "dd" and "yy" are really an alternate form of
		 * "d_" and "y_". It does accept a count, so "d3_" works to delete 3
		 * lines.
		 */
	  case '_':
lineop:
		mtype = MLINE;
		if (!onedown((long)(Prenum1 - 1)))
			CLEAROPBEEP;
		else if (operator != YANK)	/* 'Y' does not move cursor */
			beginline(TRUE);
		break;

	  case '|':
		mtype = MCHAR;
		mincl = TRUE;
		beginline(FALSE);
		if (Prenum > 0)
			coladvance((colnr_t)(Prenum - 1));
		Curswant = Prenum - 1;
		break;

		/*
		 * Word Motions
		 */

	  case 'B':
		type = 1;
		/* FALLTHROUGH */

	  case 'b':
	  case K_SLARROW:
		mtype = MCHAR;
		mincl = FALSE;
		set_want_col = TRUE;
		if (bck_word(Prenum1, type))
			CLEAROPBEEP;
		break;

	  case 'E':
		type = 1;
		/* FALLTHROUGH */

	  case 'e':
		mincl = TRUE;
		goto dowrdcmd;

	  case 'W':
		type = 1;
		/* FALLTHROUGH */

	  case 'w':
	  case K_SRARROW:
		mincl = FALSE;
		flag = TRUE;
		/*
		 * This is a little strange. To match what the real vi does, we
		 * effectively map 'cw' to 'ce', and 'cW' to 'cE', provided that we are
		 * not on a space or a TAB. This seems
		 * impolite at first, but it's really more what we mean when we say
		 * 'cw'.
		 */
		if (operator == CHANGE && (n = gcharCurpos()) != ' ' && n != TAB &&
																n != NUL)
		{
			mincl = TRUE;
			flag = FALSE;
		}

dowrdcmd:
		mtype = MCHAR;
		set_want_col = TRUE;
		if (flag)
			n = fwd_word(Prenum1, type);
		else
			n = end_word(Prenum1, type, operator == CHANGE);
		if (n)
		{
			CLEAROPBEEP;
			break;
		}
		/*
		 * if we do a 'dw' for the last word in a line, we only delete the rest
		 * of the line, not joining the two lines.
		 */
		if (operator == DELETE && Prenum1 == 1 && startop.lnum != Curpos.lnum)
		{
				Curpos = startop;
				while (oneright())
					;
				mincl = TRUE;
		}
		break;

	  case '$':
		mtype = MCHAR;
		mincl = TRUE;
		Curswant = 29999;				/* so we stay at the end */
		if (!onedown((long)(Prenum1 - 1)))
		{
				CLEAROPBEEP;
				break;
		}
		if (Quote_block)
			updateScreen(NOT_VALID);
		break;

	  case '^':
		flag = TRUE;
		/* FALLTHROUGH */

	  case '0':
		mtype = MCHAR;
		mincl = TRUE;
		beginline(flag);
		break;

/*
 * 4: Searches
 */
	  case '?':
	  case '/':
		if (!getcmdline(c, (u_char *)searchbuff))
		{
				CLEAROP;
				break;
		}
		mtype = MCHAR;
		mincl = FALSE;
		set_want_col = TRUE;

		n = dosearch(c == '/' ? FORWARD : BACKWARD, searchbuff, FALSE, Prenum1);
		if (n == 0)
				CLEAROPBEEP;
		else if (n == 2)
				mtype = MLINE;
		break;

	  case 'N':
		flag = 1;

	  case 'n':
		mtype = MCHAR;
		mincl = FALSE;
		set_want_col = TRUE;
		if (!dosearch(0, NULL, flag, Prenum1))
			CLEAROPBEEP;
		break;

		/*
		 * Character searches
		 */
	  case 'T':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 't':
		type = 1;
		goto docsearch;

	  case 'F':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 'f':
docsearch:
		mtype = MCHAR;
		mincl = TRUE;
		set_want_col = TRUE;
		if (!searchc(nchar, dir, type, Prenum1))
		{
			CLEAROPBEEP;
		}
		break;

	  case ',':
		flag = 1;
		/* FALLTHROUGH */

	  case ';':
	    dir = flag;
	    goto docsearch;		/* nchar == NUL, thus repeat previous search */

		/*
		 * section or C function searches
		 */

	  case '[':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case ']':
		mtype = MLINE;
		set_want_col = TRUE;
		flag = '{';
		if (nchar != c)
		{
			if (nchar == '[' || nchar == ']')
				flag = '}';
			else
			{
				CLEAROPBEEP;
				break;
			}
		}
		if (dir == FORWARD && operator != NOP)	/* e.g. y]] searches for '}' */
			flag = '}';
		if (!findpar(dir, Prenum1, flag))
		{
			CLEAROPBEEP;
		}
		break;

	  case '%':
		mincl = TRUE;
	    if (Prenum)		/* {cnt}% : goto {cnt} percentage in file */
		{
			if (Prenum > 100)
				CLEAROPBEEP;
			else
			{
				mtype = MLINE;
				setpcmark();
				Curpos.lnum = line_count * Prenum / 100;
				Curpos.col = 0;
			}
		}
		else			/* % : go to matching paren */
		{
			mtype = MCHAR;
			if ((pos = showmatch()) == NULL)
				CLEAROPBEEP;
			else
			{
				setpcmark();
				Curpos = *pos;
				set_want_col = TRUE;
			}
		}
		break;

	  case '(':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case ')':
		mtype = MCHAR;
		if (c == ')')
			mincl = FALSE;
		else
			mincl = TRUE;
		set_want_col = TRUE;

		if (!findsent(dir, Prenum1))
			CLEAROPBEEP;
		break;

	  case '{':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case '}':
		mtype = MCHAR;
		mincl = FALSE;
		set_want_col = TRUE;

		if (!findpar(dir, Prenum1, NUL))
			CLEAROPBEEP;
		break;

/*
 * 5: Edits
 */
	  case '.':
		CHECKCLEAROPQ;
		if (!start_redo(Prenum))
			CLEAROPBEEP;
		break;

	  case 'u':
	    if (Quote.lnum)
			goto dooperator;
	  case K_UNDO:
		CHECKCLEAROPQ;
		u_undo((int)Prenum1);
		set_want_col = TRUE;
		break;

	  case CTRL('R'):
		CHECKCLEAROPQ;
	  	u_redo((int)Prenum1);
		set_want_col = TRUE;
		break;

	  case 'U':
	    if (Quote.lnum)
			goto dooperator;
		CHECKCLEAROPQ;
		u_undoline();
		set_want_col = TRUE;
		break;

	  case 'r':
	    if (Quote.lnum)
		{
			c = 'c';
			goto dooperator;
		}
		CHECKCLEAROPQ;
		n = strlen(nr2ptr(Curpos.lnum)) - Curpos.col;
		if (n < Prenum1)			/* not enough characters to replace */
		{
			CLEAROPBEEP;
			break;
		}

		prep_redo(Prenum1, 'r', NUL, nchar);
		stuffnumReadbuff(Prenum1);
		stuffReadbuff("R");
		stuffReadbuff(mkstr(nchar));
		stuffReadbuff("\033");
		break;

	  case 'J':
	    if (Quote.lnum)		/* join the quoted lines */
		{
			if (Curpos.lnum > Quote.lnum)
			{
				Prenum = Curpos.lnum - Quote.lnum + 1;
				Curpos.lnum = Quote.lnum;
			}
			else
				Prenum = Quote.lnum - Curpos.lnum + 1;
			Quote.lnum = 0;
		}
		CHECKCLEAROP;
		if (Prenum <= 1)
				Prenum = 2; 	/* default for join is two lines! */
		if (Curpos.lnum + Prenum - 1 > line_count)	/* beyond last line */
		{
			CLEAROPBEEP;
			break;
		}

		prep_redo(Prenum, 'J', NUL, NUL);
		dodojoin(Prenum, TRUE, TRUE);
		break;

	  case 'P':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 'p':
		CHECKCLEAROPQ;
		prep_redo(Prenum, c, NUL, NUL);
		doput(dir, Prenum1);
		break;

	  case CTRL('A'):			/* add to number */
	  case CTRL('S'):			/* subtract from number */
		CHECKCLEAROPQ;
		{
			register int 	col;
			char			buf[30];
			int				hex;		/* 'x' or 'X': hexadecimal; '0': octal */
			static int		hexupper = FALSE;	/* 0xABC */

			ptr = nr2ptr(Curpos.lnum);
			col = Curpos.col;

				/* first check if we are on a hexadecimal number */
			while (col > 0 && isxdigit(ptr[col]))
				--col;
			if (col > 0 && toupper(ptr[col]) == 'X' && ptr[col - 1] == '0' && isxdigit(ptr[col + 1]))
				--col;		/* found hexadecimal number */
			else
			{
				/* first search forward and then backward for start of number */
				col = Curpos.col;

				while (ptr[col] != NUL && !isdigit(ptr[col]))
					++col;

				while (col > 0 && isdigit(ptr[col - 1]))
					--col;
			}

			if (isdigit(ptr[col]) && u_saveCurpos())
			{
				set_want_col = TRUE;
				prep_redo(Prenum1, c, NUL, NUL);

				if (ptr[col] != '0')
					hex = 0;				/* decimal */
				else
				{
					hex = toupper(ptr[col + 1]);		/* assume hexadecimal */
					if (hex != 'X' || !isxdigit(ptr[col + 2]))
					{
						if (isdigit(hex))
							hex = '0';		/* octal */
						else
							hex = 0;		/* 0 by itself is decimal */
					}
				}

				if (!hex && col > 0 && ptr[col - 1] == '-')
					--col;

				ptr += col;
				if (hex == '0')
					sscanf(ptr, "%lo", &n);
				else if (hex)
					sscanf(ptr, "%lx", &n);	/* "%X" doesn't work! */
				else
					n = atol(ptr);

				if (c == CTRL('A'))
					n += Prenum1;
				else
					n -= Prenum1;

				if (hex == 'X')					/* skip the '0x' */
					col += 2;
				Curpos.col = col;
				do								/* delete the old number */
				{
					if (isalpha(c))
					{
						if (isupper(c))
							hexupper = TRUE;
						else
							hexupper = FALSE;
					}
					delchar(FALSE);
					c = gcharCurpos();
				}
				while (hex ? (hex == '0' ? c >= '0' && c <= '7' : isxdigit(c)) : isdigit(c));

				if (hex == '0')
					sprintf(buf, "0%lo", n);
				else if (hexupper)
					sprintf(buf, "%lX", n);
				else if (hex)
					sprintf(buf, "%lx", n);
				else
					sprintf(buf, "%ld", n);
				insstr(buf);					/* insert the new number */
				--Curpos.col;
				updateline();
			}
			else
				beep();
		}
		break;

/*
 * 6: Inserts
 */
	  case 'A':
		set_want_col = TRUE;
		while (oneright())
				;
		/* FALLTHROUGH */

	  case 'a':
		CHECKCLEAROPQ;
		/* Works just like an 'i'nsert on the next character. */
		if (u_saveCurpos())
		{
			if (!lineempty(Curpos.lnum))
				incCurpos();
			startinsert(c, FALSE, Prenum1);
			command_busy = TRUE;
		}
		break;

	  case 'I':
		beginline(TRUE);
		/* FALLTHROUGH */

	  case 'i':
		CHECKCLEAROPQ;
		if (u_saveCurpos())
		{
			startinsert(c, FALSE, Prenum1);
			command_busy = TRUE;
		}
		break;

	  case 'o':
	  	if (Quote.lnum)	/* switch start and end of quote */
		{
			Prenum = Quote.lnum;
			Quote.lnum = Curpos.lnum;
			Curpos.lnum = Prenum;
			n = Quote.col;
			Quote.col = Curpos.col;
			Curpos.col = n;
			break;
		}
		CHECKCLEAROP;
		if (u_save(Curpos.lnum, (linenr_t)(Curpos.lnum + 1)) && Opencmd(FORWARD, TRUE))
		{
			startinsert('o', TRUE, Prenum1);
			command_busy = TRUE;
		}
		break;

	  case 'O':
		CHECKCLEAROPQ;
		if (u_save((linenr_t)(Curpos.lnum - 1), Curpos.lnum) && Opencmd(BACKWARD, TRUE))
		{
			startinsert('O', TRUE, Prenum1);
			command_busy = TRUE;
		}
		break;

	  case 'R':
	    if (Quote.lnum)
		{
			c = 'c';
			Quote.col = QUOTELINE;
			goto dooperator;
		}
		CHECKCLEAROPQ;
		if (u_saveCurpos())
		{
			startinsert('R', FALSE, Prenum1);
			command_busy = TRUE;
		}
		break;

/*
 * 7: Operators
 */
	  case '~': 		/* swap case */
	  /*
	   * if tilde is not an operator and Quoting is off: swap case
	   * of a single character
	   */
		if (!p_to && !Quote.lnum)
		{
			CHECKCLEAROPQ;
			if (lineempty(Curpos.lnum))
			{
				CLEAROPBEEP;
				break;
			}
			prep_redo(Prenum, '~', NUL, NUL);

			if (!u_saveCurpos())
				break;

			for (; Prenum1 > 0; --Prenum1)
			{
				if (gcharCurpos() == NUL)
					break;
				swapchar(&Curpos);
				incCurpos();
			}

			set_want_col = TRUE;
			CHANGED;
			updateline();
			break;
		}
		/*FALLTHROUGH*/

	  case 'd':
	  case 'c':
	  case 'y':
	  case '>':
	  case '<':
	  case '!':
	  case '=':
	  case 'V':
dooperator:
		n = strchr(opchars, c) - opchars + 1;
		if (n == operator)		/* double operator works on lines */
			goto lineop;
		CHECKCLEAROP;
		if (Prenum != 0)
			opnum = Prenum;
		startop = Curpos;
		operator = n;
		break;

/*
 * 8: Abbreviations
 */

	 /* when quoting the next commands are operators */
	  case 'S':
	  case 'Y':
	  case 'D':
	  case 'C':
	  case 'x':
	  case 'X':
	  case 's':
	  	if (Quote.lnum)
		{
			static char trans[] = "ScYyDdCcxdXdsc";

			if (isupper(c))			/* uppercase means linewise */
				Quote.col = QUOTELINE;
			c = *(strchr(trans, c) + 1);
			goto dooperator;
		}

	  case '&':
		CHECKCLEAROPQ;
		if (Prenum)
			stuffnumReadbuff(Prenum);

		if (c == 'S')
		{
			beginline((int)p_ai);
			substituting = TRUE;
		}
		else if (c == 'Y' && p_ye)
			c = 'Z';
		{
				static char *(ar[9]) = {"dl", "dh", "d$", "c$", "cl", "c$", "yy", "y$", ":s\r"};
				static char *str = "xXDCsSYZ&";

				stuffReadbuff(ar[strchr(str, c) - str]);
		}
		break;

/*
 * 9: Marks
 */

	  case 'm':
		CHECKCLEAROP;
		if (!setmark(nchar))
			CLEAROPBEEP;
		break;

	  case '\'':
		flag = TRUE;
		/* FALLTHROUGH */

	  case '`':
		pos = getmark(nchar, (operator == NOP));
		if (pos == (FPOS *)-1)	/* jumped to other file */
		{
			if (flag)
				beginline(TRUE);
			break;
		}

		if (pos != NULL)
			setpcmark();

cursormark:
		if (pos == NULL)
			CLEAROPBEEP;
		else
		{
			Curpos = *pos;
			if (flag)
				beginline(TRUE);
		}
		mtype = flag ? MLINE : MCHAR;
		mincl = FALSE;		/* ignored if not MCHAR */
		set_want_col = TRUE;
		break;

	case CTRL('O'):			/* goto older pcmark */
		Prenum1 = -Prenum1;
		/* FALLTHROUGH */

	case CTRL('I'):			/* goto newer pcmark */
		CHECKCLEAROPQ;
		pos = movemark((int)Prenum1);
		if (pos == (FPOS *)-1)	/* jump to other file */
		{
			set_want_col = TRUE;
			break;
		}
		goto cursormark;

/*
 * 10. Buffer setting
 */
	  case '"':
		CHECKCLEAROP;
		if (isalnum(nchar) || nchar == '.')
		{
			yankbuffer = nchar;
			opnum = Prenum;		/* remember count before '"' */
		}
		else
			CLEAROPBEEP;
		break;

/*
 * 11. Quoting
 */
 	  case 'q':
	  case 'Q':
	  case CTRL('Q'):
		CHECKCLEAROP;
		Quote_block = FALSE;
		if (Quote.lnum)					/* stop quoting */
		{
			Quote.lnum = 0;
			updateScreen(NOT_VALID);	/* delete the inversion */
		}
		else							/* start quoting */
		{
			Quote = Curpos;
			if (c == 'Q')				/* linewise */
				Quote.col = QUOTELINE;
			else if (c == CTRL('Q'))	/* blockwise */
				Quote_block = TRUE;
			updateline();				/* start the inversion */
		}
		break;

/*
 * 12. Suspend
 */

 	case CTRL('Z'):
		CLEAROP;
		Quote.lnum = 0;					/* stop quoting */
		stuffReadbuff(":st!\r");		/* no autowrite */
		break;

/*
 * The end
 */
	  case ESC:
	    if (Quote.lnum)
		{
			Quote.lnum = 0;			/* stop quoting */
			updateScreen(NOT_VALID);
		}

	  default:					/* not a known command */
		CLEAROPBEEP;
		break;

	}	/* end of switch on command character */

/*
 * if we didn't start or finish an operator, reset yankbuffer, unless we
 * need it later.
 */
	if (!finish_op && !operator && strchr("\"DCYSsXx", c) == NULL)
		yankbuffer = 0;

	/*
	 * If an operation is pending, handle it...
	 */
	if ((Quote.lnum || finish_op) && operator != NOP)
	{
		if (operator != YANK && !Quote.lnum)		/* can't redo yank */
		{
				prep_redo(Prenum, opchars[operator - 1], c, nchar);
				if (c == '/' || c == '?')		/* was a search */
				{
						AppendToRedobuff(searchbuff);
						AppendToRedobuff(NL_STR);
				}
		}

		if (redo_Quote_busy)
		{
			startop = Curpos;
			Curpos.lnum += redo_Quote_nlines - 1;
			switch (redo_Quote_type)
			{
			case 'Q':	Quote.col = QUOTELINE;
						break;

			case CTRL('Q'):
						Quote_block = TRUE;
						break;

			case 'q':		
						if (redo_Quote_nlines <= 1)
							Curpos.col += redo_Quote_col;
						else
							Curpos.col = redo_Quote_col;
						break;
			}
			if (redo_Quote_col == 29999)
			{
				Curswant = 29999;
				coladvance(29999);
			}
		}
		else if (Quote.lnum)
			startop = Quote;


		if (lt(startop, Curpos))
		{
			endop = Curpos;
			Curpos = startop;
		}
		else
		{
			endop = startop;
			startop = Curpos;
		}
		nlines = endop.lnum - startop.lnum + 1;

		if (Quote.lnum || redo_Quote_busy)
		{
			if (Quote_block)				/* block mode */
			{
				startvcol = getvcol(&startop, 2);
				n = getvcol(&endop, 2);
				if (n < startvcol)
					startvcol = n;

			/* if '$' was used, get endvcol from longest line */
				if (Curswant == 29999)
				{
					Curpos.col = 29999;
					endvcol = 0;
					for (Curpos.lnum = startop.lnum; Curpos.lnum <= endop.lnum; ++Curpos.lnum)
						if ((n = getvcol(&Curpos, 3)) > endvcol)
							endvcol = n;
					Curpos = startop;
				}
				else if (redo_Quote_busy)
					endvcol = startvcol + redo_Quote_col;
				else
				{
					endvcol = getvcol(&startop, 3);
					n = getvcol(&endop, 3);
					if (n > endvcol)
						endvcol = n;
				}
				coladvance(startvcol);
			}

	/*
	 * prepare to redo quoting: this is based on the size
	 * of the quoted text
	 */
			if (operator != YANK)		/* can't redo yank */
			{
				prep_redo(0L, 'q', opchars[operator - 1], NUL);
				if (Quote_block)
					redo_Quote_type = CTRL('Q');
				else if (Quote.col == QUOTELINE)
					redo_Quote_type = 'Q';
				else
					redo_Quote_type = 'q';
				if (Curswant == 29999)
					redo_Quote_col = 29999;
				else if (Quote_block)
					redo_Quote_col = endvcol - startvcol;
				else if (nlines > 1)
					redo_Quote_col = endop.col;
				else
					redo_Quote_col = endop.col - startop.col;
				redo_Quote_nlines = nlines;
			}

			mincl = TRUE;
			if (Quote.col == QUOTELINE)
				mtype = MLINE;
			else
				mtype = MCHAR;

			redo_Quote_busy = FALSE;
			/*
			 * Switch quoting off now, so screen updating does
			 * not show inverted text when the screen is redrawn.
			 * With YANK and sometimes with COLON there is no screen redraw, so
			 * it is done here to remove the inverted part.
			 */
			Quote.lnum = 0;
			if (operator == YANK || operator == COLON)
				updateScreen(NOT_VALID);
		}

		set_want_col = 1;
		if (!mincl && !equal(startop, endop))
			oneless = 1;
		else
			oneless = 0;

		switch (operator)
		{
		  case LSHIFT:
		  case RSHIFT:
			adjust_lnum();
			doshift(operator);
			break;

		  case DELETE:
			dodelete();
			break;

		  case YANK:
			doyank(FALSE);
			break;

		  case CHANGE:
			dochange();
			break;

		  case FILTER:
			AppendToRedobuff("!\n");	/* strange but necessary */

		  case INDENT:
		  case COLON:
			adjust_lnum();
			sprintf(IObuff, ":%ld,%ld", (long)startop.lnum, (long)endop.lnum);
			stuffReadbuff(IObuff);
			if (operator != COLON)
				stuffReadbuff("!");
			if (operator == INDENT)
			{
				stuffReadbuff(p_ep);
				stuffReadbuff("\n");
			}
				/*	docmdline() does the rest */
			break;

		  case TILDE:
		  case UPPER:
		  case LOWER:
			dotilde();
			break;

		  case FORMAT:
			adjust_lnum();
			doformat();
			break;

		  default:
			CLEAROPBEEP;
		}
		operator = NOP;
		Quote_block = FALSE;
		yankbuffer = 0;
	}

normal_end:
	premsg(-1, NUL);
	if (restart_edit && operator == NOP && Quote.lnum == 0 && !command_busy && stuff_empty() && yankbuffer == 0)
		startinsert(NUL, FALSE, 1L);
}
Esempio n. 22
0
File: tty.c Progetto: cosmos72/twin
INLINE void delete_line(ldat nr) {
   scrollup(Y, Bottom, nr);
   *Flags &= ~TTY_NEEDWRAP;
}
Esempio n. 23
0
File: screen.c Progetto: kindy/vim0
void
cursupdate()
{
        LPTR *p;
        int inc, c, nlines;
        int i;
        int didinc;

        if (bufempty()) {                /* special case - file is empty */
                *Topchar  = *Filemem;
                *Curschar = *Filemem;
        } else if ( LINEOF(Curschar) < LINEOF(Topchar) ) {
                nlines = cntllines(Curschar,Topchar);
                /* if the cursor is above the top of */
                /* the screen, put it at the top of the screen.. */
                *Topchar = *Curschar;
                Topchar->index = 0;
                /* ... and, if we weren't very close to begin with, */
                /* we scroll so that the line is close to the middle. */
                if ( nlines > Rows/3 ) {
                        for (i=0, p = Topchar; i < Rows/3 ;i++, *Topchar = *p)
                                if ((p = prevline(p)) == NULL)
                                        break;
                } else
                        s_ins(0, nlines-1);
                updatescreen();
        }
        else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
                nlines = cntllines(Botchar,Curschar);
                /* If the cursor is off the bottom of the screen, */
                /* put it at the top of the screen.. */
                /* ... and back up */
                if ( nlines > Rows/3 ) {
                        p = Curschar;
                        for (i=0; i < (2*Rows)/3 ;i++)
                                if ((p = prevline(p)) == NULL)
                                        break;
                        *Topchar = *p;
                } else {
                        scrollup(nlines);
                }
                updatescreen();
        }

        Cursrow = Curscol = Cursvcol = 0;
        for ( p=Topchar; p->linep != Curschar->linep ;p = nextline(p) )
                Cursrow += plines(p);

        Cline_row = Cursrow;
        Cline_size = plines(p);

        for (i=0; i <= Curschar->index ;i++) {
                c = Curschar->linep->s[i];
                /* A tab gets expanded, depending on the current column */
                if ( c == TAB && !P(P_LS) )
                        inc = P(P_TS) - (Curscol % P(P_TS));
                else
                        inc = chars[(unsigned)(c & 0xff)].ch_size;
                Curscol += inc;
                Cursvcol += inc;
                if ( Curscol >= Columns ) {
                        Curscol -= Columns;
                        Cursrow++;
                        didinc = TRUE;
                }
                else
                        didinc = FALSE;
        }
        if (didinc)
                Cursrow--;

        if (c == TAB && State == NORMAL && !P(P_LS)) {
                Curscol--;
                Cursvcol--;
        } else {
                Curscol -= inc;
                Cursvcol -= inc;
        }
        if (Curscol < 0)
                Curscol += Columns;

        if (set_want_col) {
                Curswant = Cursvcol;
                set_want_col = FALSE;
        }
}
Esempio n. 24
0
static void enemy_tag_loop() {
	update_caption = tag_update_caption;
	tag_enemy_current_route = 0;
	tag_enemy_current_shot = 0;
	tag_enemy_spawnline = map_spawn_line;
	tag_enemy_y = 0;
	tag_enemy_upscrolled = 0;
	reset_tag_enemy();
	tag_enemy_id = init_enemy(&tag_enemy);
	
	SDL_Event sdl_event;
	while(1) {
		if(!obj_slot_used[tag_enemy_id]) update_tag_enemy(0);
			//tag_enemy_id = init_enemy(&tag_enemy);
		unsigned need_redraw = 1;
		while (SDL_PollEvent(&sdl_event)) {
			need_redraw = 0;
			int dir = -1;
			switch (sdl_event.type) {
				case SDL_KEYUP:
					switch(sdl_event.key.keysym.sym) {
						case SDLK_e: dump_enemy(); return;
						case SDLK_g: toggle_gun(); break;
						case SDLK_d: enter_direction(); break;
						case SDLK_i: insert_steps(); break;
						case SDLK_s: insert_shot(); break;
						case SDLK_p: do_pause(); break;
						case SDLK_c: clear_screen(); video_update(); need_redraw = 1; break;
						case SDLK_SPACE: update_tag_enemy(1); break;
						case SDLK_PAGEUP: scrollup(); break;
						case SDLK_KP_PLUS:
							dir = 1;
						case SDLK_KP_MINUS:
							if((sdl_event.key.keysym.mod & KMOD_RSHIFT) ||
							   (sdl_event.key.keysym.mod & KMOD_LSHIFT))
								toggle_shape(dir);
							else
							if((sdl_event.key.keysym.mod & KMOD_RALT) ||
							   (sdl_event.key.keysym.mod & KMOD_LALT))
								toggle_route(dir);
							else
							if((sdl_event.key.keysym.mod & KMOD_RCTRL) ||
							   (sdl_event.key.keysym.mod & KMOD_LCTRL))
								toggle_shot(dir);
							else
								toggle_vel(dir);
							break;
						default: break;
					}
				case SDL_KEYDOWN:
					switch(sdl_event.key.keysym.sym) {
						case SDLK_RIGHT: dir = 1;
						case SDLK_LEFT:
							if((sdl_event.key.keysym.mod & KMOD_RSHIFT) ||
							   (sdl_event.key.keysym.mod & KMOD_LSHIFT)) dir *= 4;
							tag_enemy.x += dir;
							update_tag_enemy(1);
							break;
						case SDLK_DOWN:
							dir = 1;
						case SDLK_UP:
							if((sdl_event.key.keysym.mod & KMOD_RSHIFT) ||
							   (sdl_event.key.keysym.mod & KMOD_LSHIFT)) dir *= 4;
							tag_enemy_y += dir;
							update_tag_enemy(1);
							break;
						default: ;
					}
				break;
				default: ;
			}
		}
		game_tick(need_redraw);
	}
}
Esempio n. 25
0
/* Delete lines */
void dell(void)
{
    if(y>=stop && y<=sbot) scrollup(y,sbot,parry[0]);
}
Esempio n. 26
0
/* Linefeed */
void lf(void)
{
    if(y==sbot) scrollup(stop,sbot,1);
    else parry[0]=0, down();
}
Esempio n. 27
0
File: s3dtv.c Progetto: koo5/lemon-2
static int keypress(struct s3d_evt *event)
{
    struct s3d_key_event *keys = (struct s3d_key_event *)event->buf;
    int key=keys->keysym;
    int mod=keys->modifier;
    if (mod&S3D_KMOD_RSHIFT)
    {
        switch (key)
        {
        case S3DK_INSERT:
            clip(mod&S3D_KMOD_RCTRL);
        }
    }

    if (mod&S3D_KMOD_RCTRL)
    {
        switch (key)
        {
        case S3DK_F5:
            wdt-=0.1;
            dirty=1;
            break;
        case S3DK_F6:
            wdt+=0.1;
            dirty=1;
            break;
        case S3DK_F7:
            afterlife=!afterlife;
            break;
        case S3DK_F8:
            loadl2("l2");
            dirty=1;
            break;
        case S3DK_F12:
            dirty=1;
            showhex=!showhex;
            printf("showhex=!showhex;\n");
            break;
        case S3DK_F10:
            dirty=1;
            ok=!ok;
            printf("ok\n");
            break;
        case S3DK_END:
            resizooo(t, 0,1);
            break;
        case S3DK_HOME:
            resizooo(t, 0,-1);
            break;
        case S3DK_DELETE:
            resizooo(t, -1,0);
            break;
        case S3DK_PAGEDOWN:
            resizooo(t, 1,0);
            break;
        }
    }
    else if (mod&S3D_KMOD_RALT)
    {
        switch (key)
        {
        case S3DK_END:
            resizooo(t, 0,100);
            break;
        case S3DK_HOME:
            resizooo(t, 0,-100);
            break;
        case S3DK_DELETE:
            resizooo(t, -100,0);
            break;
        case S3DK_PAGEDOWN:
            resizooo(t, 100,0);
            break;
        }
    }
    else
    {
        if ( (key == S3DK_F1) )
            {    }
        else

            if ( (key >= S3DK_F1) && (key <= S3DK_F15) )
            {
                char *k;
                if (asprintf(&k ,"kf%i", key-S3DK_F1+1)!=-1)
                {
                    rote_vt_terminfo(t, k);
                    free(k);
                }
            }
            else if ( (key == S3DK_SPACE) )
                keyp(t,32);
            else if ( (key == S3DK_BACKSPACE) )
                rote_vt_terminfo(t, "kbs");
            else if ( (key == S3DK_ESCAPE) )
                keyp(t,27);
            else if ( (key == S3DK_LEFT) )
                rote_vt_terminfo(t, "kcub1");
            else if ( (key == S3DK_RIGHT) )
                rote_vt_terminfo(t, "kcuf1");
            else if ( (key == S3DK_UP) )
                rote_vt_terminfo(t, "kcuu1");
            else if ( (key == S3DK_DOWN) )
                rote_vt_terminfo(t, "kcud1");
            else if ( (key == S3DK_END) )
                rote_vt_terminfo(t, "kend");
            else if ( (key == S3DK_HOME) )
                rote_vt_terminfo(t, "khome");
            else if ( (key == S3DK_DELETE) )
                rote_vt_terminfo(t, "kdch1");
            else if ( (key == S3DK_PAGEDOWN) )
                rote_vt_terminfo(t, "knp");
            else if ( (key == S3DK_INSERT) )
                rote_vt_terminfo(t, "kich1");
            else if ( (key == S3DK_PAGEUP) )
                if (mod&S3D_KMOD_RSHIFT)
                    scrollup();
                else
                    rote_vt_terminfo(t, "kpp");
            else if ( (key == S3DK_RETURN) )
            {
                if (mod&(S3D_KMOD_RSHIFT|S3D_KMOD_LSHIFT))
                    keyp(t,10);
                else
                    keyp(t,13);
            }
            else if (mod&(S3D_KMOD_RALT|S3D_KMOD_LALT))
            {
                char x[2];

                x[0]=27;
                x[1]=keys->keysym;
                rote_vt_write(t, &x[0], 2);//thx twkm

            }
            else
            {
                if ( (key==S3DK_LSHIFT)||(key==S3DK_RSHIFT))
                {
                    globmousecopying=!keys->state;
                }
                else
                {
                    keyp(t, keys->unicode);
//					    	printf("%c, %i\n",  keys->keysym,  keys->unicode);
                }
            }
    }
}
Esempio n. 28
0
	void
normal()
{
	register int	c;
	long 			n;
	int				flag = FALSE;
	int				flag2 = FALSE;
	int 			type = 0;				/* type of operation */
	int 			dir = FORWARD;			/* search direction */
	int				nchar = NUL;
	int				finish_op;
	linenr_t		Prenum1;
	char_u			searchbuff[CMDBUFFSIZE];/* buffer for search string */
	FPOS			*pos = NULL;			/* init for gcc */
	register char_u	*ptr;
	int				command_busy = FALSE;
	static int		didwarn = FALSE;		/* warned for broken inversion */
	int				modified = FALSE;		/* changed current buffer */
	int				ctrl_w = FALSE;			/* got CTRL-W command */

		/* the visual area is remembered for reselection */
	static linenr_t	resel_Visual_nlines;		/* number of lines */
	static int		resel_Visual_type = 0;	/* type 'v', 'V' or CTRL-V */
	static colnr_t	resel_Visual_col;		/* number of columns or end column */
		/* the visual area is remembered for redo */
	static linenr_t	redo_Visual_nlines;		/* number of lines */
	static int		redo_Visual_type = 0;	/* type 'v', 'V' or CTRL-V */
	static colnr_t	redo_Visual_col;		/* number of columns or end column */
	static long		redo_Visual_Prenum;		/* Prenum for operator */

	Prenum = 0;
	/*
	 * If there is an operator pending, then the command we take this time
	 * will terminate it. Finish_op tells us to finish the operation before
	 * returning this time (unless the operation was cancelled).
	 */
	finish_op = (operator != NOP);

	if (!finish_op && !yankbuffer)
		opnum = 0;

	if (p_sc && (vpeekc() == NUL || KeyTyped == TRUE))
		premsg(NUL, NUL);
	State = NORMAL_BUSY;
	c = vgetc();

getcount:
	/* Pick up any leading digits and compute 'Prenum' */
	while ((c >= '1' && c <= '9') || (Prenum != 0 && (c == DEL || c == '0')))
	{
		if (c == DEL)
				Prenum /= 10;
		else
				Prenum = Prenum * 10 + (c - '0');
		if (Prenum < 0)			/* got too large! */
			Prenum = 999999999;
		premsg(ctrl_w ? Ctrl('W') : ' ', NUL);
		c = vgetc();
	}

/*
 * If we got CTRL-W there may be a/another count
 */
	if (c == Ctrl('W') && !ctrl_w)
	{
		ctrl_w = TRUE;
		opnum = Prenum;						/* remember first count */
		Prenum = 0;
		State = ONLYKEY;					/* no mapping for nchar, but keys */
		premsg(c, NUL);
		c = vgetc();						/* get next character */
		goto getcount;						/* jump back */
	}

	/*
	 * If we're in the middle of an operator (including after entering a yank
	 * buffer with ") AND we had a count before the
	 * operator, then that count overrides the current value of Prenum. What
	 * this means effectively, is that commands like "3dw" get turned into
	 * "d3w" which makes things fall into place pretty neatly.
	 * If you give a count before AND after the operator, they are multiplied.
	 */
	if (opnum != 0)
	{
			if (Prenum)
				Prenum *= opnum;
			else
				Prenum = opnum;
			opnum = 0;
	}

	Prenum1 = (Prenum == 0 ? 1 : Prenum);		/* Prenum often defaults to 1 */
	premsg(c, NUL);

	/*
	 * get an additional character if we need one
	 * for CTRL-W we already got it when looking for a count
	 */
	if (ctrl_w)
	{
		nchar = c;
		c = Ctrl('W');
		premsg(c, nchar);
	}
	else if (strchr("@zZtTfF[]mg'`\"", c) || (c == 'q' && !Recording && !Exec_reg) ||
										(c == 'r' && !VIsual.lnum))
	{
		State = NOMAPPING;
		nchar = vgetc();		/* no macro mapping for this char */
		premsg(c, nchar);
	}
	if (p_sc)
		flushbuf();		/* flush the premsg() characters onto the screen so we can
							see them while the command is being executed */

/*
 * For commands that don't get another character we can put the State back to
 * NORMAL and check for a window size change.
 */
	if (STRCHR("z:/?", c) == NULL)
		State = NORMAL;
	if (nchar == ESC)
	{
		CLEAROP;
		goto normal_end;
	}
	switch (c)
	{

/*
 * 0: Macros
 */
	  case 'q': 		/* (stop) recording into a named register */
		CHECKCLEAROP;
						/* command is ignored while executing a register */
		if (!Exec_reg && dorecord(nchar) == FAIL)
			CLEAROPBEEP;
		break;

	 case '@':			/* execute a named buffer */
		CHECKCLEAROP;
		while (Prenum1--)
		{
			if (doexecbuf(nchar) == FAIL)
			{
				CLEAROPBEEP;
				break;
			}
		}
		break;

/*
 * 1: Screen positioning commands
 */
	  case Ctrl('D'):
		flag = TRUE;

	  case Ctrl('U'):
		CHECKCLEAROP;
		if (Prenum)
			curwin->w_p_scroll = (Prenum > curwin->w_height) ? curwin->w_height : Prenum;
		n = (curwin->w_p_scroll <= curwin->w_height) ? curwin->w_p_scroll : curwin->w_height;
		if (flag)
		{
				curwin->w_topline += n;
				if (curwin->w_topline > curbuf->b_ml.ml_line_count)
					curwin->w_topline = curbuf->b_ml.ml_line_count;
				comp_Botline(curwin);		/* compute curwin->w_botline */
				(void)onedown(n);
		}
		else
		{
				if (n >= curwin->w_cursor.lnum)
					n = curwin->w_cursor.lnum - 1;
				Prenum1 = curwin->w_cursor.lnum - n;
				scrolldown(n);
				if (Prenum1 < curwin->w_cursor.lnum)
					curwin->w_cursor.lnum = Prenum1;
		}
		beginline(TRUE);
		updateScreen(VALID);
		break;

	  case Ctrl('B'):
	  case K_SUARROW:
		dir = BACKWARD;

	  case Ctrl('F'):
	  case K_SDARROW:
		CHECKCLEAROP;
		(void)onepage(dir, Prenum1);
		break;

	  case Ctrl('E'):
		CHECKCLEAROP;
		scrollup(Prenum1);
				/* We may have moved to another line -- webb */
		coladvance(curwin->w_curswant);
		updateScreen(VALID);
		break;

	  case Ctrl('Y'):
		CHECKCLEAROP;
		scrolldown(Prenum1);
				/* We may have moved to another line -- webb */
		coladvance(curwin->w_curswant);
		updateScreen(VALID);
		break;

	  case 'z':
		CHECKCLEAROP;
		if (isdigit(nchar))
		{
			/*
			 * we misuse some variables to be able to call premsg()
			 */
			operator = c;
			opnum = Prenum;
			Prenum = nchar - '0';
			for (;;)
			{
				premsg(' ', NUL);
				nchar = vgetc();
				State = NORMAL;
				if (nchar == DEL)
					Prenum /= 10;
				else if (isdigit(nchar))
					Prenum = Prenum * 10 + (nchar - '0');
				else if (nchar == CR)
				{
					win_setheight((int)Prenum);
					break;
				}
				else
				{
					CLEAROPBEEP;
					break;
				}
			}
			operator = NOP;
			break;
		}

		if (Prenum && Prenum != curwin->w_cursor.lnum)	/* line number given */
		{
			setpcmark();
			if (Prenum > curbuf->b_ml.ml_line_count)
				curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
			else
				curwin->w_cursor.lnum = Prenum;
		}
		State = NORMAL;			/* for updateScreen() */
		switch (nchar)
		{
		  case NL:				/* put curwin->w_cursor at top of screen */
		  case CR:
			beginline(TRUE);
		  case 't':
			curwin->w_topline = curwin->w_cursor.lnum;
			break;

		  case '.': 			/* put curwin->w_cursor in middle of screen */
		  case 'z':
			n = (curwin->w_height + plines(curwin->w_cursor.lnum)) / 2;
			goto dozcmd;

		  case '-': 			/* put curwin->w_cursor at bottom of screen */
		  case 'b':
			n = curwin->w_height;
			/* FALLTHROUGH */

	dozcmd:
			{
				register linenr_t	lp = curwin->w_cursor.lnum;
				register long		l = plines(lp);

				do
				{
					curwin->w_topline = lp;
					if (--lp == 0)
						break;
					l += plines(lp);
				} while (l <= n);
			}
			if (nchar != 'z' && nchar != 'b')
				beginline(TRUE);
			break;

		  case Ctrl('S'):	/* ignore CTRL-S and CTRL-Q to avoid problems */
		  case Ctrl('Q'):	/* with terminals that use xon/xoff */
		  	break;

		  default:
			CLEAROPBEEP;
		}
		updateScreen(VALID);
		break;

/*
 *	  2: Control commands
 */
	  case ':':
	    if (VIsual.lnum)
			goto dooperator;
		CHECKCLEAROP;
		/*
		 * translate "count:" into ":.,.+(count - 1)"
		 */
		if (Prenum)
		{
			stuffReadbuff((char_u *)".");
			if (Prenum > 1)
			{
				stuffReadbuff((char_u *)",.+");
				stuffnumReadbuff((long)Prenum - 1L);
			}
		}
		docmdline(NULL);
		modified = TRUE;
		break;

	  case K_HELP:
		CHECKCLEAROP;
		help();
		break;

	  case Ctrl('L'):
		CHECKCLEAROP;
		updateScreen(CLEAR);
		break;

	  case Ctrl('G'):
		CHECKCLEAROP;
		fileinfo(did_cd || Prenum);	/* print full name if count given or :cd used */
		break;

	  case K_CCIRCM:			/* CTRL-^, short for ":e #" */
		CHECKCLEAROPQ;
		(void)buflist_getfile((int)Prenum, (linenr_t)0, TRUE);
		break;

	  case 'Z': 		/* write, if changed, and exit */
		CHECKCLEAROPQ;
		if (nchar != 'Z')
		{
			CLEAROPBEEP;
			break;
		}
		stuffReadbuff((char_u *)":x\n");
		break;

	  case Ctrl(']'):			/* :ta to current identifier */
		CHECKCLEAROPQ;
	  case '*': 				/* / to current identifier or string */
	  case '#': 				/* ? to current identifier or string */
	  case 'K':					/* run program for current identifier */
		{
			register int 	col;
			register int	i;

			/*
			 * if i == 0: try to find an identifier
			 * if i == 1: try to find any string
			 */
			ptr = ml_get(curwin->w_cursor.lnum);
			for (i = 0;	i < 2; ++i)
			{
				/*
				 * skip to start of identifier/string
				 */
				col = curwin->w_cursor.col;
				while (ptr[col] != NUL &&
							(i == 0 ? !isidchar(ptr[col]) : iswhite(ptr[col])))
					++col;

				/*
				 * Back up to start of identifier/string. This doesn't match the
				 * real vi but I like it a little better and it shouldn't bother
				 * anyone.
				 */
				while (col > 0 && (i == 0 ? isidchar(ptr[col - 1]) :
							(!iswhite(ptr[col - 1]) && !isidchar(ptr[col - 1]))))
					--col;

				/*
				 * if identifier found or not '*' or '#' command, stop searching
				 */
				if (isidchar(ptr[col]) || (c != '*' && c != '#'))
					break;
			}
			/*
			 * did't find an identifier of string
			 */
			if (ptr[col] == NUL || (!isidchar(ptr[col]) && i == 0))
			{
				CLEAROPBEEP;
				break;
			}

			if (Prenum)
				stuffnumReadbuff(Prenum);
			switch (c)
			{
				case '*':
					stuffReadbuff((char_u *)"/");
					goto sow;

				case '#':
					stuffReadbuff((char_u *)"?");
sow:				if (i == 0)
						stuffReadbuff((char_u *)"\\<");
					break;

				case 'K':
					stuffReadbuff((char_u *)":! ");
					stuffReadbuff(p_kp);
					stuffReadbuff((char_u *)" ");
					break;
				default:
					stuffReadbuff((char_u *)":ta ");
			}

			/*
			 * Now grab the chars in the identifier
			 */
			while (i == 0 ? isidchar(ptr[col]) :
								(ptr[col] != NUL && !iswhite(ptr[col])))
			{
				stuffcharReadbuff(ptr[col]);
				++col;
			}
			if ((c == '*' || c == '#') && i == 0)
				stuffReadbuff((char_u *)"\\>");
			stuffReadbuff((char_u *)"\n");
		}
		break;

	  case Ctrl('T'):		/* backwards in tag stack */
			CHECKCLEAROPQ;
	  		dotag((char_u *)"", 2, (int)Prenum1);
			break;

/*
 * Cursor motions
 */
	  case 'G':
		mtype = MLINE;
		setpcmark();
		if (Prenum == 0 || Prenum > curbuf->b_ml.ml_line_count)
				curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
		else
				curwin->w_cursor.lnum = Prenum;
		beginline(TRUE);
		break;

	  case 'H':
	  case 'M':
		if (c == 'M')
				n = (curwin->w_height - curwin->w_empty_rows) / 2;
		else
				n = Prenum;
		mtype = MLINE;
		setpcmark();
		curwin->w_cursor.lnum = curwin->w_topline;
		while (n && onedown((long)1) == OK)
				--n;
		beginline(TRUE);
		break;

	  case 'L':
		mtype = MLINE;
		setpcmark();
		curwin->w_cursor.lnum = curwin->w_botline - 1;
		for (n = Prenum; n && oneup((long)1) == OK; n--)
				;
		beginline(TRUE);
		break;

	  case 'l':
	  case K_RARROW:
	  case ' ':
		mtype = MCHAR;
		mincl = FALSE;
		n = Prenum1;
		while (n--)
		{
			if (oneright() == FAIL)
			{
					/* space wraps to next line if 'whichwrap' bit 1 set */
					/* 'l' wraps to next line if 'whichwrap' bit 2 set */
					/* CURS_RIGHT wraps to next line if 'whichwrap' bit 3 set */
				if (((c == ' ' && (p_ww & 2)) ||
					 (c == 'l' && (p_ww & 4)) ||
					 (c == K_RARROW && (p_ww & 8))) &&
					 	curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
				{
					++curwin->w_cursor.lnum;
					curwin->w_cursor.col = 0;
					curwin->w_set_curswant = TRUE;
					continue;
				}
				if (operator == NOP)
					beep();
				else
				{
					if (lineempty(curwin->w_cursor.lnum))
						CLEAROPBEEP;
					else
					{
						mincl = TRUE;
						if (n)
							beep();
					}
				}
				break;
			}
		}
		break;

	  case Ctrl('H'):
	  case 'h':
	  case K_LARROW:
	  case DEL:
		mtype = MCHAR;
		mincl = FALSE;
		n = Prenum1;
		while (n--)
		{
			if (oneleft() == FAIL)
			{
					/* backspace and del wrap to previous line if 'whichwrap'
					 *											bit 0 set */
					/* 'h' wraps to previous line if 'whichwrap' bit 2 set */
					/* CURS_LEFT wraps to previous line if 'whichwrap' bit 3 set */
				if ((((c == Ctrl('H') || c == DEL) && (p_ww & 1)) ||
					 (c == 'h' && (p_ww & 4)) ||
					 (c == K_LARROW && (p_ww & 8))) &&
							curwin->w_cursor.lnum > 1)
				{
					--(curwin->w_cursor.lnum);
					coladvance(MAXCOL);
					curwin->w_set_curswant = TRUE;
					continue;
				}
				else if (operator != DELETE && operator != CHANGE)
					beep();
				else if (Prenum1 == 1)
					CLEAROPBEEP;
				break;
			}
		}
		break;

	  case '-':
		flag = TRUE;
		/* FALLTHROUGH */

	  case 'k':
	  case K_UARROW:
	  case Ctrl('P'):
		mtype = MLINE;
		if (oneup(Prenum1) == FAIL)
			CLEAROPBEEP;
		else if (flag)
			beginline(TRUE);
		break;

	  case '+':
	  case CR:
		flag = TRUE;
		/* FALLTHROUGH */

	  case 'j':
	  case K_DARROW:
	  case Ctrl('N'):
	  case NL:
		mtype = MLINE;
		if (onedown(Prenum1) == FAIL)
			CLEAROPBEEP;
		else if (flag)
			beginline(TRUE);
		break;

		/*
		 * This is a strange motion command that helps make operators more
		 * logical. It is actually implemented, but not documented in the
		 * real 'vi'. This motion command actually refers to "the current
		 * line". Commands like "dd" and "yy" are really an alternate form of
		 * "d_" and "y_". It does accept a count, so "d3_" works to delete 3
		 * lines.
		 */
	  case '_':
lineop:
		mtype = MLINE;
		if (onedown((long)(Prenum1 - 1)) == FAIL)
			CLEAROPBEEP;
		if (operator != YANK)			/* 'Y' does not move cursor */
			beginline(TRUE);
		break;

	  case '|':
		mtype = MCHAR;
		mincl = TRUE;
		beginline(FALSE);
		if (Prenum > 0)
			coladvance((colnr_t)(Prenum - 1));
		curwin->w_curswant = (colnr_t)(Prenum - 1);
			/* keep curswant at the column where we wanted to go, not where
				we ended; differs is line is too short */
		curwin->w_set_curswant = FALSE;
		break;

		/*
		 * Word Motions
		 */

	  case 'B':
		type = 1;
		/* FALLTHROUGH */

	  case 'b':
	  case K_SLARROW:
		mtype = MCHAR;
		mincl = FALSE;
		curwin->w_set_curswant = TRUE;
		if (bck_word(Prenum1, type))
			CLEAROPBEEP;
		break;

	  case 'E':
		type = 1;
		/* FALLTHROUGH */

	  case 'e':
		mincl = TRUE;
		goto dowrdcmd;

	  case 'W':
		type = 1;
		/* FALLTHROUGH */

	  case 'w':
	  case K_SRARROW:
		mincl = FALSE;
		flag = TRUE;
		/*
		 * This is a little strange. To match what the real vi does, we
		 * effectively map 'cw' to 'ce', and 'cW' to 'cE', provided that we are
		 * not on a space or a TAB. This seems
		 * impolite at first, but it's really more what we mean when we say
		 * 'cw'.
		 * Another strangeness: When standing on the end of a word "ce" will
		 * change until the end of the next wordt, but "cw" will change only
		 * one character! This is done by setting type to 2.
		 */
		if (operator == CHANGE && (n = gchar_cursor()) != ' ' && n != TAB &&
																n != NUL)
		{
			mincl = TRUE;
			flag = FALSE;
			flag2 = TRUE;
		}

dowrdcmd:
		mtype = MCHAR;
		curwin->w_set_curswant = TRUE;
		if (flag)
			n = fwd_word(Prenum1, type, operator != NOP);
		else
			n = end_word(Prenum1, type, flag2);
		if (n)
		{
			CLEAROPBEEP;
			break;
		}
#if 0
		/*
		 * If we do a 'dw' for the last word in a line, we only delete the rest
		 * of the line, not joining the two lines, unless the current line is empty.
		 */
		if (operator == DELETE && Prenum1 == 1 &&
				curbuf->b_startop.lnum != curwin->w_cursor.lnum && !lineempty(startop.lnum))
		{
				curwin->w_cursor = curbuf->b_startop;
				while (oneright() == OK)
					;
				mincl = TRUE;
		}
#endif
		break;

	  case '$':
		mtype = MCHAR;
		mincl = TRUE;
		curwin->w_curswant = MAXCOL;				/* so we stay at the end */
		if (onedown((long)(Prenum1 - 1)) == FAIL)
		{
			CLEAROPBEEP;
			break;
		}
		break;

	  case '^':
		flag = TRUE;
		/* FALLTHROUGH */

	  case '0':
		mtype = MCHAR;
		mincl = FALSE;
		beginline(flag);
		break;

/*
 * 4: Searches
 */
	  case '?':
	  case '/':
		if (!getcmdline(c, searchbuff))
		{
			CLEAROP;
			break;
		}
		mtype = MCHAR;
		mincl = FALSE;
		curwin->w_set_curswant = TRUE;

		n = dosearch(c, searchbuff, FALSE, Prenum1, TRUE, TRUE);
		if (n == 0)
			CLEAROP;
		else if (n == 2)
			mtype = MLINE;
		break;

	  case 'N':
		flag = 1;

	  case 'n':
		mtype = MCHAR;
		mincl = FALSE;
		curwin->w_set_curswant = TRUE;
		if (!dosearch(0, NULL, flag, Prenum1, TRUE, TRUE))
			CLEAROP;
		break;

		/*
		 * Character searches
		 */
	  case 'T':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 't':
		type = 1;
		goto docsearch;

	  case 'F':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 'f':
docsearch:
		mtype = MCHAR;
		if (dir == BACKWARD)
			mincl = FALSE;
		else
			mincl = TRUE;
		curwin->w_set_curswant = TRUE;
		if (!searchc(nchar, dir, type, Prenum1))
			CLEAROPBEEP;
		break;

	  case ',':
		flag = 1;
		/* FALLTHROUGH */

	  case ';':
	    dir = flag;
	    goto docsearch;		/* nchar == NUL, thus repeat previous search */

		/*
		 * section or C function searches
		 */
	  case '[':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case ']':
		mtype = MCHAR;
		mincl = FALSE;

		/*
		 * "[f" or "]f" : Edit file under the cursor (same as "gf")
		 */
		if ((c == ']' || c == '[') && nchar == 'f')
			goto gotofile;

		/*
		 * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
		 */
		if ((c == '[' && (nchar == '{' || nchar == '(')) ||
		   ((c == ']' && (nchar == '}' || nchar == ')'))))
		{
			FPOS old_pos;

			old_pos = curwin->w_cursor;
			while (Prenum1--)
			{
				if ((pos = showmatch(nchar)) == NULL)
				{
					CLEAROPBEEP;
					break;
				}
				curwin->w_cursor = *pos;
			}
			curwin->w_cursor = old_pos;
			if (pos != NULL)
			{
				setpcmark();
				curwin->w_cursor = *pos;
				curwin->w_set_curswant = TRUE;
			}
			break;
		}

		/*
		 * "[[", "[]", "]]" and "][": move to start or end of function
		 */
		if (nchar == '[' || nchar == ']')
		{
			if (nchar == c)				/* "]]" or "[[" */
				flag = '{';
			else
				flag = '}';				/* "][" or "[]" */

			curwin->w_set_curswant = TRUE;
			/*
			 * Imitate strange vi behaviour: When using "]]" with an operator we
			 * also stop at '}'.
			 */
			if (!findpar(dir, Prenum1, flag,
							(operator != NOP && dir == FORWARD && flag == '{')))
				CLEAROPBEEP;
			break;
		}

		/*
		 * "[p" and "]p": put with indent adjustment
		 */
		if (nchar == 'p')
		{
			doput((c == ']') ? FORWARD : BACKWARD, Prenum1, TRUE);
			modified = TRUE;
			break;
		}

		/*
		 * end of '[' and ']': not a valid nchar
		 */
		CLEAROPBEEP;
		break;

	  case '%':
		mincl = TRUE;
	    if (Prenum)		/* {cnt}% : goto {cnt} percentage in file */
		{
			if (Prenum > 100)
				CLEAROPBEEP;
			else
			{
				mtype = MLINE;
				setpcmark();
						/* round up, so CTRL-G will give same value */
				curwin->w_cursor.lnum = (curbuf->b_ml.ml_line_count * Prenum + 99) / 100;
				beginline(TRUE);
			}
		}
		else			/* % : go to matching paren */
		{
			mtype = MCHAR;
			if ((pos = showmatch(NUL)) == NULL)
				CLEAROPBEEP;
			else
			{
				setpcmark();
				curwin->w_cursor = *pos;
				curwin->w_set_curswant = TRUE;
			}
		}
		break;

	  case '(':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case ')':
		mtype = MCHAR;
		if (c == ')')
			mincl = FALSE;
		else
			mincl = TRUE;
		curwin->w_set_curswant = TRUE;

		if (!findsent(dir, Prenum1))
			CLEAROPBEEP;
		break;

	  case '{':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case '}':
		mtype = MCHAR;
		mincl = FALSE;
		curwin->w_set_curswant = TRUE;
		if (!findpar(dir, Prenum1, NUL, FALSE))
			CLEAROPBEEP;
		break;

/*
 * 5: Edits
 */
	  case '.':
		CHECKCLEAROPQ;
		if (start_redo(Prenum) == FAIL)
			CLEAROPBEEP;
		modified = TRUE;
		break;

	  case 'u':
	    if (VIsual.lnum)
			goto dooperator;
	  case K_UNDO:
		CHECKCLEAROPQ;
		u_undo((int)Prenum1);
		curwin->w_set_curswant = TRUE;
		modified = TRUE;
		break;

	  case Ctrl('R'):
		CHECKCLEAROPQ;
	  	u_redo((int)Prenum1);
		curwin->w_set_curswant = TRUE;
		modified = TRUE;
		break;

	  case 'U':
	    if (VIsual.lnum)
			goto dooperator;
		CHECKCLEAROPQ;
		u_undoline();
		curwin->w_set_curswant = TRUE;
		modified = TRUE;
		break;

	  case 'r':
	    if (VIsual.lnum)
		{
			c = 'c';
			goto dooperator;
		}
		CHECKCLEAROPQ;
		ptr = ml_get_cursor();
		if (STRLEN(ptr) < (unsigned)Prenum1)	/* not enough characters to replace */
		{
			CLEAROPBEEP;
			break;
		}
		/*
		 * Replacing with a line break or tab is done by edit(), because it
         * is complicated.
		 * Other characters are done below to avoid problems with things like
		 * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
		 */
		if (nchar == '\r' || nchar == '\n' || nchar == '\t')
		{
			prep_redo(Prenum1, 'r', nchar, NUL);
			stuffnumReadbuff(Prenum1);
			stuffcharReadbuff('R');
			stuffcharReadbuff(nchar);
			stuffcharReadbuff(ESC);
			break;
		}

		if (nchar == Ctrl('V'))				/* get another character */
		{
			c = Ctrl('V');
			nchar = get_literal(&type);
			if (type)						/* typeahead */
				stuffcharReadbuff(type);
		}
		else
			c = NUL;
		prep_redo(Prenum1, 'r', c, nchar);
		if (!u_save_cursor())				/* save line for undo */
			break;
			/*
			 * Get ptr again, because u_save will have released the line.
			 * At the same time we let know that the line will be changed.
			 */
		ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) + curwin->w_cursor.col;
		curwin->w_cursor.col += Prenum1 - 1;
		while (Prenum1--)					/* replace the characters */
			*ptr++ = nchar;
		curwin->w_set_curswant = TRUE;
		CHANGED;
		updateline();
		modified = TRUE;
		break;

	  case 'J':
	    if (VIsual.lnum)		/* join the visual lines */
		{
			if (curwin->w_cursor.lnum > VIsual.lnum)
			{
				Prenum = curwin->w_cursor.lnum - VIsual.lnum + 1;
				curwin->w_cursor.lnum = VIsual.lnum;
			}
			else
				Prenum = VIsual.lnum - curwin->w_cursor.lnum + 1;
			VIsual.lnum = 0;
		}
		CHECKCLEAROP;
		if (Prenum <= 1)
			Prenum = 2; 			/* default for join is two lines! */
		if (curwin->w_cursor.lnum + Prenum - 1 > curbuf->b_ml.ml_line_count)	/* beyond last line */
		{
			CLEAROPBEEP;
			break;
		}

		prep_redo(Prenum, 'J', NUL, NUL);
		dodojoin(Prenum, TRUE, TRUE);
		modified = TRUE;
		break;

	  case 'P':
		dir = BACKWARD;
		/* FALLTHROUGH */

	  case 'p':
		CHECKCLEAROPQ;
		prep_redo(Prenum, c, NUL, NUL);
		doput(dir, Prenum1, FALSE);
		modified = TRUE;
		break;

	  case Ctrl('A'):			/* add to number */
	  case Ctrl('X'):			/* subtract from number */
		CHECKCLEAROPQ;
		if (doaddsub((int)c, Prenum1) == OK)
			prep_redo(Prenum1, c, NUL, NUL);
		modified = TRUE;
		break;

/*
 * 6: Inserts
 */
	  case 'A':
		curwin->w_set_curswant = TRUE;
		while (oneright() == OK)
				;
		/* FALLTHROUGH */

	  case 'a':
		CHECKCLEAROPQ;
		/* Works just like an 'i'nsert on the next character. */
		if (u_save_cursor())
		{
			if (!lineempty(curwin->w_cursor.lnum))
				inc_cursor();
			startinsert(c, FALSE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

	  case 'I':
		beginline(TRUE);
		/* FALLTHROUGH */

	  case 'i':
		CHECKCLEAROPQ;
		if (u_save_cursor())
		{
			startinsert(c, FALSE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

	  case 'o':
	  	if (VIsual.lnum)	/* switch start and end of visual */
		{
			Prenum = VIsual.lnum;
			VIsual.lnum = curwin->w_cursor.lnum;
			curwin->w_cursor.lnum = Prenum;
			if (VIsual.col != VISUALLINE)
			{
				n = VIsual.col;
				VIsual.col = curwin->w_cursor.col;
				curwin->w_cursor.col = (int)n;
				curwin->w_set_curswant = TRUE;
			}
			break;
		}
		CHECKCLEAROP;
		if (u_save(curwin->w_cursor.lnum, (linenr_t)(curwin->w_cursor.lnum + 1)) &&
							Opencmd(FORWARD, TRUE, TRUE))
		{
			startinsert('o', TRUE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

	  case 'O':
		CHECKCLEAROPQ;
		if (u_save((linenr_t)(curwin->w_cursor.lnum - 1), curwin->w_cursor.lnum) && Opencmd(BACKWARD, TRUE, TRUE))
		{
			startinsert('O', TRUE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

	  case 'R':
	    if (VIsual.lnum)
		{
			c = 'c';
			VIsual.col = VISUALLINE;
			goto dooperator;
		}
		CHECKCLEAROPQ;
		if (u_save_cursor())
		{
			startinsert('R', FALSE, Prenum1);
			modified = TRUE;
			command_busy = TRUE;
		}
		break;

/*
 * 7: Operators
 */
	  case '~': 		/* swap case */
	  /*
	   * if tilde is not an operator and Visual is off: swap case
	   * of a single character
	   */
		if (!p_to && !VIsual.lnum)
		{
			CHECKCLEAROPQ;
			if (lineempty(curwin->w_cursor.lnum))
			{
				CLEAROPBEEP;
				break;
			}
			prep_redo(Prenum, '~', NUL, NUL);

			if (!u_save_cursor())
				break;

			for (; Prenum1 > 0; --Prenum1)
			{
				if (gchar_cursor() == NUL)
					break;
				swapchar(&curwin->w_cursor);
				inc_cursor();
			}

			curwin->w_set_curswant = TRUE;
			CHANGED;
			updateline();
			modified = TRUE;
			break;
		}
		/*FALLTHROUGH*/

	  case 'd':
	  case 'c':
	  case 'y':
	  case '>':
	  case '<':
	  case '!':
	  case '=':
	  case 'Q':
dooperator:
		n = STRCHR(opchars, c) - opchars + 1;
		if (n == operator)		/* double operator works on lines */
			goto lineop;
		CHECKCLEAROP;
		if (Prenum != 0)
			opnum = Prenum;
		curbuf->b_startop = curwin->w_cursor;
		operator = (int)n;
		break;

/*
 * 8: Abbreviations
 */

	 /* when Visual the next commands are operators */
	  case 'S':
	  case 'Y':
	  case 'D':
	  case 'C':
	  case 'x':
	  case 'X':
	  case 's':
	  	if (VIsual.lnum)
		{
			static char_u trans[] = "ScYyDdCcxdXdsc";

			if (isupper(c) && !Visual_block)		/* uppercase means linewise */
				VIsual.col = VISUALLINE;
			c = *(STRCHR(trans, c) + 1);
			goto dooperator;
		}

	  case '&':
		CHECKCLEAROPQ;
		if (Prenum)
			stuffnumReadbuff(Prenum);

		if (c == 'Y' && p_ye)
			c = 'Z';
		{
				static char_u *(ar[9]) = {(char_u *)"dl", (char_u *)"dh", (char_u *)"d$", (char_u *)"c$", (char_u *)"cl", (char_u *)"cc", (char_u *)"yy", (char_u *)"y$", (char_u *)":s\r"};
				static char_u *str = (char_u *)"xXDCsSYZ&";

				stuffReadbuff(ar[(int)(STRCHR(str, c) - str)]);
		}
		break;

/*
 * 9: Marks
 */

	  case 'm':
		CHECKCLEAROP;
		if (setmark(nchar) == FAIL)
			CLEAROPBEEP;
		break;

	  case '\'':
		flag = TRUE;
		/* FALLTHROUGH */

	  case '`':
		pos = getmark(nchar, (operator == NOP));
		if (pos == (FPOS *)-1)	/* jumped to other file */
		{
			if (flag)
				beginline(TRUE);
			break;
		}

		if (pos != NULL)
			setpcmark();

cursormark:
		if (pos == NULL || pos->lnum == 0)
			CLEAROPBEEP;
		else
		{
			curwin->w_cursor = *pos;
			if (flag)
				beginline(TRUE);
		}
		mtype = flag ? MLINE : MCHAR;
		mincl = FALSE;		/* ignored if not MCHAR */
		curwin->w_set_curswant = TRUE;
		break;

	case Ctrl('O'):			/* goto older pcmark */
		Prenum1 = -Prenum1;
		/* FALLTHROUGH */

	case Ctrl('I'):			/* goto newer pcmark */
		CHECKCLEAROPQ;
		pos = movemark((int)Prenum1);
		if (pos == (FPOS *)-1)	/* jump to other file */
		{
			curwin->w_set_curswant = TRUE;
			break;
		}
		goto cursormark;

/*
 * 10. Buffer setting
 */
	  case '"':
		CHECKCLEAROP;
		if (nchar != NUL && is_yank_buffer(nchar, FALSE))
		{
			yankbuffer = nchar;
			opnum = Prenum;		/* remember count before '"' */
		}
		else
			CLEAROPBEEP;
		break;

/*
 * 11. Visual
 */
 	  case 'v':
	  case 'V':
	  case Ctrl('V'):
		CHECKCLEAROP;
		Visual_block = FALSE;

			/* stop Visual */
		if (VIsual.lnum)
		{
			VIsual.lnum = 0;
			updateScreen(NOT_VALID);		/* delete the inversion */
		}
			/* start Visual */
		else
		{
			if (!didwarn && set_highlight('v') == FAIL)/* cannot highlight */
			{
				EMSG("Warning: terminal cannot highlight");
				didwarn = TRUE;
			}
			if (Prenum)						/* use previously selected part */
			{
				if (!resel_Visual_type)		/* there is none */
				{
					beep();
					break;
				}
				VIsual = curwin->w_cursor;
				if (resel_Visual_nlines > 1)
					curwin->w_cursor.lnum += resel_Visual_nlines * Prenum - 1;
				switch (resel_Visual_type)
				{
				case 'V':	VIsual.col = VISUALLINE;
							break;

				case Ctrl('V'):
							Visual_block = TRUE;
							break;

				case 'v':		
							if (resel_Visual_nlines <= 1)
								curwin->w_cursor.col += resel_Visual_col * Prenum - 1;
							else
								curwin->w_cursor.col = resel_Visual_col;
							break;
				}
				if (resel_Visual_col == MAXCOL)
				{
					curwin->w_curswant = MAXCOL;
					coladvance(MAXCOL);
				}
				else if (Visual_block)
					coladvance((colnr_t)(curwin->w_virtcol + resel_Visual_col * Prenum - 1));
				curs_columns(TRUE);			/* recompute w_virtcol */
				updateScreen(NOT_VALID);	/* show the inversion */
			}
			else
			{
				VIsual = curwin->w_cursor;
				if (c == 'V')				/* linewise */
					VIsual.col = VISUALLINE;
				else if (c == Ctrl('V'))	/* blockwise */
					Visual_block = TRUE;
				updateline();				/* start the inversion */
			}
		}
		break;

/*
 * 12. Suspend
 */

 	case Ctrl('Z'):
		CLEAROP;
		VIsual.lnum = 0;					/* stop Visual */
		stuffReadbuff((char_u *)":st\r");	/* with autowrite */
		break;

/*
 * 13. Window commands
 */

 	case Ctrl('W'):
		CHECKCLEAROP;
		do_window(nchar, Prenum);			/* everything is in window.c */
		break;

/*
 *   14. extended commands (starting with 'g')
 */
 	case 'g':
		switch (nchar)
		{
						/*
						 * "gf": goto file, edit file under cursor
						 * "]f" and "[f": can also be used.
						 */
			case 'f':
gotofile:
						ptr = file_name_at_cursor();
							/* do autowrite if necessary */
						if (curbuf->b_changed && curbuf->b_nwindows <= 1 && !p_hid)
							autowrite(curbuf);
						if (ptr != NULL)
						{
							setpcmark();
							stuffReadbuff((char_u *) ":e ");
							stuffReadbuff(ptr);
							stuffReadbuff((char_u *) "\n");
							free(ptr);
						}
						else
							CLEAROPBEEP;
						break;

						/*
						 * "gs": goto sleep
						 */
			case 's':	while (Prenum1-- && !got_int)
						{
							sleep(1);
							breakcheck();
						}
						break;

			default:	CLEAROPBEEP;
						break;
		}
		break;

/*
 * The end
 */
	  case ESC:
	    if (VIsual.lnum)
		{
			VIsual.lnum = 0;			/* stop Visual */
			updateScreen(NOT_VALID);
			CLEAROP;					/* don't beep */
			break;
		}
		/* Don't drop through and beep if we are canceling a command: */
		else if (operator != NOP || opnum || Prenum || yankbuffer)
		{
			CLEAROP;					/* don't beep */
			break;
		}
		/* FALLTHROUGH */

	  default:					/* not a known command */
		CLEAROPBEEP;
		break;

	}	/* end of switch on command character */

/*
 * if we didn't start or finish an operator, reset yankbuffer, unless we
 * need it later.
 */
	if (!finish_op && !operator && strchr("\"DCYSsXx.", c) == NULL)
		yankbuffer = 0;

	/*
	 * If an operation is pending, handle it...
	 */
	if ((VIsual.lnum || finish_op) && operator != NOP)
	{
		if (operator != YANK && !VIsual.lnum)		/* can't redo yank */
		{
			prep_redo(Prenum, opchars[operator - 1], c, nchar);
			if (c == '/' || c == '?')				/* was a search */
			{
				AppendToRedobuff(searchbuff);
				AppendToRedobuff(NL_STR);
			}
		}

		if (redo_Visual_busy)
		{
			curbuf->b_startop = curwin->w_cursor;
			curwin->w_cursor.lnum += redo_Visual_nlines - 1;
			switch (redo_Visual_type)
			{
			case 'V':	VIsual.col = VISUALLINE;
						break;

			case Ctrl('V'):
						Visual_block = TRUE;
						break;

			case 'v':		
						if (redo_Visual_nlines <= 1)
							curwin->w_cursor.col += redo_Visual_col - 1;
						else
							curwin->w_cursor.col = redo_Visual_col;
						break;
			}
			if (redo_Visual_col == MAXCOL)
			{
				curwin->w_curswant = MAXCOL;
				coladvance(MAXCOL);
			}
			Prenum = redo_Visual_Prenum;
			if (Prenum == 0)
				Prenum1 = 1L;
			else
				Prenum1 = Prenum;
		}
		else if (VIsual.lnum)
			curbuf->b_startop = VIsual;

		if (lt(curbuf->b_startop, curwin->w_cursor))
		{
			curbuf->b_endop = curwin->w_cursor;
			curwin->w_cursor = curbuf->b_startop;
		}
		else
		{
			curbuf->b_endop = curbuf->b_startop;
			curbuf->b_startop = curwin->w_cursor;
		}
		nlines = curbuf->b_endop.lnum - curbuf->b_startop.lnum + 1;

		if (VIsual.lnum || redo_Visual_busy)
		{
			if (Visual_block)				/* block mode */
			{
				startvcol = getvcol(curwin, &(curbuf->b_startop), 2);
				n = getvcol(curwin, &(curbuf->b_endop), 2);
				if (n < startvcol)
					startvcol = (colnr_t)n;

			/* if '$' was used, get endvcol from longest line */
				if (curwin->w_curswant == MAXCOL)
				{
					curwin->w_cursor.col = MAXCOL;
					endvcol = 0;
					for (curwin->w_cursor.lnum = curbuf->b_startop.lnum; curwin->w_cursor.lnum <= curbuf->b_endop.lnum; ++curwin->w_cursor.lnum)
						if ((n = getvcol(curwin, &curwin->w_cursor, 3)) > endvcol)
							endvcol = (colnr_t)n;
					curwin->w_cursor = curbuf->b_startop;
				}
				else if (redo_Visual_busy)
					endvcol = startvcol + redo_Visual_col - 1;
				else
				{
					endvcol = getvcol(curwin, &(curbuf->b_startop), 3);
					n = getvcol(curwin, &(curbuf->b_endop), 3);
					if (n > endvcol)
						endvcol = (colnr_t)n;
				}
				coladvance(startvcol);
			}

	/*
	 * prepare to reselect and redo Visual: this is based on the size
	 * of the Visual text
	 */
			if (Visual_block)
				resel_Visual_type = Ctrl('V');
			else if (VIsual.col == VISUALLINE)
				resel_Visual_type = 'V';
			else
				resel_Visual_type = 'v';
			if (curwin->w_curswant == MAXCOL)
				resel_Visual_col = MAXCOL;
			else if (Visual_block)
				resel_Visual_col = endvcol - startvcol + 1;
			else if (nlines > 1)
				resel_Visual_col = curbuf->b_endop.col;
			else
				resel_Visual_col = curbuf->b_endop.col - curbuf->b_startop.col + 1;
			resel_Visual_nlines = nlines;
			if (operator != YANK && operator != COLON)	/* can't redo yank and : */
			{
				prep_redo(0L, 'v', opchars[operator - 1], NUL);
				redo_Visual_type = resel_Visual_type;
				redo_Visual_col = resel_Visual_col;
				redo_Visual_nlines = resel_Visual_nlines;
				redo_Visual_Prenum = Prenum;
			}

			/*
			 * Mincl defaults to TRUE.
			 * If endop is on a NUL (empty line) mincl becomes FALSE
			 * This makes "d}P" and "v}dP" work the same.
			 */
			mincl = TRUE;
			if (VIsual.col == VISUALLINE)
				mtype = MLINE;
			else
			{
				mtype = MCHAR;
				if (*ml_get_pos(&(curbuf->b_endop)) == NUL)
					mincl = FALSE;
			}

			redo_Visual_busy = FALSE;
			/*
			 * Switch Visual off now, so screen updating does
			 * not show inverted text when the screen is redrawn.
			 * With YANK and sometimes with COLON and FILTER there is no screen
			 * redraw, so it is done here to remove the inverted part.
			 */
			VIsual.lnum = 0;
			if (operator == YANK || operator == COLON || operator == FILTER)
				updateScreen(NOT_VALID);
		}
		else if (operator == LSHIFT || operator == RSHIFT)
			Prenum1 = 1L;		/* if not visual mode: shift one indent */

		curwin->w_set_curswant = 1;

			/* no_op is set when start and end are the same */
		no_op = (mtype == MCHAR && !mincl && equal(curbuf->b_startop, curbuf->b_endop));

	/*
	 * If the end of an operator is in column one while mtype is MCHAR and mincl
	 * is FALSE, we put endop after the last character in the previous line.
	 * If startop is on or before the first non-blank in the line, the operator
	 * becomes linewise (strange, but that's the way vi does it).
	 */
		if (mtype == MCHAR && mincl == FALSE && curbuf->b_endop.col == 0 && nlines > 1)
		{
			--nlines;
			--curbuf->b_endop.lnum;
			if (inindent())
				mtype = MLINE;
			else
			{
				curbuf->b_endop.col = STRLEN(ml_get(curbuf->b_endop.lnum));
				if (curbuf->b_endop.col)
				{
					--curbuf->b_endop.col;
					mincl = TRUE;
				}
			}
		}
		switch (operator)
		{
		  case LSHIFT:
		  case RSHIFT:
			doshift(operator, TRUE, (int)Prenum1);
			modified = TRUE;
			break;

		  case DELETE:
			if (!no_op)
			{
				dodelete();
				modified = TRUE;
			}
			break;

		  case YANK:
			if (!no_op)
				(void)doyank(FALSE);
			break;

		  case CHANGE:
			dochange();
			modified = TRUE;
			command_busy = TRUE;
			break;

		  case FILTER:
			bangredo = TRUE;			/* dobang() will put cmd in redo buffer */

		  case INDENT:
		  case COLON:
dofilter:
			sprintf((char *)IObuff, ":%ld,%ld", (long)curbuf->b_startop.lnum, (long)curbuf->b_endop.lnum);
			stuffReadbuff(IObuff);
			if (operator != COLON)
				stuffReadbuff((char_u *)"!");
			if (operator == INDENT)
			{
				stuffReadbuff(p_ep);
				stuffReadbuff((char_u *)"\n");
			}
			else if (operator == FORMAT)
			{
				stuffReadbuff(p_fp);
				stuffReadbuff((char_u *)"\n");
			}
				/*	docmdline() does the rest */
			break;

		  case TILDE:
		  case UPPER:
		  case LOWER:
			if (!no_op)
			{
				dotilde();
				modified = TRUE;
			}
			break;

		  case FORMAT:
			if (*p_fp != NUL)
				goto dofilter;		/* use external command */
			doformat();				/* use internal function */
			modified = TRUE;
			break;

		  default:
			CLEAROPBEEP;
		}
		operator = NOP;
		Visual_block = FALSE;
		yankbuffer = 0;
	}

normal_end:
	premsg(-1, NUL);

	if (restart_edit && operator == NOP && VIsual.lnum == 0 && !command_busy && stuff_empty() && yankbuffer == 0)
	{
		startinsert(restart_edit, FALSE, 1L);
		modified = TRUE;
	}

	checkpcmark();			/* check if we moved since setting pcmark */

/*
 * TEMPORARY: update the other windows for the current buffer if modified
 */
	if (modified)
	{
		WIN		*wp;

        for (wp = firstwin; wp; wp = wp->w_next)
			if (wp != curwin && wp->w_buffer == curbuf)
			{
				cursor_off();
				wp->w_redr_type = NOT_VALID;
				win_update(wp);
			}
	}
}