Mercurial > hg > xemacs-beta
view 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 source
/* 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 }