Mercurial > hg > xemacs-beta
diff src/redisplay-xlike-inc.c @ 4881:a4322ac49e37
break out common separate-into-runs routines into redisplay-xlike-inc.c
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-01-18 Ben Wing <ben@xemacs.org>
* redisplay-xlike-inc.c:
* redisplay-xlike-inc.c (separate_textual_runs_nomule):
* redisplay-xlike-inc.c (separate_textual_runs_xft_nomule):
* redisplay-xlike-inc.c (separate_textual_runs_xft_mule):
* redisplay-xlike-inc.c (separate_textual_runs_mule):
Break separate_textual_runs_* functions from redisplay-x.c.
(Code in redisplay-gtk.c should have been identical but was
bit-rotted.)
* redisplay-gtk.c:
* redisplay-x.c:
Delete code, replace with include statement.
* depend: Regenerate.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Mon, 18 Jan 2010 06:21:05 -0600 |
parents | |
children | eab9498ecc0e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/redisplay-xlike-inc.c Mon Jan 18 06:21:05 2010 -0600 @@ -0,0 +1,355 @@ +/* Common code between X and GTK. + Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. + Copyright (C) 1994 Lucid, Inc. + Copyright (C) 1995 Sun Microsystems, Inc. + Copyright (C) 2002, 2003, 2005 Ben Wing. + +This file is part of XEmacs. + +XEmacs is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +XEmacs is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: Not in FSF. */ + + /* Note: We do not use the Xmb*() functions and XFontSets, nor the + Motif XFontLists and CompoundStrings. + Those functions are generally losing for a number of reasons. + Most important, they only support one locale (e.g. you could + display Japanese and ASCII text, but not mixed Japanese/Chinese + text). You could maybe call setlocale() frequently to try to deal + with this, but that would generally fail because an XFontSet is + tied to one locale and won't have the other character sets in it. + + fontconfig (the font database for Xft) has some specifier-like + properties, but it's not sufficient (witness the existence of + Pango). Pango might do the trick, but it's not a cross-platform + solution; it would need significant advantages to be worth the + effort. + */ + +struct textual_run +{ + Lisp_Object charset; + unsigned char *ptr; + int len; + int dimension; +}; + +/* Separate out the text in STR (an array of Ichars, not a string + representation) of length LEN into a series of runs, stored in + RUN_STORAGE. RUN_STORAGE is guaranteed to hold enough space for all + runs that could be generated from this text. Each run points to the a + stretch of text given simply by the position codes TEXT_STORAGE into a + series of textual runs of a particular charset. Also convert the + characters as necessary into the format needed by XDrawImageString(), + XDrawImageString16(), et al. This means converting to one or two byte + format, possibly tweaking the high bits, and possibly running a CCL + program. You must pre-allocate the space used and pass it in. (This is + done so you can ALLOCA () the space.) (2 * len) bytes must be allocated + for TEXT_STORAGE and (len * sizeof (struct textual_run)) bytes of + RUN_STORAGE, where LEN is the length of the dynarr. + + bufchar might not be fixed width (in the case of UTF-8). + + Returns the number of runs actually used. */ + +/* Notes on Xft implementation + + - With Unicode, we're no longer going to have repertoires reified as + charsets. (Not that we ever really did, what with corporate variants, + and so on.) So we really should be querying the face for the desired + font, rather than the character for the charset, and that's what would + determine the separation into runs. + - The widechar versions of fontconfig (and therefore Xft) functions + seem to be just bigendian Unicode. So there's actually no need to use + the 8-bit versions in computing runs and runes, it would seem. +*/ + +#if !defined(USE_XFT) && !defined(MULE) +static int +separate_textual_runs_nomule (unsigned char *text_storage, + struct textual_run *run_storage, + const Ichar *str, Charcount len, + struct face_cachel *UNUSED(cachel)) +{ + if (!len) + return 0; + + run_storage[0].ptr = text_storage; + run_storage[0].len = len; + run_storage[0].dimension = 1; + run_storage[0].charset = Qnil; + + while (len--) + *text_storage++ = *str++; + return 1; +} +#endif + +#if defined(USE_XFT) && !defined(MULE) +/* + Note that in this configuration the "Croatian hack" of using an 8-bit, + non-Latin-1 font to get localized display without Mule simply isn't + available. That's by design -- Unicode does not aid or abet that kind + of punning. + This means that the cast to XftChar16 gives the correct "conversion" to + UCS-2. + #### Is there an alignment issue with text_storage? +*/ +static int +separate_textual_runs_xft_nomule (unsigned char *text_storage, + struct textual_run *run_storage, + const Ichar *str, Charcount len, + struct face_cachel *UNUSED(cachel)) +{ + int i; + if (!len) + return 0; + + run_storage[0].ptr = text_storage; + run_storage[0].len = len; + run_storage[0].dimension = 2; + run_storage[0].charset = Qnil; + + for (i = 0; i < len; i++) + { + *(XftChar16 *)text_storage = str[i]; + text_storage += sizeof(XftChar16); + } + return 1; +} +#endif + +#if defined(USE_XFT) && defined(MULE) +static int +separate_textual_runs_xft_mule (unsigned char *text_storage, + struct textual_run *run_storage, + const Ichar *str, Charcount len, + struct face_cachel *UNUSED(cachel)) +{ + Lisp_Object prev_charset = Qunbound; + int runs_so_far = 0, i; + + run_storage[0].ptr = text_storage; + run_storage[0].len = len; + run_storage[0].dimension = 2; + run_storage[0].charset = Qnil; + + for (i = 0; i < len; i++) + { + Ichar ch = str[i]; + Lisp_Object charset = ichar_charset(ch); + int ucs = ichar_to_unicode(ch); + + /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to + REPLACMENT CHARACTER. */ + /* That means we can't handle characters outside of the BMP for now */ + ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs; + + if (!EQ (charset, prev_charset)) + { + if (runs_so_far) + run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1; + run_storage[runs_so_far].ptr = text_storage; + run_storage[runs_so_far].dimension = 2; + run_storage[runs_so_far].charset = charset; + prev_charset = charset; + runs_so_far++; + } + + *(XftChar16 *)text_storage = ucs; + text_storage += sizeof(XftChar16); + } + + if (runs_so_far) + run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1; + return runs_so_far; +} +#endif + +#if !defined(USE_XFT) && defined(MULE) +/* + This is the most complex function of this group, due to the various + indexing schemes used by different fonts. For our purposes, they + fall into three classes. Some fonts are indexed compatibly with ISO + 2022; those fonts just use the Mule internal representation directly + (typically the high bit must be reset; this is determined by the `graphic' + flag). Some fonts are indexed by Unicode, specifically by UCS-2. These + are all translated using `ichar_to_unicode'. Finally some fonts have + irregular indexes, and must be translated ad hoc. In XEmacs ad hoc + translations are accomplished with CCL programs. */ +static int +separate_textual_runs_mule (unsigned char *text_storage, + struct textual_run *run_storage, + const Ichar *str, Charcount len, + struct face_cachel *cachel) +{ + Lisp_Object prev_charset = Qunbound; + int runs_so_far = 0, i; + Ibyte charset_leading_byte = LEADING_BYTE_ASCII; + int dimension = 1, graphic = 0, need_ccl_conversion = 0; + Lisp_Object ccl_prog; + struct ccl_program char_converter; + + int translate_to_ucs_2 = 0; + + for (i = 0; i < len; i++) + { + Ichar ch = str[i]; + Lisp_Object charset; + int byte1, byte2; /* BREAKUP_ICHAR dereferences the addresses + of its arguments as pointer to int. */ + BREAKUP_ICHAR (ch, charset, byte1, byte2); + + if (!EQ (charset, prev_charset)) + { + /* At this point, dimension' and `prev_charset' refer to just- + completed run. `runs_so_far' and `text_storage' refer to the + run about to start. */ + if (runs_so_far) + { + /* Update metadata for previous run. */ + run_storage[runs_so_far - 1].len = + text_storage - run_storage[runs_so_far - 1].ptr; + if (2 == dimension) run_storage[runs_so_far - 1].len >>= 1; + } + + /* Compute metadata for current run. + First, classify font. + If the font is indexed by UCS-2, set `translate_to_ucs_2'. + Else if the charset has a CCL program, set `need_ccl_conversion'. + Else if the font is indexed by an ISO 2022 "graphic register", + set `graphic'. + These flags are almost mutually exclusive, but we're sloppy + about resetting "shadowed" flags. So the flags must be checked + in the proper order in computing byte1 and byte2, below. */ + charset_leading_byte = XCHARSET_LEADING_BYTE(charset); + translate_to_ucs_2 = + bit_vector_bit (FACE_CACHEL_FONT_FINAL_STAGE (cachel), + charset_leading_byte - MIN_LEADING_BYTE); + if (translate_to_ucs_2) + { + dimension = 2; + } + else + { + dimension = XCHARSET_DIMENSION (charset); + + /* Check for CCL charset. + If setup_ccl_program fails, we'll get a garbaged display. + This should never happen, and even if it does, it should + be harmless (unless the X server has buggy handling of + characters undefined in the font). It may be marginally + more useful to users and debuggers than substituting a + fixed replacement character. */ + ccl_prog = XCHARSET_CCL_PROGRAM (charset); + if ((!NILP (ccl_prog)) + && (setup_ccl_program (&char_converter, ccl_prog) >= 0)) + { + need_ccl_conversion = 1; + } + else + { + /* The charset must have an ISO 2022-compatible font index. + There are 2 "registers" (what such fonts use as index). + GL (graphic == 0) has the high bit of each octet reset, + GR (graphic == 1) has it set. */ + graphic = XCHARSET_GRAPHIC (charset); + need_ccl_conversion = 0; + } + } + + /* Initialize metadata for current run. */ + run_storage[runs_so_far].ptr = text_storage; + run_storage[runs_so_far].charset = charset; + run_storage[runs_so_far].dimension = dimension; + + /* Update loop variables. */ + prev_charset = charset; + runs_so_far++; + } + + /* Must check flags in this order. See comment above. */ + if (translate_to_ucs_2) + { + int ucs = ichar_to_unicode(ch); + /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to + REPLACMENT CHARACTER. */ + ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs; + + byte1 = ucs >> 8; + byte2 = ucs; + } + else if (need_ccl_conversion) + { + char_converter.reg[0] = charset_leading_byte; + char_converter.reg[1] = byte1; + char_converter.reg[2] = byte2; + ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING); + byte1 = char_converter.reg[1]; + byte2 = char_converter.reg[2]; + } + else if (graphic == 0) + { + byte1 &= 0x7F; + byte2 &= 0x7F; + } + else + { + byte1 |= 0x80; + byte2 |= 0x80; + } + + *text_storage++ = (unsigned char)byte1; + + if (2 == dimension) *text_storage++ = (unsigned char)byte2; + } + + if (runs_so_far) + { + run_storage[runs_so_far - 1].len = + text_storage - run_storage[runs_so_far - 1].ptr; + /* Dimension retains the relevant value for the run before it. */ + if (2 == dimension) + run_storage[runs_so_far - 1].len >>= 1; + } + + return runs_so_far; +} +#endif + +static int +separate_textual_runs (unsigned char *text_storage, + struct textual_run *run_storage, + const Ichar *str, Charcount len, + struct face_cachel *cachel) +{ +#if defined(USE_XFT) && defined(MULE) + return separate_textual_runs_xft_mule (text_storage, run_storage, + str, len, cachel); +#endif +#if defined(USE_XFT) && !defined(MULE) + return separate_textual_runs_xft_nomule (text_storage, run_storage, + str, len, cachel); +#endif +#if !defined(USE_XFT) && defined(MULE) + return separate_textual_runs_mule (text_storage, run_storage, + str, len, cachel); +#endif +#if !defined(USE_XFT) && !defined(MULE) + return separate_textual_runs_nomule (text_storage, run_storage, + str, len, cachel); +#endif +}