void CFileMatcher::ParseMultiple(LPTSTR pszMultiple) { LPTSTR psz; LPTSTR pszNext = pszMultiple; int nLen = lstrlen(pszMultiple); // Replace all commas (or separators) with a null while (1) { psz = STRCHR(pszNext, ','); if (psz == NULL) psz = STRCHR(pszNext, ';'); if (psz == NULL) break; if ((psz != pszMultiple) && (psz[-1] != '\\')) *psz = 0; pszNext = psz + 1; } // Now doubly null terminate pszMultiple pszMultiple[nLen+1] = 0; }
void ErrorHandler::SysErrMsg() { #if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(RAR_SILENT) #define STRCHR strchr #define ERRCHAR char ERRCHAR *lpMsgBuf=NULL; int ErrType=GetLastError(); if (ErrType!=0 && FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL,ErrType,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf,0,NULL)) { ERRCHAR *CurMsg=lpMsgBuf; while (CurMsg!=NULL) { while (*CurMsg=='\r' || *CurMsg=='\n') CurMsg++; if (*CurMsg==0) break; ERRCHAR *EndMsg=STRCHR(CurMsg,'\r'); if (EndMsg==NULL) EndMsg=STRCHR(CurMsg,'\n'); if (EndMsg!=NULL) { *EndMsg=0; EndMsg++; } Log(NULL,"\n%s",CurMsg); CurMsg=EndMsg; } } LocalFree( lpMsgBuf ); #endif }
main() { printf("%d\n",STRCHR("abc",'a')); printf("%d\n",STRCHR("abc",'b')); printf("%d\n",STRCHR("abc",'d')); printf("%d\n",STRRCHR("abc",'a')); printf("%d\n",STRRCHR("abc",'b')); printf("%d\n",STRRCHR("abc",'d')); }
void UrlParse::setString(const char *urlstring) { protocol = hostname = path = resource = NULL; port = 0; // parse etc String cp(urlstring); char *colon = STRCHR(cp, ':'); if (colon == NULL || colon > cp.v()+4) { // new default_protocol method setProtocol(default_protocol); } else { String p = cp, tmp(colon+1); p.changeChar(':', '\0'); setProtocol(p); cp = tmp; } // eat slashes while (cp.v()[0] == '/') { String tmp = cp.v()+1; cp = tmp; } char *firstslash = STRCHR(cp, '/'); if (firstslash == NULL) { // host only hostname = cp; return; } else { String tmp = firstslash+1; *firstslash = '\0'; hostname = cp; cp = tmp; } colon = STRCHR(hostname, ':'); // reusing if (colon != NULL) { *colon = '\0'; port = ATOI(colon+1); if (port == 0) port = 80; } if (!cp.isempty()) { char *lastslash; for (lastslash = (char*)cp.v(); *lastslash; lastslash++) { } // go to end // back up to last slash or beginning for (; lastslash > (char*)cp.v() && *lastslash != '/'; lastslash--) { } if (*lastslash == '/') { resource = lastslash+1; *lastslash = '\0'; path = cp; } else { resource = cp; // no more slashes, just the filename->no path // path is already NULL } } // resolveDotDot(); }
static void do_test (size_t align, size_t pos, size_t len) { size_t i; int c; RES_TYPE result; CHAR *rej, *s; align &= 7; if ((align + pos + 10) * sizeof (CHAR) >= page_size || len > 240) return; rej = (CHAR *) (buf2) + (random () & 255); s = (CHAR *) (buf1) + align; for (i = 0; i < len; ++i) { rej[i] = random () & BIG_CHAR; if (!rej[i]) rej[i] = random () & BIG_CHAR; if (!rej[i]) rej[i] = 1 + (random () & SMALL_CHAR); } rej[len] = '\0'; for (c = 1; c <= BIG_CHAR; ++c) if (STRCHR (rej, c) == NULL) break; for (i = 0; i < pos; ++i) { s[i] = random () & BIG_CHAR; if (STRCHR (rej, s[i])) { s[i] = random () & BIG_CHAR; if (STRCHR (rej, s[i])) s[i] = c; } } s[pos] = rej[random () % (len + 1)]; if (s[pos]) { for (i = pos + 1; i < pos + 10; ++i) s[i] = random () & BIG_CHAR; s[i] = '\0'; } result = STRPBRK_RESULT (s, pos); printf ("Length %4zd, alignment %2zd, rej len %2zd:", pos, align, len); FOR_EACH_IMPL (impl, 0) do_one_test (impl, s, rej, result); putchar ('\n'); }
static void pcre_regexp_init(mrb_state *mrb, mrb_value self, mrb_value str, mrb_value flag) { mrb_value regexp; struct mrb_pcre_regexp *reg; int cflag = 0; int erroff = 0; const char *errstr = NULL; regexp = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@regexp")); if (mrb_nil_p(regexp)) { reg = malloc(sizeof(struct mrb_pcre_regexp)); memset(reg, 0, sizeof(struct mrb_pcre_regexp)); mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@regexp"), mrb_obj_value( Data_Wrap_Struct(mrb, mrb->object_class, &mrb_pcre_regexp_type, (void*) reg))); }else{ Data_Get_Struct(mrb, regexp, &mrb_pcre_regexp_type, reg); pcre_free(reg->re); } if (mrb_nil_p(flag)) cflag = 0; else if (mrb_fixnum_p(flag)) { int nflag = mrb_fixnum(flag); if (nflag & 1) cflag |= PCRE_CASELESS; if (nflag & 2) cflag |= PCRE_EXTENDED; if (nflag & 4) cflag |= PCRE_MULTILINE | PCRE_DOTALL; } else if (mrb_type(flag) == MRB_TT_TRUE) cflag |= PCRE_CASELESS; else if (mrb_string_p(flag)) { if (STRCHR(RSTRING_PTR(flag), 'i')) cflag |= PCRE_CASELESS; if (STRCHR(RSTRING_PTR(flag), 'x')) cflag |= PCRE_EXTENDED; if (STRCHR(RSTRING_PTR(flag), 'm')) cflag |= PCRE_MULTILINE | PCRE_DOTALL; } reg->flag = cflag; reg->re = pcre_compile(RSTRING_PTR(str), cflag, &errstr, &erroff, NULL); if (!reg->re) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "'%S' is an invalid regular expression because %S.", mrb_str_new_cstr(mrb, RSTRING_PTR(str) + erroff), mrb_str_new_cstr(mrb, errstr)); } mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@source"), str); }
/* * is_special -- * Test if the character is special in a basic RE. */ static int is_special(CHAR_T c) { /* * !!! * `*' and `$' are ordinary when appear at the beginning of a RE, * but it's safe to distinguish them from the ordinary characters. * The tilde is vi-specific, of course. */ return (STRCHR(L(".[*\\^$~"), c) && c); }
// P R I V A T E M E T H O D S int ACLStr::_FindCh ( IN const TCHAR charToFind, IN BOOL caseSensitive /*=TRUE*/, IN BOOL reverseFind /*=FALSE*/ ) { LPTSTR string = NULL; TCHAR ib[MAX_STRING]; // Initialize this to the // internal buffer. LPTSTR ibPtr = _string; TCHAR chToFind = charToFind; // If the internal string is NULL or the lenght is // zero then we will just bail and say we couldn't // find the string we were searching for. if (ibPtr != NULL || 0 != _length) { if (caseSensitive == TRUE) { chToFind = TOUPPER(charToFind); // Now copy the internal ACLStr buffer to the new // tempory Upper case version. if (_string) { // NOTE: STRCPY_S(target, length, source) - The length parameter is for // the length of the target string, not the source string. STRCPY_S(ib, MAX_STRING, _string); AnsiUpper(ib); ibPtr = ib; } } // case sensitive search? // Go look for the starting point of the string. // if we do NOT find it return STR_NOTFOUND if (reverseFind == TRUE) { string = STRRCHR(ibPtr, chToFind); } else { string = STRCHR(ibPtr, chToFind); } } // search string NULL? return (string == NULL) ? STR_NOTFOUND : (int)(string - ibPtr); } // ::_FindCh
/* * is_especial -- * Test if the character is special in an extended RE. */ static int is_especial(CHAR_T c) { /* * !!! * Right-brace is not an ERE special according to IEEE 1003.1-2001. * Right-parenthesis is a special character (so quoting doesn't hurt), * though it has no special meaning in this context, viz. at the * beginning of the string. So we need not quote it. Then again, * see the BUGS section in regex/re_format.7. * The tilde is vi-specific, of course. */ return (STRCHR(L(".[\\()*+?{|^$~"), c) && c); }
static void do_test (size_t align, size_t pos, size_t len) { size_t i; CHAR *acc, *s; align &= 7; if ((align + pos + 10) * sizeof (CHAR) >= page_size || len > 240 || ! len) return; acc = (CHAR *) (buf2) + (random () & 255); s = (CHAR *) (buf1) + align; for (i = 0; i < len; ++i) { acc[i] = random () & BIG_CHAR; if (!acc[i]) acc[i] = random () & BIG_CHAR; if (!acc[i]) acc[i] = 1 + (random () & SMALL_CHAR); } acc[len] = '\0'; for (i = 0; i < pos; ++i) s[i] = acc[random () % len]; s[pos] = random () & BIG_CHAR; if (STRCHR (acc, s[pos])) s[pos] = '\0'; else { for (i = pos + 1; i < pos + 10; ++i) s[i] = random () & BIG_CHAR; s[i] = '\0'; } printf ("Length %4zd, alignment %2zd, acc len %2zd:", pos, align, len); FOR_EACH_IMPL (impl, 0) do_one_test (impl, s, acc, pos); putchar ('\n'); }
static bool parse_parameter(const TCHAR *str, const size_t len, const TCHAR *arg_name, bool *first, TCHAR *dest_buff, size_t dest_size) { if(*first) { *first = false; return false; } bool bSuccess = false; if((len > 1) && (str[0] == T('/'))) { TCHAR *buffer = new TCHAR[len]; memset(buffer, 0, sizeof(TCHAR) * len); STRNCPY(buffer, &str[1], len-1); TCHAR *offset = STRCHR(buffer, T('=')); if(offset != NULL) { offset[0] = T('\0'); if(STRICMP(buffer, arg_name) == 0) { bSuccess = true; STRNCPY(dest_buff, &offset[1], dest_size); dest_buff[dest_size-1] = T('\0'); } } else { if(STRICMP(buffer, arg_name) == 0) { bSuccess = true; dest_buff[0] = T('\0'); } } delete [] buffer; } return bSuccess; }
INT32 hourly_page_hits(struct mapping *urls, struct mapping *pages, struct mapping *hits, struct multiset *pagexts, INT32 code) { INT32 i, e, len; struct svalue *sind; struct svalue *sval; struct pike_string *decoded; unsigned char *decode_buf; unsigned char *qmark; unsigned INT32 numpages = 0; struct keypair *k; decode_buf = malloc(MAX_LINE_LEN+1); MY_MAPPING_LOOP(urls, e, k) { sind = &k->ind; sval = &k->val; qmark = (unsigned char *)STRCHR(sind->u.string->str, '?'); if(qmark) { MEMCPY(decode_buf, sind->u.string->str, len = MIN(MAX_LINE_LEN, ((INT32)qmark - (INT32)sind->u.string->str - 1))); } else { MEMCPY(decode_buf, sind->u.string->str, len = MIN(MAX_LINE_LEN, sind->u.string->len)); } decoded = http_decode_string(decode_buf, len); if(ispage(decoded, pagexts)) { numpages += sval->u.integer; /* printf("\tPAGE: %5d\t%s\n", sval->u.integer, decoded->str);*/ mapaddstrnum(pages, decoded, sval); } else { /* printf("\tHIT: %5d\t%s\n", sval->u.integer, decoded->str);*/ mapaddstrnum(hits, decoded, sval); } free_string(decoded); }
STATIC BOOL IsIllegalCharacter(LPTSTR pszString) { // TCHAR chTemp; // BOOL fRetVal; // // Return FALSE immediately for a null character // if (*pszString == TCHAR_EOS) { return FALSE; } // // If the character is a single-byte character, we can simply see if // it's illegal by calling strchrf() on the illegal character array. // If it's a double-byte character, we have to do it the slower way // (with strcspnf). // // if (!IS_LEAD_BYTE(*pszString)) { return (STRCHR(szIllegalChars, *pszString) != NULL); // } else { // // // // // We set the character after the double-byte character to the // // null character, to speed things up. // // // // chTemp = pszString[2]; // pszString[2] = TCHAR_EOS; // fRetVal = STRCSPN(pszString, szIllegalChars) == 0; // pszString[2] = chTemp; // // return fRetVal; // } }
void do_bigsay(COMMAND_ARGS) { /* * on_msg checks CARGS + CAXS */ BigC *bigc; Strp *sp; char output[MSGLEN]; char *pt,*tail,*temp; int i,x,sz; #ifdef DEBUG debug("(do_bigsay) rest = \"%s\"\n",rest); #endif /* DEBUG */ Strcpy(output,BIGSAY_DEFAULTFONT); if (read_bigcharset(output) < 0) { to_user(from,ERR_FILEOPEN,output); return; } for(i=0;i<charheight;i++) { sz = 0; *output = 0; tail = output; for(pt=rest;*pt;pt++) { /* find a matching character */ if (*pt == ' ') { x = spacewidth; while(x--) *(tail++) = ' '; *tail = 0; continue; } for(bigc=fontlist;bigc;bigc=bigc->next) { if (STRCHR(bigc->chars,*pt)) { sp = bigc->data; for(x=0;x<i;x++) if (sp) sp = sp->next; temp = Strcat(tail,sp->p); while(temp < (tail + bigc->width)) *(temp++) = ' '; if (pt[1]) { x = kerning; while(x--) *(temp++) = ' '; } *temp = 0; tail = temp; break; } } } temp = NULL; for(tail=output;*tail;tail++) { if (!temp && *tail == ' ') temp = tail; if (*tail != ' ') temp = NULL; } if (temp) { if (temp == output) temp++; *temp = 0; } to_user_q(from,FMT_PLAIN,output); } }
int WildcharsEnumerator::isWildchars(const char *filename) { return (STRCHR(filename, '*') || STRCHR(filename, '?')); }
/* EXTPROTO */ char * index(const char *s, int c) { return STRCHR(s, c); }
static void do_random_tests (void) { size_t i, j, n, align, pos, len, rlen; RES_TYPE result; int c; UCHAR *p = (UCHAR *) (buf1 + page_size) - 512; UCHAR *rej; for (n = 0; n < ITERATIONS; n++) { align = random () & 15; pos = random () & 511; if (pos + align >= 511) pos = 510 - align - (random () & 7); len = random () & 511; if (pos >= len && (random () & 1)) len = pos + 1 + (random () & 7); if (len + align >= 512) len = 511 - align - (random () & 7); if (random () & 1) rlen = random () & 63; else rlen = random () & 15; rej = (UCHAR *) (buf2 + page_size) - rlen - 1 - (random () & 7); for (i = 0; i < rlen; ++i) { rej[i] = random () & BIG_CHAR; if (!rej[i]) rej[i] = random () & BIG_CHAR; if (!rej[i]) rej[i] = 1 + (random () & SMALL_CHAR); } rej[i] = '\0'; for (c = 1; c <= BIG_CHAR; ++c) if (STRCHR ((CHAR *) rej, c) == NULL) break; j = (pos > len ? pos : len) + align + 64; if (j > 512) j = 512; for (i = 0; i < j; i++) { if (i == len + align) p[i] = '\0'; else if (i == pos + align) p[i] = rej[random () % (rlen + 1)]; else if (i < align || i > pos + align) p[i] = random () & BIG_CHAR; else { p[i] = random () & BIG_CHAR; if (STRCHR ((CHAR *) rej, p[i])) { p[i] = random () & BIG_CHAR; if (STRCHR ((CHAR *) rej, p[i])) p[i] = c; } } } result = STRPBRK_RESULT ((CHAR *) (p + align), pos < len ? pos : len); FOR_EACH_IMPL (impl, 1) if (CALL (impl, (CHAR *) (p + align), (CHAR *) rej) != result) { error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %p, %zd, %zd, %zd) %p != %p", n, impl->name, align, rej, rlen, pos, len, (void *) CALL (impl, (CHAR *) (p + align), (CHAR *) rej), (void *) result); ret = 1; } } }
/* EXTPROTO */ int rxvt_scale_pixmap(rxvt_t *r, int page, const char *geom) { int flags, changed = 0; int x = 0, y = 0; unsigned int w = 0, h = 0; unsigned int n; char *p, *str; bgPixmap_t *bgpixmap = &(PVTS(r, page)->bg); #define MAXLEN_GEOM sizeof("[1000x1000+1000+1000]") if (geom == NULL) return 0; str = rxvt_malloc(MAXLEN_GEOM + 1); if (!STRCMP(geom, "?")) { sprintf(str, "[%dx%d+%d+%d]", /* can't presume snprintf() ! */ min(bgpixmap->w, 9999), min(bgpixmap->h, 9999), min(bgpixmap->x, 9999), min(bgpixmap->y, 9999)); rxvt_xterm_seq(r, page, XTerm_title, str, CHAR_ST); rxvt_free(str); return 0; } if ((p = STRCHR(geom, ';')) == NULL) p = STRCHR(geom, '\0'); n = (p - geom); if (n <= MAXLEN_GEOM) { STRNCPY(str, geom, n); str[n] = '\0'; flags = XParseGeometry(str, &x, &y, &w, &h); if (!flags) { flags |= WidthValue; w = 0; } /* default is tile */ if (flags & WidthValue) { if (!(flags & XValue)) x = 50; if (!(flags & HeightValue)) h = w; if (w && !h) { w = (bgpixmap->w * w) / 100; h = bgpixmap->h; } else if (h && !w) { w = bgpixmap->w; h = (bgpixmap->h * h) / 100; } if (w > 1000) w = 1000; if (h > 1000) h = 1000; if (bgpixmap->w != (short)w) { bgpixmap->w = (short)w; changed++; } if (bgpixmap->h != (short)h) { bgpixmap->h = (short)h; changed++; } } if (!(flags & YValue)) { if (flags & XNegative) flags |= YNegative; y = x; } if (!(flags & WidthValue) && geom[0] != '=') { x += bgpixmap->x; y += bgpixmap->y; } else { if (flags & XNegative) x += 100; if (flags & YNegative) y += 100; } MIN_IT(x, 100); MIN_IT(y, 100); MAX_IT(x, 0); MAX_IT(y, 0); if (bgpixmap->x != x) { bgpixmap->x = x; changed++; } if (bgpixmap->y != y) { bgpixmap->y = y; changed++; } } rxvt_free(str); return changed; }
/* EXTPROTO */ Pixmap rxvt_load_pixmap(rxvt_t *r, const char *file, long* pwidth, long* pheight) { char* f; int flen; #if defined(USE_JPEG) || defined(USE_PNG) long w = 0, h = 0; #endif XpmAttributes xpm_attr; Pixmap pixmap; UNSET_PIXMAP(pixmap); assert(file != NULL); if ((char) 0 == *file) { /* No file to load */ return None; } xpm_attr.closeness = 30000; xpm_attr.colormap = XCMAP; xpm_attr.visual = XVISUAL; xpm_attr.depth = XDEPTH; xpm_attr.valuemask = (XpmCloseness | XpmColormap | XpmVisual | XpmDepth | XpmSize | XpmReturnPixels); /* search environment variables here too */ if (NULL == (f = (char*) rxvt_File_find (file, ".xpm", r->h->rs[Rs_path])) #ifdef USE_JPEG && NULL == (f = (char*) rxvt_File_find (file, ".jpg", r->h->rs[Rs_path])) && NULL == (f = (char*) rxvt_File_find (file, ".jpeg", r->h->rs[Rs_path])) #endif #ifdef USE_PNG && NULL == (f = (char*) rxvt_File_find (file, ".png", r->h->rs[Rs_path])) #endif ) { char *p; /* semi-colon delimited */ if (NULL == (p = STRCHR(file, ';'))) p = STRCHR(file, '\0'); rxvt_msg (DBG_ERROR, DBG_PIXMAP, "couldn't load image file \"%.*s\"", (p - file), file); return None; } flen = STRLEN (f); #ifdef USE_JPEG if ((flen >= 4 && !STRNCASECMP (f+flen-4, ".jpg", 4)) || (flen >= 5 && !STRNCASECMP (f+flen-5, ".jpeg",5))) { GC gc = DefaultGC (r->Xdisplay, XSCREEN); if (!JpegReadFileToPixmap (r->Xdisplay, XROOT, gc, f, &pixmap, &w, &h)) { *pwidth = w; *pheight = h; } } else #endif #ifdef USE_PNG if (flen >= 4 && !STRNCASECMP (f+flen-4, ".png", 4)) { GC gc = DefaultGC (r->Xdisplay, XSCREEN); if (!PngReadFileToPixmap (r->Xdisplay, XROOT, gc, f, &pixmap, &w, &h)) { *pwidth = w; *pheight = h; } } else #endif #ifdef HAVE_LIBXPM if (!XpmReadFileToPixmap(r->Xdisplay, XROOT, f, &pixmap, NULL, &xpm_attr)) { *pwidth = xpm_attr.width; *pheight = xpm_attr.height; } #endif { /* empty to suppress compile error */ } rxvt_free(f); if (NOT_PIXMAP(pixmap)) { char *p; /* semi-colon delimited */ if ((p = STRCHR(file, ';')) == NULL) p = STRCHR(file, '\0'); rxvt_msg (DBG_ERROR, DBG_PIXMAP, "couldn't load image file \"%.*s\"", (p - file), file); } return (pixmap); }
DBGSTATIC NET_API_STATUS GetCmdValue( IN DWORD argc, IN LPTSTR argv[], IN LPTSTR SwitchName, IN OUT LPWSTR * ParmValue ) /*++ Routine Description : read a parameter from command line Arguments : argc, argv : command line parameters SwitchName : parameter name Return Value : return NO_ERROR if successfully retrive the requested parameter and ParmValue is set appropriately. return ERROR_INVALID_PARAMETER if it can't retrive the parameter. ReplFinish is called to terminate service. --*/ { NET_API_STATUS ApiStatus = NO_ERROR; // innocent until proven guilty LPTSTR SepaPtr; DWORD i; *ParmValue = NULL; NetpAssert( SwitchName[0] == TCHAR_FWDSLASH ); for(i = 0; i < argc; i++) { SepaPtr = STRCHR(argv[i], (TCHAR) ':'); if (SepaPtr == NULL) { ReplConfigReportBadParmValue( SwitchName, NULL ); ApiStatus = ERROR_INVALID_PARAMETER; break; } if (STRNICMP(argv[i], SwitchName, (SepaPtr - argv[i])) == 0) { *ParmValue = NetpAllocWStrFromTStr( SepaPtr + 1 ); // skip colon. if(*ParmValue == NULL) { NetpKdPrint(( "[REPL] GetCmdValue: out of memory.\n" )); ReplFinish( SERVICE_UIC_CODE( SERVICE_UIC_RESOURCE, SERVICE_UIC_M_MEMORY), NULL); ApiStatus = ERROR_NOT_ENOUGH_MEMORY; break; } break; } } IF_DEBUG(REPL) { NetpKdPrint(( "GetCmdValue: returning " FORMAT_API_STATUS " while searching for '" FORMAT_LPTSTR "',\n", ApiStatus, SwitchName )); NetpKdPrint(( " *ParmValue = " FORMAT_LPVOID ".\n", (LPVOID) *ParmValue)); } return( ApiStatus ); }
/* mode 0,1: Default mode. 2: Remove the directory path of input_filename, then add output_dir. 3: Replace directory separator characters ('/','\',':') with '_', then add output_dir. */ char *create_auto_output_name(const char *input_filename, char *ext_str, char *output_dir, int mode) { char *output_filename; char *ext, *p; int32 dir_len = 0; char ext_str_tmp[65]; output_filename = (char *)safe_malloc((output_dir?strlen(output_dir):0) + strlen(input_filename) + 6); if(output_filename==NULL) return NULL; output_filename[0] = '\0'; if(output_dir!=NULL && (mode==2 || mode==3)) { strcat(output_filename,output_dir); dir_len = strlen(output_filename); #ifndef __W32__ if(dir_len>0 && output_filename[dir_len-1]!=PATH_SEP){ #else if(dir_len>0 && output_filename[dir_len-1]!='/' && output_filename[dir_len-1]!='\\' && output_filename[dir_len-1]!=':'){ #endif strcat(output_filename,PATH_STRING); dir_len++; } } strcat(output_filename, input_filename); if((ext = strrchr(output_filename, '.')) == NULL) ext = output_filename + strlen(output_filename); else { /* strip ".gz" */ if(strcasecmp(ext, ".gz") == 0) { *ext = '\0'; if((ext = strrchr(output_filename, '.')) == NULL) ext = output_filename + strlen(output_filename); } } /* replace '\' , '/' or PATH_SEP between '#' and ext */ p = strrchr(output_filename,'#'); if(p!=NULL){ char *p1; #ifdef _mbsrchr #define STRCHR(a,b) _mbschr(a,b) #else #define STRCHR(a,b) strchr(a,b) #endif #ifndef __W32__ p1 = p + 1; while((p1 = STRCHR(p1,PATH_SEP))!=NULL && p1<ext){ *p1 = '_'; p1++; } #else p1 = p + 1; while((p1 = STRCHR(p1,'\\'))!=NULL && p1<ext){ *p1 = '_'; p1++; } p1 = p; while((p1 = STRCHR(p1,'/'))!=NULL && p1<ext){ *p1 = '_'; p1++; } #endif #undef STRCHR } /* replace '.' and '#' before ext */ for(p = output_filename; p < ext; p++) #ifndef __W32__ if(*p == '.' || *p == '#') #else if(*p == '#') #endif *p = '_'; if(mode==2){ char *p1,*p2,*p3; #ifndef __W32__ p = strrchr(output_filename+dir_len,PATH_SEP); #else #ifdef _mbsrchr #define STRRCHR _mbsrchr #else #define STRRCHR strrchr #endif p1 = STRRCHR(output_filename+dir_len,'/'); p2 = STRRCHR(output_filename+dir_len,'\\'); p3 = STRRCHR(output_filename+dir_len,':'); #undef STRRCHR p1>p2 ? (p1>p3 ? (p = p1) : (p = p3)) : (p2>p3 ? (p = p2) : (p = p3)); #endif if(p!=NULL){ for(p1=output_filename+dir_len,p2=p+1; *p2; p1++,p2++) *p1 = *p2; *p1 = '\0'; } } if(mode==3){ for(p=output_filename+dir_len; *p; p++) #ifndef __W32__ if(*p==PATH_SEP) #else if(*p=='/' || *p=='\\' || *p==':') #endif *p = '_'; } if((ext = strrchr(output_filename, '.')) == NULL) ext = output_filename + strlen(output_filename); if(*ext){ strncpy(ext_str_tmp,ext_str,64); ext_str_tmp[64]=0; if(isupper(*(ext + 1))){ for(p=ext_str_tmp;*p;p++) *p = toupper(*p); *p = '\0'; } else { for(p=ext_str_tmp;*p;p++) *p = tolower(*p); *p = '\0'; } strcpy(ext+1,ext_str_tmp); } return output_filename; }
void do_help(COMMAND_ARGS) { char line[MSGLEN]; char *pt; int i,level,axs; int cur,nxt,count,ci,tl; int in; if (dcc_only_command(from)) return; axs = get_maxaccess(from); if (!*rest) { cur = -1; *line = 0; help_loop: count = 0; nxt = OWNERLEVEL; for(i=0;mcmd[i].name;i++) { tl = acmd[i]; if ((tl < nxt) && (tl > cur)) nxt = tl; if (tl != cur) continue; if (count == 0) sprintf(line,"\037Level %3i\037: ",cur); count++; } if (!count) { cur = nxt; goto help_loop; } ci = count; for(i=0;mcmd[i].name;i++) { tl = acmd[i]; if (tl != cur) continue; if (ci != count) Strcat(line,", "); print_help(from,line,strlen(mcmd[i].name)); if (*line == 0) Strcpy(line," "); Strcat(line,(char*)mcmd[i].name); count--; } print_help(from,line,500); if ((cur != OWNERLEVEL) && (nxt <= axs)) cur = nxt; else return; goto help_loop; } level = a2i(rest); if (!errno) { if ((level > axs) || (level < 0)) level = axs; to_user(from,"\037Commands available at Level %i:\037",level); *line = 0; ci = 0; for(i=0;mcmd[i].name;i++) { if (acmd[i] <= level) { if (ci != 0) Strcat(line,", "); ci++; print_help(from,line,strlen(mcmd[i].name)); Strcat(line,(char*)mcmd[i].name); } } if (ci) print_help(from,line,58); else to_user(from,TEXT_NONE); return; } if (STRCHR(rest,'*')) { line[0] = 0; ci = 0; to_user(from,"\037Commands that match query %s\037:",rest); for(i=0;mcmd[i].name;i++) { if ((!matches(rest,(char*)mcmd[i].name)) && (acmd[i] <= axs)) { if (ci != 0) Strcat(line,", "); ci++; print_help(from,line,strlen(mcmd[i].name)); Strcat(line,(char*)mcmd[i].name); } } if (ci) print_help(from,line,500); else to_user(from,TEXT_NONE); return; } /* * We dont want to show help for "../../../../../../etc/passwd" */ if (!is_safepath(rest)) return; pt = Strcpy(line,HELPDIR); for(i=0;(rest[i]);i++) { if (rest[i] >= 'a' && rest[i] <= 'z') *pt = rest[i] - 0x20; else *pt = rest[i]; pt++; } *pt = 0; #ifdef DEBUG debug("(do_help) help file check: %s\n",line); #endif /* DEBUG */ if ((in = open(line,O_RDONLY)) < 0) { to_user(from,"No help found for \"%s\"",rest); return; } #ifdef DEBUG debug("(do_help) helpfile for = '%s'\n",rest); #endif /* DEBUG */ table_buffer("\037Help on %s\037",rest); level = access_needed(rest); if (level > 200) table_buffer("Level needed: Command disabled"); else if (level > 0) table_buffer("Level needed: %i",level); for(i=0;ulist[i].command;i++) { if (!Strcasecmp(rest,ulist[i].command)) { pt = (ulist[i].usage) ? ulist[i].usage : ""; table_buffer("Usage: %s %s",ulist[i].command,pt); break; } } readline(in,&do_help_callback); /* readline closes in */ table_send(from,0); }
int begin_redirect(char *from, char *args) { char *pt,*nick; if (!args) return(0); pt = STRCHR(args,'>'); if (pt) { *pt = 0; nick = pt+1; pt--; while((pt > args) && (*pt == ' ')) { *pt = 0; pt--; } while(*nick == ' ') nick++; if (*nick) { #ifdef DEBUG debug("(begin_redirect) from %s --> %s\n",from,nick); #endif /* DEBUG */ if (ischannel(nick)) { if (find_channel_ac(nick)) { redirect.to = stringdup(nick); redirect.method = R_PRIVMSG; return(0); } else { to_user(from,ERR_CHAN,nick); return(-1); } } if (*nick == '>') { nick++; while(*nick == ' ') nick++; if (!*nick) { to_user(from,"Missing name for redirect."); return(-1); } if (is_safepath(nick,FILE_MAY_EXIST) != FILE_IS_SAFE) // redirect output is appended { to_user(from,"Bad filename."); return(-1); } redirect.to = stringdup(nick); redirect.method = R_FILE; return(0); } if ((pt = find_nuh(nick))) { redirect.to = stringdup(nick); redirect.method = R_NOTICE; return(0); } else { to_user(from,TEXT_UNKNOWNUSER,nick); return(-1); } } else { to_user(from,"Bad redirect"); return(-1); } } return(0); }
static int do_test (void) { int size = sysconf (_SC_PAGESIZE); int nchars = size / sizeof (CHAR); CHAR *adr; CHAR *dest; int result = 0; adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); dest = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (adr == MAP_FAILED || dest == MAP_FAILED) { if (errno == ENOSYS) puts ("No test, mmap not available."); else { printf ("mmap failed: %m"); result = 1; } } else { int inner, middle, outer; mprotect (adr, size, PROT_NONE); mprotect (adr + 2 * nchars, size, PROT_NONE); adr += nchars; mprotect (dest, size, PROT_NONE); mprotect (dest + 2 * nchars, size, PROT_NONE); dest += nchars; MEMSET (adr, L('T'), nchars); /* strlen/wcslen test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) { adr[inner] = L('\0'); if (STRLEN (&adr[outer]) != (size_t) (inner - outer)) { printf ("%s flunked for outer = %d, inner = %d\n", STRINGIFY (STRLEN), outer, inner); result = 1; } adr[inner] = L('T'); } } /* strnlen/wcsnlen test */ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) { for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) { adr[inner] = L('\0'); if (STRNLEN (&adr[outer], inner - outer + 1) != (size_t) (inner - outer)) { printf ("%s flunked for outer = %d, inner = %d\n", STRINGIFY (STRNLEN), outer, inner); result = 1; } adr[inner] = L('T'); } } for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) { for (inner = MAX (outer, nchars - 64); inner <= nchars; ++inner) { if (STRNLEN (&adr[outer], inner - outer) != (size_t) (inner - outer)) { printf ("%s flunked bounded for outer = %d, inner = %d\n", STRINGIFY (STRNLEN), outer, inner); result = 1; } } } /* strchr/wcschr test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) { for (inner = middle; inner < nchars; ++inner) { adr[middle] = L('V'); adr[inner] = L('\0'); CHAR *cp = STRCHR (&adr[outer], L('V')); if ((inner == middle && cp != NULL) || (inner != middle && (cp - &adr[outer]) != middle - outer)) { printf ("%s flunked for outer = %d, middle = %d, " "inner = %d\n", STRINGIFY (STRCHR), outer, middle, inner); result = 1; } adr[inner] = L('T'); adr[middle] = L('T'); } } } /* Special test. */ adr[nchars - 1] = L('\0'); if (STRCHR (&adr[nchars - 1], L('\n')) != NULL) { printf ("%s flunked test of empty string at end of page\n", STRINGIFY (STRCHR)); result = 1; } /* strrchr/wcsrchr test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) { for (inner = middle; inner < nchars; ++inner) { adr[middle] = L('V'); adr[inner] = L('\0'); CHAR *cp = STRRCHR (&adr[outer], L('V')); if ((inner == middle && cp != NULL) || (inner != middle && (cp - &adr[outer]) != middle - outer)) { printf ("%s flunked for outer = %d, middle = %d, " "inner = %d\n", STRINGIFY (STRRCHR), outer, middle, inner); result = 1; } adr[inner] = L('T'); adr[middle] = L('T'); } } } /* memchr test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) { adr[middle] = L('V'); CHAR *cp = MEMCHR (&adr[outer], L('V'), 3 * size); if (cp - &adr[outer] != middle - outer) { printf ("%s flunked for outer = %d, middle = %d\n", STRINGIFY (MEMCHR), outer, middle); result = 1; } adr[middle] = L('T'); } } for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) { CHAR *cp = MEMCHR (&adr[outer], L('V'), nchars - outer); if (cp != NULL) { printf ("%s flunked for outer = %d\n", STRINGIFY (MEMCHR), outer); result = 1; } } /* These functions only exist for single-byte characters. */ #ifndef WCSTEST /* rawmemchr test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) { adr[middle] = L('V'); CHAR *cp = rawmemchr (&adr[outer], L('V')); if (cp - &adr[outer] != middle - outer) { printf ("%s flunked for outer = %d, middle = %d\n", STRINGIFY (rawmemchr), outer, middle); result = 1; } adr[middle] = L('T'); } } /* memrchr test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) { adr[middle] = L('V'); CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer); if (cp - &adr[outer] != middle - outer) { printf ("%s flunked for outer = %d, middle = %d\n", STRINGIFY (memrchr), outer, middle); result = 1; } adr[middle] = L('T'); } } for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) { CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer); if (cp != NULL) { printf ("%s flunked for outer = %d\n", STRINGIFY (memrchr), outer); result = 1; } } #endif /* strcpy/wcscpy test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) { adr[inner] = L('\0'); if (STRCPY (dest, &adr[outer]) != dest || STRLEN (dest) != (size_t) (inner - outer)) { printf ("%s flunked for outer = %d, inner = %d\n", STRINGIFY (STRCPY), outer, inner); result = 1; } adr[inner] = L('T'); } } /* strcmp/wcscmp tests */ for (outer = 1; outer < 32; ++outer) for (middle = 0; middle < 16; ++middle) { MEMSET (adr + middle, L('T'), 256); adr[256] = L('\0'); MEMSET (dest + nchars - outer, L('T'), outer - 1); dest[nchars - 1] = L('\0'); if (STRCMP (adr + middle, dest + nchars - outer) <= 0) { printf ("%s 1 flunked for outer = %d, middle = %d\n", STRINGIFY (STRCMP), outer, middle); result = 1; } if (STRCMP (dest + nchars - outer, adr + middle) >= 0) { printf ("%s 2 flunked for outer = %d, middle = %d\n", STRINGIFY (STRCMP), outer, middle); result = 1; } } /* strncmp/wcsncmp tests */ for (outer = 1; outer < 32; ++outer) for (middle = 0; middle < 16; ++middle) { MEMSET (adr + middle, L('T'), 256); adr[256] = L('\0'); MEMSET (dest + nchars - outer, L('T'), outer - 1); dest[nchars - 1] = L('U'); for (inner = 0; inner < outer; ++inner) { if (STRNCMP (adr + middle, dest + nchars - outer, inner) != 0) { printf ("%s 1 flunked for outer = %d, middle = %d, " "inner = %d\n", STRINGIFY (STRNCMP), outer, middle, inner); result = 1; } if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0) { printf ("%s 2 flunked for outer = %d, middle = %d, " "inner = %d\n", STRINGIFY (STRNCMP), outer, middle, inner); result = 1; } } if (STRNCMP (adr + middle, dest + nchars - outer, outer) >= 0) { printf ("%s 1 flunked for outer = %d, middle = %d, full\n", STRINGIFY (STRNCMP), outer, middle); result = 1; } if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0) { printf ("%s 2 flunked for outer = %d, middle = %d, full\n", STRINGIFY (STRNCMP), outer, middle); result = 1; } } /* strncpy/wcsncpy tests */ adr[nchars - 1] = L('T'); for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) { size_t len; for (len = 0; len < nchars - outer; ++len) { if (STRNCPY (dest, &adr[outer], len) != dest || MEMCMP (dest, &adr[outer], len) != 0) { printf ("outer %s flunked for outer = %d, len = %Zd\n", STRINGIFY (STRNCPY), outer, len); result = 1; } } } adr[nchars - 1] = L('\0'); for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) { size_t len; adr[inner] = L('\0'); for (len = 0; len < nchars - outer + 64; ++len) { if (STRNCPY (dest, &adr[outer], len) != dest || MEMCMP (dest, &adr[outer], MIN (inner - outer, len)) != 0 || (inner - outer < len && STRLEN (dest) != (inner - outer))) { printf ("%s flunked for outer = %d, inner = %d, " "len = %Zd\n", STRINGIFY (STRNCPY), outer, inner, len); result = 1; } if (STRNCPY (dest + 1, &adr[outer], len) != dest + 1 || MEMCMP (dest + 1, &adr[outer], MIN (inner - outer, len)) != 0 || (inner - outer < len && STRLEN (dest + 1) != (inner - outer))) { printf ("%s+1 flunked for outer = %d, inner = %d, " "len = %Zd\n", STRINGIFY (STRNCPY), outer, inner, len); result = 1; } } adr[inner] = L('T'); } } /* stpcpy/wcpcpy test */ for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner) { adr[inner] = L('\0'); if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer) { printf ("%s flunked for outer = %d, inner = %d\n", STRINGIFY (STPCPY), outer, inner); result = 1; } adr[inner] = L('T'); } } /* stpncpy/wcpncpy test */ adr[nchars - 1] = L('T'); for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) { size_t len; for (len = 0; len < nchars - outer; ++len) { if (STPNCPY (dest, &adr[outer], len) != dest + len || MEMCMP (dest, &adr[outer], len) != 0) { printf ("outer %s flunked for outer = %d, len = %Zd\n", STRINGIFY (STPNCPY), outer, len); result = 1; } } } adr[nchars - 1] = L('\0'); for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) { for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle) { adr[middle] = L('\0'); for (inner = 0; inner < nchars - outer; ++ inner) { if ((STPNCPY (dest, &adr[outer], inner) - dest) != MIN (inner, middle - outer)) { printf ("%s flunked for outer = %d, middle = %d, " "inner = %d\n", STRINGIFY (STPNCPY), outer, middle, inner); result = 1; } } adr[middle] = L('T'); } } /* memcpy/wmemcpy test */ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) for (inner = 0; inner < nchars - outer; ++inner) if (MEMCPY (dest, &adr[outer], inner) != dest) { printf ("%s flunked for outer = %d, inner = %d\n", STRINGIFY (MEMCPY), outer, inner); result = 1; } /* mempcpy/wmempcpy test */ for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) for (inner = 0; inner < nchars - outer; ++inner) if (MEMPCPY (dest, &adr[outer], inner) != dest + inner) { printf ("%s flunked for outer = %d, inner = %d\n", STRINGIFY (MEMPCPY), outer, inner); result = 1; } /* This function only exists for single-byte characters. */ #ifndef WCSTEST /* memccpy test */ memset (adr, '\0', nchars); for (outer = nchars; outer >= MAX (0, nchars - 128); --outer) for (inner = 0; inner < nchars - outer; ++inner) if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL) { printf ("memccpy flunked full copy for outer = %d, inner = %d\n", outer, inner); result = 1; } for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer) for (middle = 0; middle < nchars - outer; ++middle) { memset (dest, L('\2'), middle + 1); for (inner = 0; inner < middle; ++inner) { adr[outer + inner] = L('\1'); if (memccpy (dest, &adr[outer], '\1', middle + 128) != dest + inner + 1) { printf ("\ memccpy flunked partial copy for outer = %d, middle = %d, inner = %d\n", outer, middle, inner); result = 1; } else if (dest[inner + 1] != L('\2')) { printf ("\ memccpy copied too much for outer = %d, middle = %d, inner = %d\n", outer, middle, inner); result = 1; } adr[outer + inner] = L('\0'); }
/* * v_match -- % * Search to matching character. * * PUBLIC: int v_match(SCR *, VICMD *); */ int v_match(SCR *sp, VICMD *vp) { VCS cs; MARK *mp; size_t cno, len, off; int cnt, isempty, matchc, startc, (*gc)(SCR *, VCS *); CHAR_T *p; CHAR_T *cp; const CHAR_T *match_chars; /* * Historically vi would match (), {} and [] however * an update included <>. This is ok for editing HTML * but a pain in the butt for C source. * Making it an option lets the user decide what is 'right'. */ match_chars = VIP(sp)->mcs; /* * !!! * Historic practice; ignore the count. * * !!! * Historical practice was to search for the initial character in the * forward direction only. */ if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) { if (isempty) goto nomatch; return (1); } for (off = vp->m_start.cno;; ++off) { if (off >= len) { nomatch: msgq(sp, M_BERR, "184|No match character on this line"); return (1); } startc = p[off]; cp = STRCHR(match_chars, startc); if (cp != NULL) { cnt = cp - match_chars; matchc = match_chars[cnt ^ 1]; gc = cnt & 1 ? cs_prev : cs_next; break; } } cs.cs_lno = vp->m_start.lno; cs.cs_cno = off; if (cs_init(sp, &cs)) return (1); for (cnt = 1;;) { if (gc(sp, &cs)) return (1); if (cs.cs_flags != 0) { if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF) break; continue; } if (cs.cs_ch == startc) ++cnt; else if (cs.cs_ch == matchc && --cnt == 0) break; } if (cnt) { msgq(sp, M_BERR, "185|Matching character not found"); return (1); } vp->m_stop.lno = cs.cs_lno; vp->m_stop.cno = cs.cs_cno; /* * If moving right, non-motion commands move to the end of the range. * Delete and yank stay at the start. * * If moving left, all commands move to the end of the range. * * !!! * Don't correct for leftward movement -- historic vi deleted the * starting cursor position when deleting to a match. */ if (vp->m_start.lno < vp->m_stop.lno || (vp->m_start.lno == vp->m_stop.lno && vp->m_start.cno < vp->m_stop.cno)) vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop; else vp->m_final = vp->m_stop; /* * !!! * If the motion is across lines, and the earliest cursor position * is at or before any non-blank characters in the line, i.e. the * movement is cutting all of the line's text, and the later cursor * position has nothing other than whitespace characters between it * and the end of its line, the buffer is in line mode. */ if (!ISMOTION(vp) || vp->m_start.lno == vp->m_stop.lno) return (0); mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_start : &vp->m_stop; if (mp->cno != 0) { cno = 0; if (nonblank(sp, mp->lno, &cno)) return (1); if (cno < mp->cno) return (0); } mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_stop : &vp->m_start; if (db_get(sp, mp->lno, DBG_FATAL, &p, &len)) return (1); for (p += mp->cno + 1, len -= mp->cno; --len; ++p) if (!isblank(*p)) return (0); F_SET(vp, VM_LMODE); return (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); } } }