Example #1
0
String String::lstrip(const String& charset) const {
	if (!s_len) {
		return *this;
	}

	rune tmp[s_len + 1];
	utf8_decode(s_data, tmp, s_len + 1);

	rune tmp_charset[charset.len() + 1];
	utf8_decode(charset.s_data, tmp_charset, charset.len() + 1);

	bool found;

	size_t l = s_len;
	while(l > 0) {
		found = false;
		for(size_t n = 0; n < charset.len(); n++) {
			if (tmp_charset[n] == tmp[0]) {
				found = true;
				break;
			}
		}
		if (!found) {
			break;
		}
		std::memmove(tmp, &tmp[1], l * sizeof(rune));
		l--;
	}
	return String(tmp);
}
Example #2
0
static unsigned int
get_unicode( str *s, unsigned int *pi, int charsetin, int latexin, int utf8in, int xmlin )
{
	unsigned int ch;
	int unicode = 0, err = 0;
	if ( xmlin && s->data[*pi]=='&' ) {
		ch = decode_entity( s->data, pi, &unicode, &err );
	} else if ( charsetin==CHARSET_GB18030 ) {
		ch = gb18030_decode( s->data, pi );
		unicode = 1;
	} else if ( latexin ) {
		/* Must handle bibtex files in UTF8/Unicode */
		if ( utf8in && ( s->data[*pi] & 128 ) ) {
			ch = utf8_decode( s->data, pi );
			unicode = 1;
		} else ch = latex2char( s->data, pi, &unicode );
	}
	else if ( utf8in )
		ch = utf8_decode( s->data, pi );
	else {
		ch = (unsigned int) s->data[*pi];
		*pi = *pi + 1;
	}
	if ( !unicode && charsetin!=CHARSET_UNICODE )
		ch = charset_lookupchar( charsetin, ch );
	return ch;
}
Example #3
0
String String::rstrip(const String& charset) const {
	if (!s_len) {
		return *this;
	}

	rune tmp[s_len + 1];
	utf8_decode(s_data, tmp, s_len + 1);

	rune tmp_charset[charset.len() + 1];
	utf8_decode(charset.s_data, tmp_charset, charset.len() + 1);

	bool found;

	int l = s_len - 1;

	while(l >= 0) {
		found = false;
		for(size_t n = 0; n < charset.len(); n++) {
			if (tmp_charset[n] == tmp[l]) {
				found = true;
				break;
			}
		}
		if (!found) {
			break;
		}
		tmp[l--] = 0;
	}
	return String(tmp);
}
Example #4
0
void LuaProxy::playSFX(const std::string& filename)
{
#ifndef NO_SDL
	playSFXSDL(filename);
#else
	wstring full_path;
	if(!isAbsolutePath(filename)){
		full_path = getCustomFolderPath() + utf8_decode(filename);
	}else{
		full_path = utf8_decode(filename);
	}
	
	PlaySound(full_path.c_str(), 0, SND_FILENAME | SND_ASYNC);
#endif
}
Example #5
0
int win_draw_text(win_t *win, XftDraw *d, const XftColor *color, int x, int y,
                  char *text, int len, int w)
{
	int err, tw = 0;
	char *t, *next;
	uint32_t rune;
	XftFont *f;
	FcCharSet *fccharset;
	XGlyphInfo ext;

	for (t = text; t - text < len; t = next) {
		next = utf8_decode(t, &rune, &err);
		if (XftCharExists(win->env.dpy, font, rune)) {
			f = font;
		} else { /* fallback font */
			fccharset = FcCharSetCreate();
			FcCharSetAddChar(fccharset, rune);
			f = XftFontOpen(win->env.dpy, win->env.scr, FC_CHARSET, FcTypeCharSet,
			                fccharset, FC_SCALABLE, FcTypeBool, FcTrue,
			                FC_SIZE, FcTypeDouble, fontsize, NULL);
			FcCharSetDestroy(fccharset);
		}
		XftTextExtentsUtf8(win->env.dpy, f, (XftChar8*)t, next - t, &ext);
		tw += ext.xOff;
		if (tw <= w) {
			XftDrawStringUtf8(d, color, f, x, y, (XftChar8*)t, next - t);
			x += ext.xOff;
		}
		if (f != font)
			XftFontClose(win->env.dpy, f);
	}
	return tw;
}
string MenuStateAbout::loadAdditionalCredits(){
	string data_path= getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
	if(data_path != ""){
		endPathWithSlash(data_path);
	}
	string result= "";
	const string dir= getGameCustomCoreDataPath(data_path,"data/core/menu/credits.txt");
	//printf("dir [%s]\n",dir.c_str());

	if(fileExists(dir) == true) {
#if defined(WIN32) && !defined(__MINGW32__)
		FILE *fp = _wfopen(utf8_decode(dir).c_str(), L"r");
		ifstream file(fp);
#else
		ifstream file(dir.c_str());
#endif
		std::string buffer;
		while(!file.eof()){
			getline(file, buffer);
			result+= buffer + "\n";
		}
		std::cout << buffer << std::endl;
		file.close();
#if defined(WIN32) && !defined(__MINGW32__)
		if(fp) fclose(fp);
#endif
	}
	return result;
}
Example #7
0
String String::slice(int idx1, int idx2) const {
	if (idx1 < 0) {
		idx1 += len();

		if (idx1 < 0)
			idx1 = 0;
	}
	if ((size_t)idx1 >= len()) {
		return String();
	}
	if (idx2 < 0) {
		idx2 += len();

		if (idx2 < 0) {
			idx2 = 0;
		}
	}
	if ((size_t)idx2 > len()) {
		idx2 = len();
	}
	if (idx1 >= idx2) {
		return String();
	}
	rune tmp[s_len + 1];
	utf8_decode(s_data, tmp, s_len + 1);
	tmp[idx2] = 0;
	return String(&tmp[idx1]);
}
Example #8
0
/*
** codepoint(s, [i, [j]])  -> returns codepoints for all characters
** that start in the range [i,j]
*/
static int codepoint (lua_State *L) {
    size_t len;
    const char *s = luaL_checklstring(L, 1, &len);
    lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
    lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len);
    int n;
    const char *se;
    luaL_argcheck(L, posi >= 1, 2, "out of range");
    luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range");
    if (posi > pose) return 0;  /* empty interval; return no values */
    if (pose - posi >= INT_MAX)  /* (lua_Integer -> int) overflow? */
        return luaL_error(L, "string slice too long");
    n = (int)(pose -  posi) + 1;
    luaL_checkstack(L, n, "string slice too long");
    n = 0;
    se = s + pose;
    for (s += posi - 1; s < se;) {
        int code;
        s = utf8_decode(s, &code);
        if (s == NULL)
            return luaL_error(L, "invalid UTF-8 code");
        lua_pushinteger(L, code);
        n++;
    }
    return n;
}
Example #9
0
  static void encode_string(std::ostream& os, std::string s) {
    std::vector<uint32_t> str = utf8_decode(s);

    std::vector<uint32_t>::iterator it;
    
    os << "\"";

    for (it = str.begin(); it != str.end(); it++) {
      uint32_t c = *it;
      
      switch(c) {
        case '"': os << "\\\""; break;
        case '\\': os << "\\\\"; break;
        case '/': os << "\\/"; break;
        case '\b': os << "\\b"; break;
        case '\f': os << "\\f"; break;
        case '\n': os << "\\n"; break;
        case '\r': os << "\\r"; break;
        case '\t': os << "\\t"; break;
        default:
          utf8_encode(c, os);
          break;
      }
    }

    os << "\"";
  }
