Esempio n. 1
0
ssize_t
utf16_to_utf8(uint8_t        *out,
              const uint16_t *in,
              size_t         len)
{
  ssize_t  rc = 0;
  ssize_t  units;
  uint32_t code;
  uint8_t  encoded[4];

  do
  {
    units = decode_utf16(&code, in);
    if(units == -1)
      return -1;

    if(code > 0)
    {
      in += units;

      units = encode_utf8(encoded, code);
      if(units == -1)
        return -1;

      if(out != NULL)
      {
        if(rc + units <= len)
        {
          *out++ = encoded[0];
          if(units > 1)
            *out++ = encoded[1];
          if(units > 2)
            *out++ = encoded[2];
          if(units > 3)
            *out++ = encoded[3];
        }
      }

      if(SSIZE_MAX - units >= rc)
        rc += units;
      else
        return -1;
    }
  } while(code > 0);

  return rc;
}
Esempio n. 2
0
/*
 * v_key_name --
 *	Return the string that will display the key.  This routine
 *	is the backup for the KEY_NAME() macro.
 *
 * PUBLIC: char *v_key_name __P((SCR *, ARG_CHAR_T));
 */
char *
v_key_name(
	SCR *sp,
	ARG_CHAR_T ach)
{
	static const char hexdigit[] = "0123456789abcdef";
	static const char octdigit[] = "01234567";
	int ch;
	size_t len;
	char *chp;

	/*
	 * Cache the last checked character.  It won't be a problem
	 * since nvi will rescan the mapping when settings changed.
	 */
	if (ach && sp->lastc == ach)
		return (sp->cname);
	sp->lastc = ach;

#ifdef USE_WIDECHAR
	len = wctomb(sp->cname, ach);
	if (len > MB_CUR_MAX)
#endif
		sp->cname[(len = 1)-1] = (u_char)ach;

	ch = (u_char)sp->cname[0];
	sp->cname[len] = '\0';

	/* See if the character was explicitly declared printable or not. */
	if ((chp = O_STR(sp, O_PRINT)) != NULL)
		if (strstr(chp, sp->cname) != NULL)
			goto done;
	if ((chp = O_STR(sp, O_NOPRINT)) != NULL)
		if (strstr(chp, sp->cname) != NULL)
			goto nopr;

	/*
	 * Historical (ARPA standard) mappings.  Printable characters are left
	 * alone.  Control characters less than 0x20 are represented as '^'
	 * followed by the character offset from the '@' character in the ASCII
	 * character set.  Del (0x7f) is represented as '^' followed by '?'.
	 *
	 * XXX
	 * The following code depends on the current locale being identical to
	 * the ASCII map from 0x40 to 0x5f (since 0x1f + 0x40 == 0x5f).  I'm
	 * told that this is a reasonable assumption...
	 *
	 * XXX
	 * The code prints non-printable wide characters in 4 or 5 digits
	 * Unicode escape sequences, so only supports plane 0 to 15.
	 */
	if (ISPRINT(ach))
		goto done;
nopr:	if (iscntrl(ch) && (ch < 0x20 || ch == 0x7f)) {
		sp->cname[0] = '^';
		sp->cname[1] = ch == 0x7f ? '?' : '@' + ch;
		len = 2;
		goto done;
	}
#ifdef USE_WIDECHAR
	if (INTISWIDE(ach)) {
		int uc = -1;

		if (!strcmp(codeset(), "UTF-8"))
			uc = decode_utf8(sp->cname);
#ifdef USE_ICONV
		else {
			char buf[sizeof(sp->cname)] = "";
			size_t left = sizeof(sp->cname);
			char *in = sp->cname;
			char *out = buf;
			iconv(sp->conv.id[IC_IE_TO_UTF16],
			    (iconv_src_t)&in, &len, &out, &left);
			iconv(sp->conv.id[IC_IE_TO_UTF16],
			    NULL, NULL, NULL, NULL);
			uc = decode_utf16(buf, 1);
		}
#endif
		if (uc >= 0) {
			len = snprintf(sp->cname, sizeof(sp->cname),
			    uc < 0x10000 ? "\\u%04x" : "\\U%05X", uc);
			goto done;
		}
	}
#endif
	if (O_ISSET(sp, O_OCTAL)) {
		sp->cname[0] = '\\';
		sp->cname[1] = octdigit[(ch & 0300) >> 6];
		sp->cname[2] = octdigit[(ch &  070) >> 3];
		sp->cname[3] = octdigit[ ch &   07      ];
	} else {