예제 #1
0
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;
}
예제 #2
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
}
예제 #3
0
파일: tst.c 프로젝트: NoSuchProcess/OrangeC
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'));
}
예제 #4
0
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();
}
예제 #5
0
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');
}
예제 #6
0
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);
}
예제 #7
0
파일: v_search.c 프로젝트: Alkzndr/freebsd
/*
 * 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);
}
예제 #8
0
파일: ACLStr.cpp 프로젝트: Fahrni/ACLLib
// 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
예제 #9
0
파일: v_search.c 프로젝트: Hooman3/minix
/*
 * 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);
}
예제 #10
0
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');
}
예제 #11
0
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;
}
예제 #12
0
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);
  }
예제 #13
0
파일: gettoken.c 프로젝트: shuowen/OpenNT
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;
//    }
}
예제 #14
0
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);
	}
}
예제 #15
0
int WildcharsEnumerator::isWildchars(const char *filename) {
  return (STRCHR(filename, '*') || STRCHR(filename, '?'));
}
예제 #16
0
파일: strings.c 프로젝트: WndSks/msys
/* EXTPROTO */
char           *
index(const char *s, int c)
{
    return STRCHR(s, c);
}
예제 #17
0
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;
	  }
    }
}
예제 #18
0
파일: pixmap.c 프로젝트: mcgrew/lxvt
/* 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;
}
예제 #19
0
파일: pixmap.c 프로젝트: mcgrew/lxvt
/* 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);
}
예제 #20
0
파일: parse.c 프로젝트: mingpen/OpenNT
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 );

}
예제 #21
0
파일: output.c 프로젝트: 1c0n/xbmc
/* 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;
}
예제 #22
0
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);
}
예제 #23
0
파일: spy.c 프로젝트: MadCamel/energymech
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);
}
예제 #24
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');
	      }
예제 #25
0
파일: v_match.c 프로젝트: lichray/nvi2
/*
 * 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);
}
예제 #26
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);
			}
	}
}