Example #10
0
// default argument sep = ' '
Array<String> String::split(rune sep) const {
	if (!s_len) {
		return Array<String>();
	}

	rune tmp[s_len + 1];
	utf8_decode(s_data, tmp, s_len + 1);

	Array<String> a;

	unsigned int start = 0, end;
	for(end = 0; end < s_len; end++) {
		if (tmp[end] == sep) {
			// copy word
			tmp[end] = 0;
			a.append(String(&tmp[start]));

			// skip to next word
			end++;
			while(end < s_len && tmp[end] == sep) {
				end++;
			}
			start = end;
			continue;
		}
	}
	// last word
	if (end != start) {
		tmp[end] = 0;
		a.append(String(&tmp[start]));
	}
	return a;
}
Example #11
0
File: qw.c Project: Distrotech/joe
static int utypeqw(QW *qw, int c)
{
	W *win;
	W *w = qw->parent;
	int *notify = w->notify;
	int (*func) ();
	void *object = qw->object;

	if (locale_map->type) {
		c = utf8_decode(&qw_sm, c);
		if (c<0)
			return 0;
	}

	win = qw->parent->win;
	func = qw->func;
	vsrm(qw->prompt);
	joe_free(qw);
	w->object = NULL;
	w->notify = NULL;
	wabort(w);
	if (func)
		return func(win->object, c, object, notify);
	return -1;
}
Example #12
0
File: utils.c Project: jeeb/flac
void write_vc_field(const char *filename, const FLAC__StreamMetadata_VorbisComment_Entry *entry, FLAC__bool raw, FILE *f)
{
	if(0 != entry->entry) {
		if(filename)
			fprintf(f, "%s:", filename);

		if(!raw) {
			/*
			 * WATCHOUT: comments that contain an embedded null will
			 * be truncated by utf_decode().
			 */
			char *converted;

			if(utf8_decode((const char *)entry->entry, &converted) >= 0) {
				(void) local_fwrite(converted, 1, strlen(converted), f);
				free(converted);
			}
			else {
				(void) local_fwrite(entry->entry, 1, entry->length, f);
			}
		}
		else {
			(void) local_fwrite(entry->entry, 1, entry->length, f);
		}
	}

	putc('\n', f);
}
Example #13
0
/*
 * Check keyboard buffer for key sequences.
 */
