Esempio n. 1
0
/*
 *  This function forms a search string, to look for the best
 *  letter to underline in a menu item. It first tries the
 *  accelerator key, then the uppercase letters from the menu name,
 *  then the digits, and finally the lowercase letters.
 *  It ignores spaces.
 */
static void set_search_string(char *search, const char *name, int key)
{
    int source;
    int dest = 0;
    int mb_len;
    mbstate_t mb_st;

    /* handle a couple of special cases first */
    if (! string_diff(name, "Cut"))  search[dest++] = 't';
    if (! string_diff(name, "Exit")) search[dest++] = 'x';
    if (! string_diff(name, "?")) search[dest++] = '?';

    {
	/* If there is an '&' in the string, use the next letter first */
	char *p = strchr(name, '&');
	if (p && *(p+1)) search[dest++] = *(p+1);
    }

    /* add the accelerator key if it is in the name string */
    if (key) {
	key = toupper(key);
	if (find_char(key, name) >= 0)
	    search[dest++] = (char) key;
	else {
	    key = tolower(key);
	    if (find_char(key, name) >= 0)
		search[dest++] = (char) key;
	}
    }
    /* add the uppercase letters */
    for (source=0; name[source]; source++) {
	mbs_init(mb_st);
	mb_len = Rf_mbrtowc(NULL, name + source, MB_CUR_MAX,&mb_st);
	if (mb_len > 1) source += mb_len-1;
	else
	    if (isupper(name[source])) search[dest++] = name[source];
    }
    /* add the digits */
    for (source=0; name[source]; source++) {
	mbs_init(mb_st);
	mb_len = Rf_mbrtowc(NULL, name + source, MB_CUR_MAX,&mb_st);
	if (mb_len > 1) source += mb_len-1;
	else
	    if (isdigit(name[source])) search[dest++] = name[source];
    }
    /* add the lowercase letters */
    for (source=0; name[source]; source++) {
	mbs_init(mb_st);
	mb_len = Rf_mbrtowc(NULL, name + source, MB_CUR_MAX,&mb_st);
	if (mb_len > 1) source += mb_len-1;
	else
	    if (islower(name[source])) search[dest++] = name[source];
    }
    /* end the search string */
    search[dest] = '\0';
}
Esempio n. 2
0
static void substr(char *buf, const char *str, int ienc, int sa, int so)
{
/* Store the substring	str [sa:so]  into buf[] */
    int i, j, used;

    if (ienc == CE_UTF8) {
	const char *end = str + strlen(str);
	for (i = 0; i < so && str < end; i++) {
	    int used = utf8clen(*str);
	    if (i < sa - 1) { str += used; continue; }
	    for (j = 0; j < used; j++) *buf++ = *str++;
	}
    } else if (ienc == CE_LATIN1 || ienc == CE_BYTES) {
	for (str += (sa - 1), i = sa; i <= so; i++) *buf++ = *str++;
    } else {
	if (mbcslocale && !strIsASCII(str)) {
	    const char *end = str + strlen(str);
	    mbstate_t mb_st;
	    mbs_init(&mb_st);
	    for (i = 1; i < sa; i++) str += Mbrtowc(NULL, str, MB_CUR_MAX, &mb_st);
	    for (i = sa; i <= so && str < end; i++) {
		used = (int) Mbrtowc(NULL, str, MB_CUR_MAX, &mb_st);
		for (j = 0; j < used; j++) *buf++ = *str++;
	    }
	} else
	    for (str += (sa - 1), i = sa; i <= so; i++) *buf++ = *str++;
    }
    *buf = '\0';
}
Esempio n. 3
0
/*
 *  Look through the list of siblings of the given object, and
 *  find a shortcut key from the search string which hasn't already
 *  been used by some other object. Return the valid shortcut char,
 *  or else zero if we can't find one.
 */
static int find_shortcut(object me, char *search)
{
    int source;
    object first, obj;

    first = me->parent->child;

    for (source = 0; search[source]; source++)
    {
	int mb_len;
	mbstate_t mb_st;
	mbs_init(mb_st);
	mb_len = Rf_mbrtowc(NULL, search + source, MB_CUR_MAX, &mb_st);
	if ( mb_len > 1 ) {
	    source += mb_len - 1;
	} else
	    /* for each character in the search string */
	    /* look through every sibling object */

	    for (obj = first; obj; obj = obj->next)
	    {
		if (obj == me) /* at end of list, success! */
		    return search[source];

		/* use uppercase comparisons */
		if (obj->shortcut == toupper(search[source]))
		    break; /* can't use this shortcut */

	    }
    }

    return 0;
}
Esempio n. 4
0
static void
gl_addchar(int c)
      
