/* * STevie - ST editor for VI enthusiasts. ...Tim Thompson...twitch!tjt... */ #include #include "stevie.h" /* * normal * * Execute a command in normal mode. */ normal(c) int c; { char *p, *q; int nchar, n; switch(c){ case 'H': help(); /* fall through purposely */ case '\014': screenclear(); updatescreen(); break; case 04: /* control-d */ if ( ! onedown(10) ) beep(); break; case 025: /* control-u */ if ( ! oneup(10) ) beep(); break; case 06: /* control-f */ if ( ! onedown(Rows) ) beep(); break; case 02: /* control-b */ if ( ! oneup(Rows) ) beep(); break; case '\007': fileinfo(); break; case 'G': gotoline(Prenum); break; case 'l': if ( ! oneright() ) beep(); break; case 'h': if ( ! oneleft() ) beep(); break; case 'k': if ( ! oneup(1) ) beep(); break; case 'j': if ( ! onedown(1) ) beep(); break; case 'b': /* If we're on the first character of a word, force */ /* an initial backup. */ if ( ! issepchar(*Curschar) && Curschar>Filemem && issepchar(*(Curschar-1)) ) Curschar--; if ( ! issepchar(*Curschar) ) { /* If we start in the middle of a word, back */ /* up until we hit a separator. */ while ( Curschar>Filemem && !issepchar(*Curschar)) Curschar--; if ( issepchar(*Curschar) ) Curschar++; } else { /* back up past all separators. */ while ( Curschar>Filemem && issepchar(*Curschar)) Curschar--; /* back up past all non-separators. */ while (Curschar>Filemem && !issepchar(*Curschar)){ Curschar--; } if ( issepchar(*Curschar) ) Curschar++; } break; case 'w': if ( issepchar(*Curschar) ) { /* If we're on a separator, we advance to */ /* the next non-separator char. */ while ( (p=Curschar+1) < Fileend ) { Curschar = p; if ( ! issepchar(*Curschar) ) break; } } else { /* If we're in the middle of a word, we */ /* advance to the next word-separator. */ while ( (p=Curschar+1) < Fileend ) { Curschar = p; if ( issepchar(*Curschar) ) break; } /* Now go past any trailing white space */ while (isspace(*Curschar) && (Curschar+1)': nchar = vgetc(); n = (Prenum==0?1:Prenum); switch(nchar){ case '>': tabinout(0,n); updatescreen(); break; default: beep(); } break; case '<': nchar = vgetc(); n = (Prenum==0?1:Prenum); switch(nchar){ case '<': tabinout(1,n); updatescreen(); break; default: beep(); } break; case '?': case '/': case ':': readcmdline(c); break; case 'n': repsearch(); break; case 'C': case 'D': p = Curschar; while ( Curschar >= p ) delchar(); updatescreen(); resetundo(); /* This should really go above the */ /* delchars above, and the undobuff should */ /* be constructed by them. */ if ( c == 'C' ) { Curschar++; startinsert("C"); } break; case 'r': nchar = vgetc(); resetundo(); if ( nchar=='\n' || (!Binary && nchar=='\r') ) { /* Replacing a char with a newline breaks the */ /* line in two, and is special. */ nchar = '\n'; /* convert \r to \n */ /* Save stuff necessary to undo it, by joining */ Uncurschar = Curschar-1; addtobuff(Undobuff,'J','i',*Curschar,'\033',NULL); /* Change current character. */ *Curschar = nchar; /* We don't want to end up on the '\n' */ if ( Curschar > Filemem ) Curschar--; else if (Curschar < Fileend ) Curschar++; } else { /* Replacing with a normal character */ addtobuff(Undobuff,'r',*Curschar,NULL); Uncurschar = Curschar; /* Change current character. */ *Curschar = nchar; } /* Save stuff necessary to redo it */ addtobuff(Redobuff,'r',nchar,NULL); updatescreen(); break; case 'p': putline(0); break; case 'P': putline(1); break; case 'J': for ( p=Curschar; *p!= '\n' && p<(Fileend-1) ; p++ ) ; if ( p >= (Fileend-1) ) { beep(); break; } Curschar = p; delchar(); resetundo(); Uncurschar = Curschar; addtobuff(Undobuff,'i','\n','\033',NULL); addtobuff(Redobuff,'J',NULL); updatescreen(); break; case '.': stuffin(Redobuff); break; case 'u': if ( Uncurschar != NULL && *Undobuff != '\0' ) { Curschar = Uncurschar; stuffin(Undobuff); *Undobuff = '\0'; } if ( Undelchars > 0 ) { Curschar = Uncurschar; /* construct the next Undobuff and Redobuff, which */ /* will re-insert the characters we're deleting. */ p = Undobuff; q = Redobuff; *p++ = *q++ = 'i'; while ( Undelchars-- > 0 ) { *p++ = *q++ = *Curschar; delchar(); } /* Finish constructing Uncursbuff, and Uncurschar */ /* is left unchanged. */ *p++ = *q++ = '\033'; *p = *q = '\0'; /* Undelchars has been reset to 0 */ updatescreen(); } break; default: beep(); break; } } /* * tabinout(inout,num) * * If inout==0, add a tab to the begining of the next num lines. * If inout==1, delete a tab from the begining of the next num lines. */ tabinout(inout,num) { int ntodo = num; char *savecurs, *p; beginline(); savecurs = Curschar; while ( ntodo-- > 0 ) { beginline(); if ( inout == 0 ) inschar('\t'); else { if ( *Curschar == '\t' ) delchar(); } if ( ntodo > 0 ) { if ( (p=nextline(Curschar)) != NULL ) Curschar = p; else break; } } /* We want to end up where we started */ Curschar = savecurs; updatescreen(); /* Construct re-do and un-do stuff */ sprintf(Redobuff,"%d%s",num,inout==0?">>":"<<"); resetundo(); Uncurschar = savecurs; sprintf(Undobuff,"%d%s",num,inout==0?"<<":">>"); } startinsert(initstr) char *initstr; { char *p, c; Insstart = Curschar; Ninsert = 0; Insptr = Insbuff; for (p=initstr; (c=(*p++))!='\0'; ) *Insptr++ = c; State = INSERT; windrefresh(); } resetundo() { Undelchars = 0; *Undobuff = '\0'; Uncurschar = NULL; }