6106 lines · 154.2 KB · C
RawDownload
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved	by Bram Moolenaar * Multibyte extensions partly by Sung-Hoon Baek * * Do ":help uganda"  in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. *//* * mbyte.c: Code specifically for handling multi-byte characters. * * The encoding used in the core is set with 'encoding'.  When 'encoding' is * changed, the following four variables are set (for speed). * Currently these types of character encodings are supported: * * "enc_dbcs"	    When non-zero it tells the type of double byte character *		    encoding (Chinese, Korean, Japanese, etc.). *		    The cell width on the display is equal to the number of *		    bytes.  (exception: DBCS_JPNU with first byte 0x8e) *		    Recognizing the first or second byte is difficult, it *		    requires checking a byte sequence from the start. * "enc_utf8"	    When TRUE use Unicode characters in UTF-8 encoding. *		    The cell width on the display needs to be determined from *		    the character value. *		    Recognizing bytes is easy: 0xxx.xxxx is a single-byte *		    char, 10xx.xxxx is a trailing byte, 11xx.xxxx is a leading *		    byte of a multi-byte character. *		    To make things complicated, up to two composing characters *		    are allowed.  These are drawn on top of the first char. *		    For most editing the sequence of bytes with composing *		    characters included is considered to be one character. * "enc_unicode"    When 2 use 16-bit Unicode characters (or UTF-16). *		    When 4 use 32-but Unicode characters. *		    Internally characters are stored in UTF-8 encoding to *		    avoid NUL bytes.  Conversion happens when doing I/O. *		    "enc_utf8" will also be TRUE. * * "has_mbyte" is set when "enc_dbcs" or "enc_utf8" is non-zero. * * If none of these is TRUE, 8-bit bytes are used for a character.  The * encoding isn't currently specified (TODO). * * 'encoding' specifies the encoding used in the core.  This is in registers, * text manipulation, buffers, etc.  Conversion has to be done when characters * in another encoding are received or send: * *		       clipboard *			   ^ *			   | (2) *			   V *		   +---------------+ *	      (1)  |		   | (3) *  keyboard ----->|	 core	   |-----> display *		   |		   | *		   +---------------+ *			   ^ *			   | (4) *			   V *			 file * * (1) Typed characters arrive in the current locale.  Conversion is to be *     done when 'encoding' is different from 'termencoding'. * (2) Text will be made available with the encoding specified with *     'encoding'.  If this is not sufficient, system-specific conversion *     might be required. * (3) For the GUI the correct font must be selected, no conversion done. *     Otherwise, conversion is to be done when 'encoding' differs from *     'termencoding'.  (Different in the GTK+ 2 port -- 'termencoding' *     is always used for both input and output and must always be set to *     "utf-8".  gui_mch_init() does this automatically.) * (4) The encoding of the file is specified with 'fileencoding'.  Conversion *     is to be done when it's different from 'encoding'. * * The viminfo file is a special case: Only text is converted, not file names. * Vim scripts may contain an ":encoding" command.  This has an effect for * some commands, like ":menutrans" */ #include "vim.h" #ifdef WIN32UNIX# ifndef WIN32_LEAN_AND_MEAN#  define WIN32_LEAN_AND_MEAN# endif# include <windows.h># ifdef WIN32#  undef WIN32	    /* Some windows.h define WIN32, we don't want that here. */# endif#endif #if (defined(WIN3264) || defined(WIN32UNIX)) && !defined(__MINGW32__)# include <winnls.h>#endif #ifdef FEAT_GUI_X11# include <X11/Intrinsic.h>#endif#ifdef X_LOCALE#include <X11/Xlocale.h>#endif #if defined(FEAT_GUI_GTK) && defined(FEAT_XIM) && defined(HAVE_GTK2)# include <gdk/gdkkeysyms.h># ifdef WIN3264#  include <gdk/gdkwin32.h># else#  include <gdk/gdkx.h># endif#endif #ifdef HAVE_WCHAR_H# include <wchar.h>#endif #if 0/* This has been disabled, because several people reported problems with the * wcwidth() and iswprint() library functions, esp. for Hebrew. */# ifdef __STDC_ISO_10646__#  define USE_WCHAR_FUNCTIONS# endif#endif #if defined(FEAT_MBYTE) || defined(PROTO) static int enc_canon_search __ARGS((char_u *name));static int dbcs_char2len __ARGS((int c));static int dbcs_char2bytes __ARGS((int c, char_u *buf));static int dbcs_ptr2len __ARGS((char_u *p));static int dbcs_char2cells __ARGS((int c));static int dbcs_ptr2char __ARGS((char_u *p)); /* Lookup table to quickly get the length in bytes of a UTF-8 character from * the first byte of a UTF-8 string.  Bytes which are illegal when used as the * first byte have a one, because these will be used separately. */static char utf8len_tab[256] ={    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /*bogus*/    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /*bogus*/    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,}; /* * XIM often causes trouble.  Define XIM_DEBUG to get a log of XIM callbacks * in the "xim.log" file. *//* #define XIM_DEBUG */#ifdef XIM_DEBUG    static voidxim_log(char *s, ...){    va_list arglist;    static FILE *fd = NULL;     if (fd == (FILE *)-1)	return;    if (fd == NULL)    {	fd = mch_fopen("xim.log", "w");	if (fd == NULL)	{	    EMSG("Cannot open xim.log");	    fd = (FILE *)-1;	    return;	}    }     va_start(arglist, s);    vfprintf(fd, s, arglist);    va_end(arglist);}#endif #endif #if defined(FEAT_MBYTE) || defined(FEAT_POSTSCRIPT) || defined(PROTO)/* * Canonical encoding names and their properties. * "iso-8859-n" is handled by enc_canonize() directly. */static struct{   char *name;		int prop;		int codepage;}enc_canon_table[] ={#define IDX_LATIN_1	0    {"latin1",		ENC_8BIT + ENC_LATIN1,	1252},#define IDX_ISO_2	1    {"iso-8859-2",	ENC_8BIT,		0},#define IDX_ISO_3	2    {"iso-8859-3",	ENC_8BIT,		0},#define IDX_ISO_4	3    {"iso-8859-4",	ENC_8BIT,		0},#define IDX_ISO_5	4    {"iso-8859-5",	ENC_8BIT,		0},#define IDX_ISO_6	5    {"iso-8859-6",	ENC_8BIT,		0},#define IDX_ISO_7	6    {"iso-8859-7",	ENC_8BIT,		0},#define IDX_ISO_8	7    {"iso-8859-8",	ENC_8BIT,		0},#define IDX_ISO_9	8    {"iso-8859-9",	ENC_8BIT,		0},#define IDX_ISO_10	9    {"iso-8859-10",	ENC_8BIT,		0},#define IDX_ISO_11	10    {"iso-8859-11",	ENC_8BIT,		0},#define IDX_ISO_13	11    {"iso-8859-13",	ENC_8BIT,		0},#define IDX_ISO_14	12    {"iso-8859-14",	ENC_8BIT,		0},#define IDX_ISO_15	13    {"iso-8859-15",	ENC_8BIT + ENC_LATIN9,	0},#define IDX_KOI8_R	14    {"koi8-r",		ENC_8BIT,		0},#define IDX_KOI8_U	15    {"koi8-u",		ENC_8BIT,		0},#define IDX_UTF8	16    {"utf-8",		ENC_UNICODE,		0},#define IDX_UCS2	17    {"ucs-2",		ENC_UNICODE + ENC_ENDIAN_B + ENC_2BYTE, 0},#define IDX_UCS2LE	18    {"ucs-2le",		ENC_UNICODE + ENC_ENDIAN_L + ENC_2BYTE, 0},#define IDX_UTF16	19    {"utf-16",		ENC_UNICODE + ENC_ENDIAN_B + ENC_2WORD, 0},#define IDX_UTF16LE	20    {"utf-16le",	ENC_UNICODE + ENC_ENDIAN_L + ENC_2WORD, 0},#define IDX_UCS4	21    {"ucs-4",		ENC_UNICODE + ENC_ENDIAN_B + ENC_4BYTE, 0},#define IDX_UCS4LE	22    {"ucs-4le",		ENC_UNICODE + ENC_ENDIAN_L + ENC_4BYTE, 0},     /* For debugging DBCS encoding on Unix. */#define IDX_DEBUG	23    {"debug",		ENC_DBCS,		DBCS_DEBUG},#define IDX_EUC_JP	24    {"euc-jp",		ENC_DBCS,		DBCS_JPNU},#define IDX_SJIS	25    {"sjis",		ENC_DBCS,		DBCS_JPN},#define IDX_EUC_KR	26    {"euc-kr",		ENC_DBCS,		DBCS_KORU},#define IDX_EUC_CN	27    {"euc-cn",		ENC_DBCS,		DBCS_CHSU},#define IDX_EUC_TW	28    {"euc-tw",		ENC_DBCS,		DBCS_CHTU},#define IDX_BIG5	29    {"big5",		ENC_DBCS,		DBCS_CHT},     /* MS-DOS and MS-Windows codepages are included here, so that they can be     * used on Unix too.  Most of them are similar to ISO-8859 encodings, but     * not exactly the same. */#define IDX_CP437	30    {"cp437",		ENC_8BIT,		437}, /* like iso-8859-1 */#define IDX_CP737	31    {"cp737",		ENC_8BIT,		737}, /* like iso-8859-7 */#define IDX_CP775	32    {"cp775",		ENC_8BIT,		775}, /* Baltic */#define IDX_CP850	33    {"cp850",		ENC_8BIT,		850}, /* like iso-8859-4 */#define IDX_CP852	34    {"cp852",		ENC_8BIT,		852}, /* like iso-8859-1 */#define IDX_CP855	35    {"cp855",		ENC_8BIT,		855}, /* like iso-8859-2 */#define IDX_CP857	36    {"cp857",		ENC_8BIT,		857}, /* like iso-8859-5 */#define IDX_CP860	37    {"cp860",		ENC_8BIT,		860}, /* like iso-8859-9 */#define IDX_CP861	38    {"cp861",		ENC_8BIT,		861}, /* like iso-8859-1 */#define IDX_CP862	39    {"cp862",		ENC_8BIT,		862}, /* like iso-8859-1 */#define IDX_CP863	40    {"cp863",		ENC_8BIT,		863}, /* like iso-8859-8 */#define IDX_CP865	41    {"cp865",		ENC_8BIT,		865}, /* like iso-8859-1 */#define IDX_CP866	42    {"cp866",		ENC_8BIT,		866}, /* like iso-8859-5 */#define IDX_CP869	43    {"cp869",		ENC_8BIT,		869}, /* like iso-8859-7 */#define IDX_CP874	44    {"cp874",		ENC_8BIT,		874}, /* Thai */#define IDX_CP932	45    {"cp932",		ENC_DBCS,		DBCS_JPN},#define IDX_CP936	46    {"cp936",		ENC_DBCS,		DBCS_CHS},#define IDX_CP949	47    {"cp949",		ENC_DBCS,		DBCS_KOR},#define IDX_CP950	48    {"cp950",		ENC_DBCS,		DBCS_CHT},#define IDX_CP1250	49    {"cp1250",		ENC_8BIT,		1250}, /* Czech, Polish, etc. */#define IDX_CP1251	50    {"cp1251",		ENC_8BIT,		1251}, /* Cyrillic */    /* cp1252 is considered to be equal to latin1 */#define IDX_CP1253	51    {"cp1253",		ENC_8BIT,		1253}, /* Greek */#define IDX_CP1254	52    {"cp1254",		ENC_8BIT,		1254}, /* Turkish */#define IDX_CP1255	53    {"cp1255",		ENC_8BIT,		1255}, /* Hebrew */#define IDX_CP1256	54    {"cp1256",		ENC_8BIT,		1256}, /* Arabic */#define IDX_CP1257	55    {"cp1257",		ENC_8BIT,		1257}, /* Baltic */#define IDX_CP1258	56    {"cp1258",		ENC_8BIT,		1258}, /* Vietnamese */ #define IDX_MACROMAN	57    {"macroman",	ENC_8BIT + ENC_MACROMAN, 0},	/* Mac OS */#define IDX_DECMCS	58    {"dec-mcs",		ENC_8BIT,		0},	/* DEC MCS */#define IDX_HPROMAN8	59    {"hp-roman8",	ENC_8BIT,		0},	/* HP Roman8 */#define IDX_COUNT	60}; /* * Aliases for encoding names. */static struct{   char *name;		int canon;}enc_alias_table[] ={    {"ansi",		IDX_LATIN_1},    {"iso-8859-1",	IDX_LATIN_1},    {"latin2",		IDX_ISO_2},    {"latin3",		IDX_ISO_3},    {"latin4",		IDX_ISO_4},    {"cyrillic",	IDX_ISO_5},    {"arabic",		IDX_ISO_6},    {"greek",		IDX_ISO_7},#ifdef WIN3264    {"hebrew",		IDX_CP1255},#else    {"hebrew",		IDX_ISO_8},#endif    {"latin5",		IDX_ISO_9},    {"turkish",		IDX_ISO_9}, /* ? */    {"latin6",		IDX_ISO_10},    {"nordic",		IDX_ISO_10}, /* ? */    {"thai",		IDX_ISO_11}, /* ? */    {"latin7",		IDX_ISO_13},    {"latin8",		IDX_ISO_14},    {"latin9",		IDX_ISO_15},    {"utf8",		IDX_UTF8},    {"unicode",		IDX_UCS2},    {"ucs2",		IDX_UCS2},    {"ucs2be",		IDX_UCS2},    {"ucs-2be",		IDX_UCS2},    {"ucs2le",		IDX_UCS2LE},    {"utf16",		IDX_UTF16},    {"utf16be",		IDX_UTF16},    {"utf-16be",	IDX_UTF16},    {"utf16le",		IDX_UTF16LE},    {"ucs4",		IDX_UCS4},    {"ucs4be",		IDX_UCS4},    {"ucs-4be",		IDX_UCS4},    {"ucs4le",		IDX_UCS4LE},    {"932",		IDX_CP932},    {"949",		IDX_CP949},    {"936",		IDX_CP936},    {"gbk",		IDX_CP936},    {"950",		IDX_CP950},    {"eucjp",		IDX_EUC_JP},    {"unix-jis",	IDX_EUC_JP},    {"ujis",		IDX_EUC_JP},    {"shift-jis",	IDX_SJIS},    {"euckr",		IDX_EUC_KR},    {"5601",		IDX_EUC_KR},	/* Sun: KS C 5601 */    {"euccn",		IDX_EUC_CN},    {"gb2312",		IDX_EUC_CN},    {"euctw",		IDX_EUC_TW},#if defined(WIN3264) || defined(WIN32UNIX) || defined(MACOS)    {"japan",		IDX_CP932},    {"korea",		IDX_CP949},    {"prc",		IDX_CP936},    {"chinese",		IDX_CP936},    {"taiwan",		IDX_CP950},    {"big5",		IDX_CP950},#else    {"japan",		IDX_EUC_JP},    {"korea",		IDX_EUC_KR},    {"prc",		IDX_EUC_CN},    {"chinese",		IDX_EUC_CN},    {"taiwan",		IDX_EUC_TW},    {"cp950",		IDX_BIG5},    {"950",		IDX_BIG5},#endif    {"mac",		IDX_MACROMAN},    {"mac-roman",	IDX_MACROMAN},    {NULL,		0}}; #ifndef CP_UTF8# define CP_UTF8 65001	/* magic number from winnls.h */#endif /* * Find encoding "name" in the list of canonical encoding names. * Returns -1 if not found. */    static intenc_canon_search(name)    char_u	*name;{    int		i;     for (i = 0; i < IDX_COUNT; ++i)	if (STRCMP(name, enc_canon_table[i].name) == 0)	    return i;    return -1;} #endif #if defined(FEAT_MBYTE) || defined(PROTO) /* * Find canonical encoding "name" in the list and return its properties. * Returns 0 if not found. */    intenc_canon_props(name)    char_u	*name;{    int		i;     i = enc_canon_search(name);    if (i >= 0)	return enc_canon_table[i].prop;#ifdef WIN3264    if (name[0] == 'c' && name[1] == 'p' && VIM_ISDIGIT(name[2]))    {	CPINFO	cpinfo; 	/* Get info on this codepage to find out what it is. */	if (GetCPInfo(atoi(name + 2), &cpinfo) != 0)	{	    if (cpinfo.MaxCharSize == 1) /* some single-byte encoding */		return ENC_8BIT;	    if (cpinfo.MaxCharSize == 2		    && (cpinfo.LeadByte[0] != 0 || cpinfo.LeadByte[1] != 0))		/* must be a DBCS encoding */		return ENC_DBCS;	}	return 0;    }#endif    if (STRNCMP(name, "2byte-", 6) == 0)	return ENC_DBCS;    if (STRNCMP(name, "8bit-", 5) == 0 || STRNCMP(name, "iso-8859-", 9) == 0)	return ENC_8BIT;    return 0;} /* * Set up for using multi-byte characters. * Called in three cases: * - by main() to initialize (p_enc == NULL) * - by set_init_1() after 'encoding' was set to its default. * - by do_set() when 'encoding' has been set. * p_enc must have been passed through enc_canonize() already. * Sets the "enc_unicode", "enc_utf8", "enc_dbcs" and "has_mbyte" flags. * Fills mb_bytelen_tab[] and returns NULL when there are no problems. * When there is something wrong: Returns an error message and doesn't change * anything. */    char_u *mb_init(){    int		i;    int		idx;    int		n;    int		enc_dbcs_new = 0;#if defined(USE_ICONV) && !defined(WIN3264) && !defined(WIN32UNIX) \	&& !defined(MACOS)# define LEN_FROM_CONV    vimconv_T	vimconv;    char_u	*p;#endif     if (p_enc == NULL)    {	/* Just starting up: set the whole table to one's. */	for (i = 0; i < 256; ++i)	    mb_bytelen_tab[i] = 1;	input_conv.vc_type = CONV_NONE;	input_conv.vc_factor = 1;	output_conv.vc_type = CONV_NONE;	return NULL;    } #ifdef WIN3264    if (p_enc[0] == 'c' && p_enc[1] == 'p' && VIM_ISDIGIT(p_enc[2]))    {	CPINFO	cpinfo;

Lines 1–500 of 6106.