/* adds the character c to the input buffer at current location */
{
    int  i;

    if (gl_cnt >= BUF_SIZE - 2) {
            gl_putc('\a');
            return; 
    }
    if(mbcslocale) {
	mbstate_t mb_st;
	wchar_t wc;
	char s[9]; /* only 3 needed */
	int res;
	int clen ;
      
	s[0] = c;
	clen = 1;
	res = 0;
	/* This is a DBCS locale, so input is 1 or 2 bytes.
	   This loop should not be necessary.
	 */
	if((unsigned int) c >= (unsigned int) 0x80) {
            while(clen <= MB_CUR_MAX) {
	        mbs_init(&mb_st);
	        res = mbrtowc(&wc, s, clen, &mb_st);
	        if(res >= 0) break;
	        if(res == -1) 
		    gl_error("invalid multibyte character in mbcs_get_next");
  	        /* so res == -2 */
	        c = gl_getc();
	        if(c == EOF) 
		    gl_error("EOF whilst reading MBCS char");
	        s[clen++] = c;
	    } /* we've tried enough, so must be complete or invalid by now */
	}
	if( res >= 0 ) {
	    if (!(gl_overwrite == 0 || gl_pos == gl_cnt))  
		gl_del(0); 
	    for (i = gl_cnt; i >= gl_pos; i--)
                gl_buf[i+clen] = gl_buf[i];
	    for (i = 0; i < clen; i++)
                gl_buf[gl_pos + i] = s[i];
	    gl_fixup(gl_prompt, gl_pos, gl_pos+clen);
	}
       
    } else
	if (gl_overwrite == 0 || gl_pos == gl_cnt) {
	    for (i = gl_cnt; i >= gl_pos; i--)
		gl_buf[i+1] = gl_buf[i];
	    gl_buf[gl_pos] = (char) c;
	    gl_fixup(gl_prompt, gl_pos, gl_pos+1);
	} else {
	    gl_buf[gl_pos] = (char) c;
	    gl_extent = 1;
	    gl_fixup(gl_prompt, gl_pos, gl_pos+1);
	}
}
Esempio n. 5
0
static void
gl_transpose(void)
/* switch character under cursor and to left of cursor */
{
    int    c;

    if (gl_pos > 0 && gl_cnt > gl_pos) {
	if(mbcslocale) {
	    int l_len = 0;
	    int r_len = 0;
	    int i = 0;
	    int j = 0;
	    mbstate_t mb_st;

	    mbs_init(&mb_st);
	    for (i = 0; i < gl_pos;) {
		l_len = mbrlen(gl_buf+i, MB_CUR_MAX, &mb_st);
		i += l_len;
	    }
	    mbs_init(&mb_st);
	    r_len = mbrlen(gl_buf+gl_pos, MB_CUR_MAX, &mb_st);
	    for (i = 0; i < r_len; i++) {
		for(j = 0; j < l_len; j++) {
		    c = gl_buf[gl_pos+i-j];
		    gl_buf[gl_pos+i-j] = gl_buf[gl_pos+i-j-1];
		    gl_buf[gl_pos+i-j-1] = (char)c;
		}
	    }
	    gl_extent = l_len + r_len;
	    gl_fixup(gl_prompt, gl_pos - l_len, gl_pos + (r_len - l_len)); 
	} else {
	    c = gl_buf[gl_pos-1];
	    gl_buf[gl_pos-1] = gl_buf[gl_pos];
	    gl_buf[gl_pos] = (char) c;
	    gl_extent = 2;
	    gl_fixup(gl_prompt, gl_pos-1, gl_pos);
	}
    } else
	gl_beep();
}
Esempio n. 6
0
/*
 *  Take "Open..." and 'O' and produce the string "Open...\tCtrl+O".
 *  This function also sets an object's shortcut key, which is the
 *  underlined letter in a menu item in Windows or X-Windows.
 */
static void setmenustring(object obj, char *buf, const char *name, int key)
{
    char search[256];
    int ch, where, source, dest = 0;
    char *extra = "\tCtrl+";

    set_search_string(search, name, key);
    ch = find_shortcut(obj, search);

    if (ch) /* found a valid shortcut key */
    {
	obj->shortcut = toupper(ch); /* case-insensitive */
	where = find_char(ch, name);

	for (source=0; source < where; source++)
	{
	    int mb_len;
	    int i;
	    mbstate_t mb_st;
	    mbs_init(mb_st);
	    mb_len = Rf_mbrtowc(NULL, name + source, MB_CUR_MAX, &mb_st);
	    if ( mb_len > 1 ) {
		for (i = 0 ; i < mb_len ; i++)
		    buf[dest++] = name[source+i];
		source += mb_len-1;
	    } else if(name[source] == '&') {
		/* skip it */
	    } else
		buf[dest++] = name[source];
	}
	buf[dest++] = '&';
	for (; name[source]; source++)
	    buf[dest++] = name[source];
    }
    else /* no shortcut key, just copy the name string except '&' */
    {
	for (source = 0; name[source]; source++)
	    if(name[source] != '&') buf[dest++] = name[source];
    }

    if (key) {
	for (source=0; extra[source]; source++)
	    buf[dest++] = extra[source];
	buf[dest++] = key;
    }

    buf[dest] = '\0';
}
Esempio n. 7
0
File: rui.c Progetto: Maxsl/r-source
/* We need to handle \ in paths which are to be passed to R code.
   Since these can include \\ for network drives, we cannot just use /,
   although we did prior to R 2.4.0.

   MBCS-aware since 2.4.0.
 */