void check_for_key(int del_garbage)
{
  unsigned u, len;

  kbd.key = 0;

  if(!kbd.pos) return;

  if(config.debug >= 4) {
    fprintf(stderr, "kbd buffer(%d):", del_garbage);
    for(u = 0; u < kbd.pos; u++) {
      fprintf(stderr, " 0x%02x", kbd.buffer[u]);
    }
    fprintf(stderr, "\n");
  }

  /* look for esc sequences */
  for(u = 0; u < sizeof key_list / sizeof *key_list; u++) {
    len = strlen(key_list[u].bytes);
    if(len && len <= kbd.pos && !memcmp(kbd.buffer, key_list[u].bytes, len)) {
      kbd.key = key_list[u].key;
      del_keys(len);
//      fprintf(stderr, "-> key = 0x%02x\n", kbd.key);

      return;
    }
  }

  /* kill unknown esc sequences */
  if(del_garbage && kbd.buffer[0] == '\x1b' && kbd.pos > 1) {
    kbd.key = 0;
    del_keys(kbd.pos);

    return;
  }

  /* utf8 sequence */
  if(kbd.buffer[0] != '\x1b') {
    u = utf8_enc_len(kbd.buffer[0]);
    if(u && u <= kbd.pos) {
      kbd.key = utf8_decode(kbd.buffer);
      del_keys(u);

//      fprintf(stderr, "utf8(%u) = 0x%02x\n", u, kbd.key);

      return;
    }
  }

  /* kill remaining stuff */
  if(del_garbage) {
    /* basically for 'Esc' */
    if(kbd.pos == 1) kbd.key = kbd.buffer[0];

    del_keys(kbd.pos);

    return;
  }
}
Example #14
0
bool fileExists(const std::string& path)
{
#if defined(OS_WIN)
    return ::PathFileExistsW(utf8_decode(path).c_str()) == TRUE;
#else
    return ::access(path.c_str(), F_OK) == 0;
#endif // OS_WIN
}
Example #15
0
void TextLineMetrics::getVisibleText(const char* _string, float _top, float _bottom, const char*& _begin, const char*& _end)
{
	CodePoint codepoint = 0;
	uint32_t state = 0;
	// y is bottom of a text line
	float y = m_lineHeight;
	while (*_string && (y < _top) )
	{
		for (; *_string; ++_string)
		{	
			if(utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT)
			{
				if(codepoint == L'\n')
				{
					y += m_lineHeight;
					++_string;
					break;
				}
			}
		}
	}

	BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed");
	_begin = _string;

	// y is now top of a text line
	y -= m_lineHeight;
	while ( (*_string) && (y < _bottom) )
	{
		for (; *_string; ++_string)
		{	
			if(utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT)
			{
				if(codepoint == L'\n')
				{
					y += m_lineHeight;
					++_string;
					break;
				}
			}
		}
	}

	BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed");
	_end = _string;
}
Example #16
0
void TextLineMetrics::getSubText(const char* _string, uint32_t _firstLine, uint32_t _lastLine, const char*& _begin, const char*& _end)
{
	CodePoint codepoint = 0;
	uint32_t state = 0;
	// y is bottom of a text line
	uint32_t currentLine = 0;
	while(*_string && (currentLine < _firstLine) )
	{
		for (; *_string; ++_string)
		{	
			if (utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT)
			{
				if (codepoint == L'\n')
				{
					++currentLine;
					++_string;
					break;
				}
			}
		}
	}

	BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed");
	_begin = _string;

	while ( (*_string) && (currentLine < _lastLine) )
	{
		for (; *_string; ++_string)
		{	
			if(utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT)
			{
				if(codepoint == L'\n')
				{
					++currentLine;
					++_string;
					break;
				}
			}
		}
	}

	BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed");
	_end = _string;
}
Example #17
0
// default arguments start=0, end=0
int String::rfind(const String& s, int start, int end) const {
	if (start < 0) {
		start += s_len;

		if (start < 0) {
			return -1;
		}
	}

	// end must be at least at 'distance' of length of search string
	end -= s.len();

	if (end <= 0) {
		end += s_len;

		if (end <= 0) {
			return -1;
		}
	}
	if ((size_t)end > s_len) {
		end = len();
	}
	if ((size_t)start >= s_len || start > end) {
		return -1;
	}

	rune tmp[s_len + 1];
	utf8_decode(s_data, tmp, s_len + 1);

	rune tmp2[s.s_len + 1];
	utf8_decode(s.s_data, tmp2, s.s_len + 1);

	int pos;
	for(pos = end; pos >= start; pos--) {
		if (!std::memcmp(&tmp[pos], tmp2, sizeof(rune) * s.s_len)) {
			break;
		}
	}
	if (pos < start) {
		pos = -1;
	}
	return pos;
}
Example #18
0
void TextMetrics::appendText(FontHandle _fontHandle, const char* _string)
{
	const FontInfo& font = m_fontManager->getFontInfo(_fontHandle);

	if (font.lineGap > m_lineGap)
	{
		m_lineGap = font.lineGap;
	}

	if ( (font.ascender - font.descender) > m_lineHeight)
	{
		m_height -= m_lineHeight;
		m_lineHeight = font.ascender - font.descender;
		m_height += m_lineHeight;
	}

	CodePoint codepoint = 0;
	uint32_t state = 0;

	for (; *_string; ++_string)
	{
		if (!utf8_decode(&state, (uint32_t*)&codepoint, *_string) )
		{
			const GlyphInfo* glyph = m_fontManager->getGlyphInfo(_fontHandle, codepoint);
			if (NULL != glyph)
			{
				if (codepoint == L'\n')
				{
					m_height += m_lineGap + font.ascender - font.descender;					
					m_lineGap = font.lineGap;
					m_lineHeight = font.ascender - font.descender;					
					m_x = 0;
					break;
				}

				m_x += glyph->advance_x;
				if(m_x > m_width)
				{
					m_width = m_x;
				}
			}
			else
			{
				BX_CHECK(false, "Glyph not found");
			}
		}
	}

	BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed");
}
Example #19
0
bool CSprite::Init(const std::string& bname, float opacity = 1.0f)
{
	if (bname != m_ImgName)
	{
		return false;
	}
	
	m_ImgName = bname;
	std::wstring wbname = utf8_decode(bname);
	HRESULT hr = g_Graphics.LoadBitmapFromFile(wbname.c_str(), &m_pBitmap);
	
	SetOpacity(opacity);
	return SUCCEEDED(hr);
}
Example #20
0
File: tvm.c Project: fy0/tinyre
uint32_t* u8str_to_u32str(const char* p, int* len) {
    uint32_t *ret, *p2;
    int i, code, slen = utf8_len(p);

    ret = p2 = tre_new(uint32_t, slen + 1);

    for (i = 0; i < slen; i++) {
        p = utf8_decode(p, &code);
        *p2++ = (uint32_t)code;
    }

    *len = slen;
    *p2 = 0;
    return ret;
}
Example #21
0
void print_comments(FILE *out, vorbis_comment *vc, int raw)
{
	int i;
    char *decoded_value;

	for (i = 0; i < vc->comments; i++)
    {
	    if (!raw && utf8_decode(vc->user_comments[i], &decoded_value) >= 0)
        {
    		fprintf(out, "%s\n", decoded_value);
            free(decoded_value);
        }
        else
            fprintf(out, "%s\n", vc->user_comments[i]);
    }
}
Example #22
0
static UINTVAL
utf8_ord(PARROT_INTERP, ARGIN(const STRING *src), INTVAL idx)
{
    ASSERT_ARGS(utf8_ord)
    const UINTVAL len = STRING_length(src);
    const utf8_t *start;

    if (idx < 0)
        idx += len;

    if ((UINTVAL)idx >= len)
        encoding_ord_error(interp, src, idx);

    start = utf8_skip_forward((utf8_t *)src->strstart, idx);

    return utf8_decode(interp, start);
}
Example #23
0
void AllocRegistry::dump(const char *path) {

	int leakCount=0;
	size_t leakBytes=0;

	//time_t debugTime = time(NULL);
	//struct tm *loctime = localtime (&debugTime);
	struct tm loctime = threadsafe_localtime(systemtime_now());
	char szBuf2[100]="";
	strftime(szBuf2,100,"%Y-%m-%d %H:%M:%S",&loctime);

#ifdef WIN32
	FILE* f= _wfopen(utf8_decode(path).c_str(), L"wt");
#else
	FILE *f= fopen(path, "wt");
#endif

	if(f) {
		fprintf(f, "Memory leak dump at: %s\n\n",szBuf2);

		for(int index = 0; index < maxAllocs; ++index) {
			AllocInfo &info = allocs[index];
			if(info.freetouse == false && info.inuse == true) {

				if(info.line > 0) {
					leakBytes += info.bytes;

					//allocs[i].stack = AllocInfo::getStackTrace();
					fprintf(f, "Leak #%d.\tfile: %s, line: %d, ptr [%p], bytes: " MG_SIZE_T_SPECIFIER ", array: %d, inuse: %d\n%s\n", ++leakCount, info.file, info.line, info.ptr, info.bytes, info.array,info.inuse,info.stack.c_str());
				}
			}
		}

		fprintf(f, "\nTotal leaks: %d, " MG_SIZE_T_SPECIFIER " bytes\n", leakCount, leakBytes);
		fprintf(f, "Total allocations: %d, " MG_SIZE_T_SPECIFIER " bytes\n", allocCount, allocBytes);
		fprintf(f, "Not monitored allocations: %d, " MG_SIZE_T_SPECIFIER " bytes\n", nonMonitoredCount, nonMonitoredBytes);

		fclose(f);
	}

	printf("Memory leak dump summary at: %s\n",szBuf2);
	printf("Total leaks: %d, " MG_SIZE_T_SPECIFIER " bytes\n", leakCount, leakBytes);
	printf("Total allocations: %d, " MG_SIZE_T_SPECIFIER " bytes\n", allocCount, allocBytes);
	printf("Not monitored allocations: %d, " MG_SIZE_T_SPECIFIER " bytes\n", nonMonitoredCount, nonMonitoredBytes);
}
Example #24
0
uint32_t TextLineMetrics::getLineCount(const char* _string) const
{
	CodePoint codepoint = 0;
	uint32_t state = 0;
	uint32_t lineCount = 1;
	for (; *_string; ++_string)
	{
		if (utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT)
		{
			if(codepoint == L'\n')
			{				
				++lineCount;
			}
		}
	}

	BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed");
	return lineCount;
}
Example #25
0
static int strtokey1(const char *p)
{
    int i, n;

    for(i=0;i<sizeof(keycodes)/sizeof(keycodes[0]);i++) {
        if (!strcmp(p, keystr[i]))
            return keycodes[i];
    }
    if (p[0] == 'f' && isdigit((unsigned char)p[1])) {
        p++;
        n = *p - '0';
        if (isdigit((unsigned char)p[1]))
            n = n * 10 + *p - '0';
        if (n == 0)
            n = 1;
        return KEY_F1 + n - 1;
    }
    return utf8_decode(&p);;
}
Example #26
0
PyLiteStrObject* pylt_obj_str_new_from_cstr(PyLiteInterpreter *I, const char *str, bool is_raw) {
    uint32_t code;
    PyLiteStrObject *obj;
    const char *p = (const char *)str;
    int len = utf8_len(str);
    uint32_t *buf = pylt_malloc(I, (len + 1) * sizeof(uint32_t));

    for (int i = 0; i < len; i++) {
        p = utf8_decode(p, &code);
        if (!p) {
            pylt_free(I, buf, (len + 1) * sizeof(uint32_t));
            return NULL;
        }
        buf[i] = code;
    }

    obj = pylt_obj_str_new(I, buf, len, is_raw);
    return obj;
}
Example #27
0
void print_vorbis_comment (char *comment, decoder_callbacks_t *cb, 
			   void *callback_arg)
{
  char *comment_prettyprint;
  char *decoded_value;
  int offset;

  if (cb == NULL || cb->printf_metadata == NULL)
    return;

  comment_prettyprint = lookup_comment_prettyprint(comment, &offset);

  if (utf8_decode(comment + offset, &decoded_value) >= 0) {
    cb->printf_metadata(callback_arg, 1, "%s %s", comment_prettyprint, 
			decoded_value);
    free(decoded_value);
  } else
    cb->printf_metadata(callback_arg, 1, "%s %s", comment_prettyprint, 
			comment + offset);
  free(comment_prettyprint);
}
Example #28
0
/* expat char data handler */
static void _xmlrpc_charHandler(void *userData,
                        const char *s,
                        int len)
{
   xml_elem_data* mydata = (xml_elem_data*)userData;
   if(mydata && mydata->current) {

      /* Check if we need to decode utf-8 parser output to another encoding */
      if(mydata->needs_enc_conversion && mydata->input_options->encoding) {
         int new_len = 0;
         char* add_text = utf8_decode(s, len, &new_len, mydata->input_options->encoding);
         if(add_text) {
            len = new_len;
            simplestring_addn(&mydata->current->text, add_text, len);
            free(add_text);
            return;
         }
      }
      simplestring_addn(&mydata->current->text, s, len);
   }
}
Example #29
0
static char* AimApplyEncoding(char* pszStr, const char* pszEncoding)
{ // decode encoding to ANSI only
	if (pszStr && pszEncoding)
	{
		const char *szEnc = strstrnull(pszEncoding, "charset=");

		if (szEnc)
		{ // decode custom encoding to Utf-8
			char *szStr = ApplyEncoding(pszStr, szEnc + 9);
			// decode utf-8 to ansi
			char *szRes = NULL;

			SAFE_FREE((void**)&pszStr);
			utf8_decode(szStr, &szRes);
			SAFE_FREE((void**)&szStr);

			return szRes;
		}
	}
	return pszStr;
}
Example #30
0
File: util.c Project: kjk/qemacs
/* CG: this code is still quite inelegant */
static int strtokey1(const char **pp)
{
    const char *p, *p1, *q;
    int i, key;

    /* should return KEY_NONE at end and KEY_UNKNOWN if unrecognized */
    p = *pp;

    /* scan for separator */
    for (p1 = p; *p1 && *p1 != ' '; p1++)
        continue;

    for (i = 0; i < sizeof(keycodes)/sizeof(keycodes[0]); i++) {
        if (strstart(p, keystr[i], &q) && q == p1) {
            key = keycodes[i];
            *pp = p1;
            return key;
        }
    }
#if 0
    if (p[0] == 'f' && p[1] >= '1' && p[1] <= '9') {
        i = p[1] - '0';
        p += 2;
        if (p1 == isdigit((unsigned char)*p))
            i = i * 10 + *p++ - '0';
        key = KEY_F1 + i - 1;
        *pp = p1;
        return key;
    }
#endif
    if (p[0] == 'C' && p[1] == '-' && p1 == p + 3) {
        /* control */
        key = KEY_CTRL(p[2]);
    } else {
        key = utf8_decode(&p);
    }
    *pp = p1;

    return key;
}