static void double_backslashes(char *s, char *out)
{
    char *p = s;

    int i;
    if(mbcslocale) {
	mbstate_t mb_st; int used;
	mbs_init(&mb_st);
	while((used = Mbrtowc(NULL, p, MB_CUR_MAX, &mb_st))) {
	    if(*p == '\\') *out++ = '\\';
	    for(i = 0; i < used; i++) *out++ = *p++;
	}
    } else
	for (; *p; p++)
	    if (*p == '\\') {*out++ = *p; *out++ = *p;} else *out++ = *p;
    *out = '\0';
}
Esempio n. 8
0
static void
gl_del(int loc)
/*
 * Delete a character.  The loc variable can be:
 *    -1 : delete character to left of cursor
 *     0 : delete character under cursor
 */
{
   int i;

   if(mbcslocale) {
       int mb_len;
       mbstate_t mb_st;
       wchar_t wc;

       mb_len=0;
       mbs_init(&mb_st);
   
       if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
	   for(i = 0; i<= gl_pos + loc;) {
	       mbrtowc(&wc,gl_buf+i, MB_CUR_MAX, &mb_st);
	       mb_len = Ri18n_wcwidth(wc);
	       i += (wc==0) ? 0 : mb_len;
	   }
	   for (i = gl_pos+(loc*mb_len); i <= gl_cnt - mb_len; i++)
	       gl_buf[i] = gl_buf[i + mb_len];
	   gl_fixup(gl_prompt,gl_pos+(loc * mb_len) , gl_pos+(loc * mb_len));
       } else
	   gl_beep();
   } else   
       if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
	   for (i = gl_pos+loc; i < gl_cnt; i++)
	       gl_buf[i] = gl_buf[i+1];
	   gl_fixup(gl_prompt, gl_pos+loc, gl_pos+loc);
       } else
	   gl_beep();
}
Esempio n. 9
0
SEXP attribute_hidden do_makenames(SEXP call, SEXP op, SEXP args, SEXP env)
{
    SEXP arg, ans;
    R_xlen_t i, n;
    int l, allow_;
    char *p, *tmp = NULL, *cbuf;
    const char *This;
    Rboolean need_prefix;
    const void *vmax;

    checkArity(op ,args);
    arg = CAR(args);
    if (!isString(arg))
	error(_("non-character names"));
    n = XLENGTH(arg);
    allow_ = asLogical(CADR(args));
    if (allow_ == NA_LOGICAL)
	error(_("invalid '%s' value"), "allow_");
    PROTECT(ans = allocVector(STRSXP, n));
    vmax = vmaxget();
    for (i = 0 ; i < n ; i++) {
	This = translateChar(STRING_ELT(arg, i));
	l = (int) strlen(This);
	/* need to prefix names not beginning with alpha or ., as
	   well as . followed by a number */
	need_prefix = FALSE;
	if (mbcslocale && This[0]) {
	    int nc = l, used;
	    wchar_t wc;
	    mbstate_t mb_st;
	    const char *pp = This;
	    mbs_init(&mb_st);
	    used = (int) Mbrtowc(&wc, pp, MB_CUR_MAX, &mb_st);
	    pp += used; nc -= used;
	    if (wc == L'.') {
		if (nc > 0) {
		    Mbrtowc(&wc, pp, MB_CUR_MAX, &mb_st);
		    if (iswdigit(wc))  need_prefix = TRUE;
		}
	    } else if (!iswalpha(wc)) need_prefix = TRUE;
	} else {
	    if (This[0] == '.') {
		if (l >= 1 && isdigit(0xff & (int) This[1])) need_prefix = TRUE;
	    } else if (!isalpha(0xff & (int) This[0])) need_prefix = TRUE;
	}
	if (need_prefix) {
	    tmp = Calloc(l+2, char);
	    strcpy(tmp, "X");
	    strcat(tmp, translateChar(STRING_ELT(arg, i)));
	} else {
	    tmp = Calloc(l+1, char);
	    strcpy(tmp, translateChar(STRING_ELT(arg, i)));
	}
	if (mbcslocale) {
	    /* This cannot lengthen the string, so safe to overwrite it.
	       Would also be possible a char at a time.
	     */
	    int nc = (int) mbstowcs(NULL, tmp, 0);
	    wchar_t *wstr = Calloc(nc+1, wchar_t), *wc;
	    if (nc >= 0) {
		mbstowcs(wstr, tmp, nc+1);
		for (wc = wstr; *wc; wc++) {
		    if (*wc == L'.' || (allow_ && *wc == L'_'))
			/* leave alone */;
		    else if (!iswalnum((int)*wc)) *wc = L'.';
		    /* If it changes into dot here,
		     * length will become short on mbcs.
		     * The name which became short will contain garbage.
		     * cf.
		     *   >  make.names(c("\u30fb"))
		     *   [1] "X.\0"
		     */
		}
		wcstombs(tmp, wstr, strlen(tmp)+1);
		Free(wstr);
	    } else error(_("invalid multibyte string %d"), i+1);
	} else {
	    for (p = tmp; *p; p++) {
Esempio n. 10
0
const char *EncodeString(SEXP s, int w, int quote, Rprt_adj justify)
{
    int b, b0, i, j, cnt;
    const char *p; char *q, buf[11];
    cetype_t ienc = CE_NATIVE;

    /* We have to do something like this as the result is returned, and
       passed on by EncodeElement -- so no way could be end user be
       responsible for freeing it.  However, this is not thread-safe. */

    static R_StringBuffer gBuffer = {NULL, 0, BUFSIZE};
    R_StringBuffer *buffer = &gBuffer;

    if (s == NA_STRING) {
	p = quote ? CHAR(R_print.na_string) : CHAR(R_print.na_string_noquote);
	cnt = i = (int)(quote ? strlen(CHAR(R_print.na_string)) :
			strlen(CHAR(R_print.na_string_noquote)));
	quote = 0;
    } else {
#ifdef Win32
	if(WinUTF8out) {
	    ienc = getCharCE(s);
	    if(ienc == CE_UTF8) {
		p = CHAR(s);
		i = Rstrlen(s, quote);
		cnt = LENGTH(s);
	    } else {
		p = translateChar0(s);
		if(p == CHAR(s)) {
		    i = Rstrlen(s, quote);
		    cnt = LENGTH(s);
		} else {
		    cnt = strlen(p);
		    i = Rstrwid(p, cnt, CE_NATIVE, quote);
		}
		ienc = CE_NATIVE;
	    }
	} else
#endif
	{
	    if(IS_BYTES(s)) {
		p = CHAR(s);
		cnt = (int) strlen(p);
		const char *q;
		char *pp = R_alloc(4*cnt+1, 1), *qq = pp, buf[5];
		for (q = p; *q; q++) {
		    unsigned char k = (unsigned char) *q;
		    if (k >= 0x20 && k < 0x80) {
			*qq++ = *q;
			if (quote && *q == '"') cnt++;
		    } else {
			snprintf(buf, 5, "\\x%02x", k);
			for(j = 0; j < 4; j++) *qq++ = buf[j];
			cnt += 3;
		    }
		}
		*qq = '\0';
		p = pp;
		i = cnt;
	    } else {
		p = translateChar(s);
		if(p == CHAR(s)) {
		    i = Rstrlen(s, quote);
		    cnt = LENGTH(s);
		} else {
		    cnt = (int) strlen(p);
		    i = Rstrwid(p, cnt, CE_NATIVE, quote);
		}
	    }
	}
    }

    /* We need enough space for the encoded string, including escapes.
       Octal encoding turns one byte into four.
       \u encoding can turn a multibyte into six or ten,
       but it turns 2/3 into 6, and 4 (and perhaps 5/6) into 10.
       Let's be wasteful here (the worst case appears to be an MBCS with
       one byte for an upper-plane Unicode point output as ten bytes,
       but I doubt that such an MBCS exists: two bytes is plausible).

       +2 allows for quotes, +6 for UTF_8 escapes.
     */
    q = R_AllocStringBuffer(imax2(5*cnt+8, w), buffer);
    b = w - i - (quote ? 2 : 0); /* total amount of padding */
    if(justify == Rprt_adj_none) b = 0;
    if(b > 0 && justify != Rprt_adj_left) {
	b0 = (justify == Rprt_adj_centre) ? b/2 : b;
	for(i = 0 ; i < b0 ; i++) *q++ = ' ';
	b -= b0;
    }
    if(quote) *q++ = (char) quote;
    if(mbcslocale || ienc == CE_UTF8) {
	int j, res;
	mbstate_t mb_st;
	wchar_t wc;
	unsigned int k; /* not wint_t as it might be signed */
#ifndef __STDC_ISO_10646__
	Rboolean Unicode_warning = FALSE;
#endif
	if(ienc != CE_UTF8)  mbs_init(&mb_st);
#ifdef Win32
	else if(WinUTF8out) { memcpy(q, UTF8in, 3); q += 3; }
#endif
	for (i = 0; i < cnt; i++) {
	    res = (int)((ienc == CE_UTF8) ? utf8toucs(&wc, p):
			mbrtowc(&wc, p, MB_CUR_MAX, NULL));
	    if(res >= 0) { /* res = 0 is a terminator */
		k = wc;
		/* To be portable, treat \0 explicitly */
		if(res == 0) {k = 0; wc = L'\0';}
		if(0x20 <= k && k < 0x7f && iswprint(wc)) {
		    switch(wc) {
		    case L'\\': *q++ = '\\'; *q++ = '\\'; p++;
			break;
		    case L'\'':
		    case L'"':
			if(quote == *p)  *q++ = '\\'; *q++ = *p++;
			break;
		    default:
			for(j = 0; j < res; j++) *q++ = *p++;
			break;
		    }
		} else if (k < 0x80) {
		    /* ANSI Escapes */
		    switch(wc) {
		    case L'\a': *q++ = '\\'; *q++ = 'a'; break;
		    case L'\b': *q++ = '\\'; *q++ = 'b'; break;
		    case L'\f': *q++ = '\\'; *q++ = 'f'; break;
		    case L'\n': *q++ = '\\'; *q++ = 'n'; break;
		    case L'\r': *q++ = '\\'; *q++ = 'r'; break;
		    case L'\t': *q++ = '\\'; *q++ = 't'; break;
		    case L'\v': *q++ = '\\'; *q++ = 'v'; break;
		    case L'\0': *q++ = '\\'; *q++ = '0'; break;

		    default:
			/* print in octal */
			snprintf(buf, 5, "\\%03o", k);
			for(j = 0; j < 4; j++) *q++ = buf[j];
			break;
		    }
		    p++;
		} else {
		    if(iswprint(wc)) {
			/* The problem here is that wc may be
			   printable according to the Unicode tables,
			   but it may not be printable on the output
			   device concerned. */
			for(j = 0; j < res; j++) *q++ = *p++;
		    } else {
#ifndef Win32
# ifndef __STDC_ISO_10646__
			Unicode_warning = TRUE;
# endif
			if(k > 0xffff)
			    snprintf(buf, 11, "\\U%08x", k);
			else
#endif
			    snprintf(buf, 11, "\\u%04x", k);
			j = (int) strlen(buf);
			memcpy(q, buf, j);
			q += j;
			p += res;
		    }
		    i += (res - 1);
		}

	    } else { /* invalid char */
		snprintf(q, 5, "\\x%02x", *((unsigned char *)p));
		q += 4; p++;
	    }
	}
#ifndef __STDC_ISO_10646__
	if(Unicode_warning)
	    warning(_("it is not known that wchar_t is Unicode on this platform"));
#endif

    } else
	for (i = 0; i < cnt; i++) {

	    /* ASCII */
	    if((unsigned char) *p < 0x80) {
		if(*p != '\t' && isprint((int)*p)) { /* Windows has \t as printable */
		    switch(*p) {
		    case '\\': *q++ = '\\'; *q++ = '\\'; break;
		    case '\'':
		    case '"':
			if(quote == *p)  *q++ = '\\'; *q++ = *p; break;
		    default: *q++ = *p; break;
		    }
		} else switch(*p) {
			/* ANSI Escapes */
		    case '\a': *q++ = '\\'; *q++ = 'a'; break;
		    case '\b': *q++ = '\\'; *q++ = 'b'; break;
		    case '\f': *q++ = '\\'; *q++ = 'f'; break;
		    case '\n': *q++ = '\\'; *q++ = 'n'; break;
		    case '\r': *q++ = '\\'; *q++ = 'r'; break;
		    case '\t': *q++ = '\\'; *q++ = 't'; break;
		    case '\v': *q++ = '\\'; *q++ = 'v'; break;
		    case '\0': *q++ = '\\'; *q++ = '0'; break;

		    default:
			/* print in octal */
			snprintf(buf, 5, "\\%03o", (unsigned char) *p);
			for(j = 0; j < 4; j++) *q++ = buf[j];
			break;
		    }
		p++;
	    } else {  /* 8 bit char */
#ifdef Win32 /* It seems Windows does not know what is printable! */
		*q++ = *p++;
#else
		if(!isprint((int)*p & 0xff)) {
		    /* print in octal */
		    snprintf(buf, 5, "\\%03o", (unsigned char) *p);
		    for(j = 0; j < 4; j++) *q++ = buf[j];
		    p++;
		} else *q++ = *p++;
#endif
	    }
	}

#ifdef Win32
    if(WinUTF8out && ienc == CE_UTF8)  { memcpy(q, UTF8out, 3); q += 3; }
#endif
    if(quote) *q++ = (char) quote;
    if(b > 0 && justify != Rprt_adj_right) {
	for(i = 0 ; i < b ; i++) *q++ = ' ';
    }
    *q = '\0';
    return buffer->data;
}
Esempio n. 11
0
/* strlen() using escaped rather than literal form,
   and allowing for embedded nuls.
   In MBCS locales it works in characters, and reports in display width.
   Also used in printarray.c.
 */
attribute_hidden
int Rstrwid(const char *str, int slen, cetype_t ienc, int quote)
{
    const char *p = str;
    int len = 0, i;

    if(mbcslocale || ienc == CE_UTF8) {
	int res;
	mbstate_t mb_st;
	wchar_t wc;
	unsigned int k; /* not wint_t as it might be signed */

	if(ienc != CE_UTF8)  mbs_init(&mb_st);
	for (i = 0; i < slen; i++) {
	    res = (ienc == CE_UTF8) ? (int) utf8toucs(&wc, p):
		(int) mbrtowc(&wc, p, MB_CUR_MAX, NULL);
	    if(res >= 0) {
		k = wc;
		if(0x20 <= k && k < 0x7f && iswprint(wc)) {
		    switch(wc) {
		    case L'\\':
			len += 2;
			break;
		    case L'\'':
		    case L'"':
			len += (quote == *p) ? 2 : 1;
			break;
		    default:
			len++; /* assumes these are all width 1 */
			break;
		    }
		    p++;
		} else if (k < 0x80) {
		    switch(wc) {
		    case L'\a':
		    case L'\b':
		    case L'\f':
		    case L'\n':
		    case L'\r':
		    case L'\t':
		    case L'\v':
		    case L'\0':
			len += 2; break;
		    default:
			/* print in octal */
			len += 4; break;
		    }
		    p++;
		} else {
		    len += iswprint((wint_t)wc) ? Ri18n_wcwidth(wc) :
#ifdef Win32
			6;
#else
		    (k > 0xffff ? 10 : 6);
#endif
		    i += (res - 1);
		    p += res;
		}
	    } else {
		len += 4;
		p++;
	    }
	}
    } else
	for (i = 0; i < slen; i++) {
	    /* ASCII */
	    if((unsigned char) *p < 0x80) {
		if(isprint((int)*p)) {
		    switch(*p) {
		    case '\\':
			len += 2; break;
		    case '\'':
		    case '"':
			len += (quote == *p)? 2 : 1; break;
		    default:
			len++; break;
		    }
		} else switch(*p) {
		    case '\a':
		    case '\b':
		    case '\f':
		    case '\n':
		    case '\r':
		    case '\t':
		    case '\v':
		    case '\0':
			len += 2; break;
		    default:
			/* print in octal */
			len += 4; break;
		    }
		p++;
	    } else { /* 8 bit char */
#ifdef Win32 /* It seems Windows does not know what is printable! */
		len++;
#else
		len += isprint((int)*p) ? 1 : 4;
#endif
		p++;
	    }
	}

    return len;
}
Esempio n. 12
0
/* strlen() using escaped rather than literal form.
   In MBCS locales it works in characters, and reports in display width.
   Rstrwid is also used in printarray.c.

   This supported embedded nuls when we had those.
 */
attribute_hidden
int Rstrwid(const char *str, int slen, cetype_t ienc, int quote)
{
    const char *p = str;
    int len = 0, i;

    if(ienc == CE_BYTES) { // not currently used for that encoding
	for (i = 0; i < slen; i++) {
	    unsigned char k = str[i];
	    if (k >= 0x20 && k < 0x80) len += 1;
	    else len += 4;
	}
	return len;
    }
    /* Future-proof: currently that is all Rstrlen calls it with,
       and printarray has CE_NATIVE explicitly */
    if(ienc > 2) // CE_NATIVE, CE_UTF8, CE_BYTES are supported
	warning("unsupported encoding (%d) in Rstrwid", ienc);
    if(mbcslocale || ienc == CE_UTF8) {
	int res;
	mbstate_t mb_st;
	wchar_t wc;
	unsigned int k; /* not wint_t as it might be signed */

	if(ienc != CE_UTF8)  mbs_init(&mb_st);
	for (i = 0; i < slen; i++) {
	    res = (ienc == CE_UTF8) ? (int) utf8toucs(&wc, p):
		(int) mbrtowc(&wc, p, MB_CUR_MAX, NULL);
	    if(res >= 0) {
		k = wc;
		if(0x20 <= k && k < 0x7f && iswprint(wc)) {
		    switch(wc) {
		    case L'\\':
			len += 2;
			break;
		    case L'\'':
		    case L'"':
		    case L'`':
			len += (quote == *p) ? 2 : 1;
			break;
		    default:
			len++; /* assumes these are all width 1 */
			break;
		    }
		    p++;
		} else if (k < 0x80) {
		    switch(wc) {
		    case L'\a':
		    case L'\b':
		    case L'\f':
		    case L'\n':
		    case L'\r':
		    case L'\t':
		    case L'\v':
		    case L'\0':
			len += 2; break;
		    default:
			/* print in octal */
			len += 4; break;
		    }
		    p++;
		} else {
		    len += iswprint((wint_t)wc) ? Ri18n_wcwidth(wc) :
#ifdef Win32
			6;
#else
		    (k > 0xffff ? 10 : 6);
#endif
		    i += (res - 1);
		    p += res;
		}
	    } else {
		len += 4;
		p++;
	    }
	}
    } else // not MBCS nor marked as UTF-8
	for (i = 0; i < slen; i++) {
	    if((unsigned char) *p < 0x80) {
		/* ASCII */
		if(isprint((int)*p)) {
		    switch(*p) {
		    case '\\':
			len += 2; break;
		    case '\'':
		    case '"':
		    case '`':
			len += (quote == *p)? 2 : 1; break;
		    default:
			len++; break;
		    }
		} else switch(*p) {
		    case '\a':
		    case '\b':
		    case '\f':
		    case '\n':
		    case '\r':
		    case '\t':
		    case '\v':
		    case '\0':
			len += 2; break;
		    default:
			/* print in octal */
			len += 4; break;
		    }
		p++;
	    } else { /* 8 bit char */
#ifdef Win32 /* It seems Windows does not know what is printable! */
		len++;
#else
		len += isprint((int)*p) ? 1 : 4;
#endif
		p++;
	    }
	}

    return len;
}
Esempio n. 13
0
int
getline(const char *prompt, char *buf, int buflen)
{
    int             c, loc, tmp;
    int mb_len;
    mbstate_t mb_st;
    int i;
    wchar_t wc;

    BUF_SIZE = buflen;
    gl_buf = buf;
    gl_buf[0] = '\0';
    if (setjmp(gl_jmp)) {
       gl_newline();
       gl_cleanup(); 
       return 0;
    }
    gl_init();	
    gl_pos = 0;
    gl_prompt = (prompt)? prompt : "";
    if (gl_in_hook)
	gl_in_hook(gl_buf);
    gl_fixup(gl_prompt, -2, BUF_SIZE);
    while ((c = gl_getc()) >= 0) {
	gl_extent = 0;  	/* reset to full extent */
	if (!iscntrl(c)) {
	    if (gl_search_mode)
	       search_addchar(c);
	    else
	       gl_addchar(c);
	} else {
	    if (gl_search_mode) {
	        if (c == '\033' || c == '\016' || c == '\020') {
	            search_term();
	            c = 0;     		/* ignore the character */
		} else if (c == '\010' || c == '\177') {
		    search_addchar(-1); /* unwind search string */
		    c = 0;
		} else if (c != '\022' && c != '\023') {
		    search_term();	/* terminate and handle char */
		}
	    }
	    switch (c) {
	      case '\n': case '\r': 			/* newline */
		gl_newline();
		gl_cleanup();
		return 0;
		/*NOTREACHED*/
		break; 
	      case '\001': gl_fixup(gl_prompt, -1, 0);		/* ^A */
		break;
	      case '\002': 	/* ^B */
		if(mbcslocale) {
		    mb_len = 0;
		    mbs_init(&mb_st);
		    for(i = 0; i < gl_pos ;) {
			mbrtowc(&wc, gl_buf+i, MB_CUR_MAX, &mb_st);
			mb_len = Ri18n_wcwidth(wc);
			i += (wc==0) ? 0 : mb_len;
		    }
		    gl_fixup(gl_prompt, -1, gl_pos - mb_len);
		} else
		    gl_fixup(gl_prompt, -1, gl_pos-1);
		break;
	      case '\003':                                      /* ^C */
		  gl_fixup(gl_prompt, -1, gl_cnt);
		  gl_puts("^C\n");
		  gl_kill(0);
		  gl_fixup(gl_prompt, -2, BUF_SIZE);
		break;
	      case '\004':					/* ^D */
		if (gl_cnt == 0) {
		    gl_buf[0] = 0;
		    gl_cleanup();
		    gl_putc('\n');
		    return 0;
		} else {
		    gl_del(0);
		}
		break;
	      case '\005': gl_fixup(gl_prompt, -1, gl_cnt);	/* ^E */
		break;
		case '\006': /* ^F */
		  if(mbcslocale) { 
		      if(gl_pos >= gl_cnt) break;
		      mb_len = 0;
		      mbs_init(&mb_st);
		      for(i = 0; i<= gl_pos ;){
			  mbrtowc(&wc, gl_buf+i, MB_CUR_MAX, &mb_st);
			  mb_len = Ri18n_wcwidth(wc);
			  i += (wc==0) ? 0 : mb_len;
		      }
		      gl_fixup(gl_prompt, -1, gl_pos + mb_len);
		  }
		else
		  gl_fixup(gl_prompt, -1, gl_pos+1);
		break;
	      case '\010': case '\177': gl_del(-1);	/* ^H and DEL */
		break;
	      case '\t':        				/* TAB */
                if (gl_tab_hook) {
		    tmp = gl_pos;
	            loc = gl_tab_hook(gl_buf, gl_strlen(gl_prompt), &tmp);
	            if (loc != -1 || tmp != gl_pos)
	                gl_fixup(gl_prompt, loc, tmp);
                }
		break;
	      case '\013': gl_kill(gl_pos);			/* ^K */
		break;
	      case '\014': gl_redraw();				/* ^L */
		break;
	      case '\016': 					/* ^N */
		strncpy(gl_buf, gl_hist_next(), BUF_SIZE-2);
		gl_buf[BUF_SIZE-2] = '\0';
                if (gl_in_hook)
	            gl_in_hook(gl_buf);
		gl_fixup(gl_prompt, 0, BUF_SIZE);
		break;
	      case '\017': gl_overwrite = !gl_overwrite;       	/* ^O */
		break;
	      case '\020': 					/* ^P */
		strncpy(gl_buf, gl_hist_prev(),BUF_SIZE-2);
		gl_buf[BUF_SIZE-2] = '\0';
                if (gl_in_hook)
	            gl_in_hook(gl_buf);
		gl_fixup(gl_prompt, 0, BUF_SIZE);
		break;
	      case '\022': search_back(1);			/* ^R */
		break;
	      case '\023': search_forw(1);			/* ^S */
		break;
	      case '\024': gl_transpose();			/* ^T */
		break;
              case '\025': gl_kill(0);				/* ^U */
		break;
              case '\027': gl_killword(-1);			/* ^W */
		break;
	      case '\031': gl_yank();				/* ^Y */
		break;
	      case '\032': 					/* ^Z */
		gl_newline();
		gl_cleanup();
		return 1;
		/*NOTREACHED*/
		break;
	      case '\033':				/* ansi arrow keys */
		c = gl_getc();
		if (c == '[') {
		    switch(c = gl_getc()) {
		      case 'A':             			/* up */
		        strncpy(gl_buf, gl_hist_prev(), BUF_SIZE-2);
		        gl_buf[BUF_SIZE-2] = '\0';
		        if (gl_in_hook)
	                    gl_in_hook(gl_buf);
		        gl_fixup(gl_prompt, 0, BUF_SIZE);
		        break;
		      case 'B':                         	/* down */
		        strncpy(gl_buf, gl_hist_next(), BUF_SIZE-2);
		        gl_buf[BUF_SIZE-2] = '\0';
                        if (gl_in_hook)
	                    gl_in_hook(gl_buf);
		        gl_fixup(gl_prompt, 0, BUF_SIZE);
		        break;
		    case 'C': /* right */
			if(mbcslocale) { 
			    mb_len = 0;
			    mbs_init(&mb_st);
			    for(i = 0; i <= gl_pos ;) {
				mbrtowc(&wc, gl_buf+i, MB_CUR_MAX, &mb_st);
				mb_len = Ri18n_wcwidth(wc);
				i += (wc==0) ? 0 : mb_len;
			    }
			    gl_fixup(gl_prompt, -1, gl_pos + mb_len);
			} else
			    gl_fixup(gl_prompt, -1, gl_pos+1);
		        break;
		    case 'D': /* left */
		       if(mbcslocale) {
			   mb_len = 0;
			   mbs_init(&mb_st);
			   for(i = 0; i <= gl_pos ;) {
			       mbrtowc(&wc, gl_buf+i, MB_CUR_MAX, &mb_st);
			       mb_len = Ri18n_wcwidth(wc);
			       i += (wc==0) ? 0 :mb_len;
			   }
			   gl_fixup(gl_prompt, -1, gl_pos - mb_len);
		       } else
			 gl_fixup(gl_prompt, -1, gl_pos-1);
			break;
		      default: gl_putc('\007');         /* who knows */
		        break;
		    }
		} else if (c == 'f' || c == 'F') {
		    gl_word(1);
		} else if (c == 'b' || c == 'B') {
		    gl_word(-1);
		} else
		    gl_putc('\007');
		break;
	      default:		/* check for a terminal signal */
                if (c > 0)
		    gl_putc('\007');
		break;
	    }
	}
    }
    gl_newline();
    gl_cleanup();
    return 0;
}
Esempio n. 14
0
static int
gl_getc(void)
/* get a character without echoing it to screen */
{
    int             c;
    static char buf[9] = "";
    static int bufavail = 0;
    static int bufpos = 0;

    if (bufavail > 0) {
	bufavail--;
	return buf[bufpos++];
    }
    bufpos = 0;

/* guido masarotto (3/12/98)
 * get Ansi char code from a Win32 console
 */
    DWORD a;
    INPUT_RECORD r;
    DWORD st;
    WORD vk;
    CONSOLE_SCREEN_BUFFER_INFO csb;
    int bbb = 0, nAlt=0, n;

    c = 0; 
    while (!c) {
      /* 
	   Following two lines seem to be needed under Win2k 
	   to reshow the cursor 
      */
      GetConsoleScreenBufferInfo(Win32OutputStream, &csb);
      SetConsoleCursorPosition(Win32OutputStream, csb.dwCursorPosition);
      ReadConsoleInputW(Win32InputStream, &r, 1, &a);
      if (!(r.EventType == KEY_EVENT)) break;
      st = r.Event.KeyEvent.dwControlKeyState;
      vk = r.Event.KeyEvent.wVirtualKeyCode;
      if (r.Event.KeyEvent.bKeyDown) {
        AltIsDown = (st & LEFT_ALT_PRESSED);
	if (vk == VK_MENU && AltIsDown) { /* VK_MENU is
							   Alt or AltGr */
	  nAlt = 0;
	  bbb  = 0;
	} 
	else if (st & ENHANCED_KEY) { 
	  switch(vk) {
	  case VK_LEFT: c=2 ;break;
	  case VK_RIGHT: c=6;break;
	  case VK_HOME:  c='\001';break;
	  case VK_END: c='\005';break;
	  case VK_UP:  c=16;break;
	  case VK_DOWN: c=14;break;		
	  case VK_DELETE:  c='\004';break;
	  }
	} 
	else if (AltIsDown) { /* Interpret Alt+xxx entries */
	  switch (vk) {
	  case VK_INSERT: n = 0; break;
	  case VK_END: n = 1; break;
	  case VK_DOWN: n = 2; break;
	  case VK_NEXT: n = 3;break;
	  case VK_LEFT: n = 4; break;
	  case VK_CLEAR:  n = 5; break;
	  case VK_RIGHT: n = 6; break;
	  case VK_HOME: n = 7; break;
	  case VK_UP: n = 8; break;
	  case VK_PRIOR: n = 9; break;	 
	  default: n = -1;
	  }
	  if (n >= 0) bbb = 10 * bbb + n;
	  nAlt += 1;
	  if (nAlt==3) { 
	    c = (bbb < 256) && (bbb > 0) ? bbb : 0;
	    bbb = 0;
	    nAlt = 0;
	  } 
	} 
	else {
	  /* Originally uChar.AsciiChar was used here and for MBCS characters
	     GetConsoleInput returned as many events as bytes in the character.
	     As of Windows 8 this reportedly no longer works, GetConsoleInput
	     would only generate one event with the first byte in AsciiChar.
	     The bug still exists in Windows 10, and thus we now call
	     GetConsoleInputW to get uchar.UnicodeChar. Ideally (at least for
	     Windows) all of getline code would be refactored to work with wide
	     characters, but for now we just convert the character back to bytes
	     in current native locale to recover the old behavior of gl_getc. */
	  wchar_t wc = r.Event.KeyEvent.uChar.UnicodeChar;
	  mbstate_t mb_st;
	  mbs_init(&mb_st);
	  if (wc != L'\0') {
	    size_t cres = wcrtomb(buf, wc, &mb_st);
	    if (cres != (size_t)-1) {
	      bufavail = (int) cres - 1;
	      bufpos = 1;
	      c = buf[0];
	    }
	  }
	}
      }
      else if (vk == VK_MENU && AltIsDown) { 
           /* Alt key up event: could be AltGr, but let's hope users 
	      only press one of them at a time. */
	AltIsDown = 0;
	c = (bbb < 256) && (bbb > 0) ? bbb : 0;
	bbb = 0;
	nAlt = 0;
      }
      if ((c < -127) || (c > 255)) c = 0; 
      if (c < 0) c = 256 + c;    
    }
    return c;
}