Mercurial > hg > xemacs-beta
comparison 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 |
comparison
equal
deleted
inserted
replaced
4880:ae81a2c00f4f | 4881:a4322ac49e37 |
---|---|
1 /* Common code between X and GTK. | |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1994 Lucid, Inc. | |
4 Copyright (C) 1995 Sun Microsystems, Inc. | |
5 Copyright (C) 2002, 2003, 2005 Ben Wing. | |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Not in FSF. */ | |
25 | |
26 /* Note: We do not use the Xmb*() functions and XFontSets, nor the | |
27 Motif XFontLists and CompoundStrings. | |
28 Those functions are generally losing for a number of reasons. | |
29 Most important, they only support one locale (e.g. you could | |
30 display Japanese and ASCII text, but not mixed Japanese/Chinese | |
31 text). You could maybe call setlocale() frequently to try to deal | |
32 with this, but that would generally fail because an XFontSet is | |
33 tied to one locale and won't have the other character sets in it. | |
34 | |
35 fontconfig (the font database for Xft) has some specifier-like | |
36 properties, but it's not sufficient (witness the existence of | |
37 Pango). Pango might do the trick, but it's not a cross-platform | |
38 solution; it would need significant advantages to be worth the | |
39 effort. | |
40 */ | |
41 | |
42 struct textual_run | |
43 { | |
44 Lisp_Object charset; | |
45 unsigned char *ptr; | |
46 int len; | |
47 int dimension; | |
48 }; | |
49 | |
50 /* Separate out the text in STR (an array of Ichars, not a string | |
51 representation) of length LEN into a series of runs, stored in | |
52 RUN_STORAGE. RUN_STORAGE is guaranteed to hold enough space for all | |
53 runs that could be generated from this text. Each run points to the a | |
54 stretch of text given simply by the position codes TEXT_STORAGE into a | |
55 series of textual runs of a particular charset. Also convert the | |
56 characters as necessary into the format needed by XDrawImageString(), | |
57 XDrawImageString16(), et al. This means converting to one or two byte | |
58 format, possibly tweaking the high bits, and possibly running a CCL | |
59 program. You must pre-allocate the space used and pass it in. (This is | |
60 done so you can ALLOCA () the space.) (2 * len) bytes must be allocated | |
61 for TEXT_STORAGE and (len * sizeof (struct textual_run)) bytes of | |
62 RUN_STORAGE, where LEN is the length of the dynarr. | |
63 | |
64 bufchar might not be fixed width (in the case of UTF-8). | |
65 | |
66 Returns the number of runs actually used. */ | |
67 | |
68 /* Notes on Xft implementation | |
69 | |
70 - With Unicode, we're no longer going to have repertoires reified as | |
71 charsets. (Not that we ever really did, what with corporate variants, | |
72 and so on.) So we really should be querying the face for the desired | |
73 font, rather than the character for the charset, and that's what would | |
74 determine the separation into runs. | |
75 - The widechar versions of fontconfig (and therefore Xft) functions | |
76 seem to be just bigendian Unicode. So there's actually no need to use | |
77 the 8-bit versions in computing runs and runes, it would seem. | |
78 */ | |
79 | |
80 #if !defined(USE_XFT) && !defined(MULE) | |
81 static int | |
82 separate_textual_runs_nomule (unsigned char *text_storage, | |
83 struct textual_run *run_storage, | |
84 const Ichar *str, Charcount len, | |
85 struct face_cachel *UNUSED(cachel)) | |
86 { | |
87 if (!len) | |
88 return 0; | |
89 | |
90 run_storage[0].ptr = text_storage; | |
91 run_storage[0].len = len; | |
92 run_storage[0].dimension = 1; | |
93 run_storage[0].charset = Qnil; | |
94 | |
95 while (len--) | |
96 *text_storage++ = *str++; | |
97 return 1; | |
98 } | |
99 #endif | |
100 | |
101 #if defined(USE_XFT) && !defined(MULE) | |
102 /* | |
103 Note that in this configuration the "Croatian hack" of using an 8-bit, | |
104 non-Latin-1 font to get localized display without Mule simply isn't | |
105 available. That's by design -- Unicode does not aid or abet that kind | |
106 of punning. | |
107 This means that the cast to XftChar16 gives the correct "conversion" to | |
108 UCS-2. | |
109 #### Is there an alignment issue with text_storage? | |
110 */ | |
111 static int | |
112 separate_textual_runs_xft_nomule (unsigned char *text_storage, | |
113 struct textual_run *run_storage, | |
114 const Ichar *str, Charcount len, | |
115 struct face_cachel *UNUSED(cachel)) | |
116 { | |
117 int i; | |
118 if (!len) | |
119 return 0; | |
120 | |
121 run_storage[0].ptr = text_storage; | |
122 run_storage[0].len = len; | |
123 run_storage[0].dimension = 2; | |
124 run_storage[0].charset = Qnil; | |
125 | |
126 for (i = 0; i < len; i++) | |
127 { | |
128 *(XftChar16 *)text_storage = str[i]; | |
129 text_storage += sizeof(XftChar16); | |
130 } | |
131 return 1; | |
132 } | |
133 #endif | |
134 | |
135 #if defined(USE_XFT) && defined(MULE) | |
136 static int | |
137 separate_textual_runs_xft_mule (unsigned char *text_storage, | |
138 struct textual_run *run_storage, | |
139 const Ichar *str, Charcount len, | |
140 struct face_cachel *UNUSED(cachel)) | |
141 { | |
142 Lisp_Object prev_charset = Qunbound; | |
143 int runs_so_far = 0, i; | |
144 | |
145 run_storage[0].ptr = text_storage; | |
146 run_storage[0].len = len; | |
147 run_storage[0].dimension = 2; | |
148 run_storage[0].charset = Qnil; | |
149 | |
150 for (i = 0; i < len; i++) | |
151 { | |
152 Ichar ch = str[i]; | |
153 Lisp_Object charset = ichar_charset(ch); | |
154 int ucs = ichar_to_unicode(ch); | |
155 | |
156 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to | |
157 REPLACMENT CHARACTER. */ | |
158 /* That means we can't handle characters outside of the BMP for now */ | |
159 ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs; | |
160 | |
161 if (!EQ (charset, prev_charset)) | |
162 { | |
163 if (runs_so_far) | |
164 run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1; | |
165 run_storage[runs_so_far].ptr = text_storage; | |
166 run_storage[runs_so_far].dimension = 2; | |
167 run_storage[runs_so_far].charset = charset; | |
168 prev_charset = charset; | |
169 runs_so_far++; | |
170 } | |
171 | |
172 *(XftChar16 *)text_storage = ucs; | |
173 text_storage += sizeof(XftChar16); | |
174 } | |
175 | |
176 if (runs_so_far) | |
177 run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1; | |
178 return runs_so_far; | |
179 } | |
180 #endif | |
181 | |
182 #if !defined(USE_XFT) && defined(MULE) | |
183 /* | |
184 This is the most complex function of this group, due to the various | |
185 indexing schemes used by different fonts. For our purposes, they | |
186 fall into three classes. Some fonts are indexed compatibly with ISO | |
187 2022; those fonts just use the Mule internal representation directly | |
188 (typically the high bit must be reset; this is determined by the `graphic' | |
189 flag). Some fonts are indexed by Unicode, specifically by UCS-2. These | |
190 are all translated using `ichar_to_unicode'. Finally some fonts have | |
191 irregular indexes, and must be translated ad hoc. In XEmacs ad hoc | |
192 translations are accomplished with CCL programs. */ | |
193 static int | |
194 separate_textual_runs_mule (unsigned char *text_storage, | |
195 struct textual_run *run_storage, | |
196 const Ichar *str, Charcount len, | |
197 struct face_cachel *cachel) | |
198 { | |
199 Lisp_Object prev_charset = Qunbound; | |
200 int runs_so_far = 0, i; | |
201 Ibyte charset_leading_byte = LEADING_BYTE_ASCII; | |
202 int dimension = 1, graphic = 0, need_ccl_conversion = 0; | |
203 Lisp_Object ccl_prog; | |
204 struct ccl_program char_converter; | |
205 | |
206 int translate_to_ucs_2 = 0; | |
207 | |
208 for (i = 0; i < len; i++) | |
209 { | |
210 Ichar ch = str[i]; | |
211 Lisp_Object charset; | |
212 int byte1, byte2; /* BREAKUP_ICHAR dereferences the addresses | |
213 of its arguments as pointer to int. */ | |
214 BREAKUP_ICHAR (ch, charset, byte1, byte2); | |
215 | |
216 if (!EQ (charset, prev_charset)) | |
217 { | |
218 /* At this point, dimension' and `prev_charset' refer to just- | |
219 completed run. `runs_so_far' and `text_storage' refer to the | |
220 run about to start. */ | |
221 if (runs_so_far) | |
222 { | |
223 /* Update metadata for previous run. */ | |
224 run_storage[runs_so_far - 1].len = | |
225 text_storage - run_storage[runs_so_far - 1].ptr; | |
226 if (2 == dimension) run_storage[runs_so_far - 1].len >>= 1; | |
227 } | |
228 | |
229 /* Compute metadata for current run. | |
230 First, classify font. | |
231 If the font is indexed by UCS-2, set `translate_to_ucs_2'. | |
232 Else if the charset has a CCL program, set `need_ccl_conversion'. | |
233 Else if the font is indexed by an ISO 2022 "graphic register", | |
234 set `graphic'. | |
235 These flags are almost mutually exclusive, but we're sloppy | |
236 about resetting "shadowed" flags. So the flags must be checked | |
237 in the proper order in computing byte1 and byte2, below. */ | |
238 charset_leading_byte = XCHARSET_LEADING_BYTE(charset); | |
239 translate_to_ucs_2 = | |
240 bit_vector_bit (FACE_CACHEL_FONT_FINAL_STAGE (cachel), | |
241 charset_leading_byte - MIN_LEADING_BYTE); | |
242 if (translate_to_ucs_2) | |
243 { | |
244 dimension = 2; | |
245 } | |
246 else | |
247 { | |
248 dimension = XCHARSET_DIMENSION (charset); | |
249 | |
250 /* Check for CCL charset. | |
251 If setup_ccl_program fails, we'll get a garbaged display. | |
252 This should never happen, and even if it does, it should | |
253 be harmless (unless the X server has buggy handling of | |
254 characters undefined in the font). It may be marginally | |
255 more useful to users and debuggers than substituting a | |
256 fixed replacement character. */ | |
257 ccl_prog = XCHARSET_CCL_PROGRAM (charset); | |
258 if ((!NILP (ccl_prog)) | |
259 && (setup_ccl_program (&char_converter, ccl_prog) >= 0)) | |
260 { | |
261 need_ccl_conversion = 1; | |
262 } | |
263 else | |
264 { | |
265 /* The charset must have an ISO 2022-compatible font index. | |
266 There are 2 "registers" (what such fonts use as index). | |
267 GL (graphic == 0) has the high bit of each octet reset, | |
268 GR (graphic == 1) has it set. */ | |
269 graphic = XCHARSET_GRAPHIC (charset); | |
270 need_ccl_conversion = 0; | |
271 } | |
272 } | |
273 | |
274 /* Initialize metadata for current run. */ | |
275 run_storage[runs_so_far].ptr = text_storage; | |
276 run_storage[runs_so_far].charset = charset; | |
277 run_storage[runs_so_far].dimension = dimension; | |
278 | |
279 /* Update loop variables. */ | |
280 prev_charset = charset; | |
281 runs_so_far++; | |
282 } | |
283 | |
284 /* Must check flags in this order. See comment above. */ | |
285 if (translate_to_ucs_2) | |
286 { | |
287 int ucs = ichar_to_unicode(ch); | |
288 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to | |
289 REPLACMENT CHARACTER. */ | |
290 ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs; | |
291 | |
292 byte1 = ucs >> 8; | |
293 byte2 = ucs; | |
294 } | |
295 else if (need_ccl_conversion) | |
296 { | |
297 char_converter.reg[0] = charset_leading_byte; | |
298 char_converter.reg[1] = byte1; | |
299 char_converter.reg[2] = byte2; | |
300 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING); | |
301 byte1 = char_converter.reg[1]; | |
302 byte2 = char_converter.reg[2]; | |
303 } | |
304 else if (graphic == 0) | |
305 { | |
306 byte1 &= 0x7F; | |
307 byte2 &= 0x7F; | |
308 } | |
309 else | |
310 { | |
311 byte1 |= 0x80; | |
312 byte2 |= 0x80; | |
313 } | |
314 | |
315 *text_storage++ = (unsigned char)byte1; | |
316 | |
317 if (2 == dimension) *text_storage++ = (unsigned char)byte2; | |
318 } | |
319 | |
320 if (runs_so_far) | |
321 { | |
322 run_storage[runs_so_far - 1].len = | |
323 text_storage - run_storage[runs_so_far - 1].ptr; | |
324 /* Dimension retains the relevant value for the run before it. */ | |
325 if (2 == dimension) | |
326 run_storage[runs_so_far - 1].len >>= 1; | |
327 } | |
328 | |
329 return runs_so_far; | |
330 } | |
331 #endif | |
332 | |
333 static int | |
334 separate_textual_runs (unsigned char *text_storage, | |
335 struct textual_run *run_storage, | |
336 const Ichar *str, Charcount len, | |
337 struct face_cachel *cachel) | |
338 { | |
339 #if defined(USE_XFT) && defined(MULE) | |
340 return separate_textual_runs_xft_mule (text_storage, run_storage, | |
341 str, len, cachel); | |
342 #endif | |
343 #if defined(USE_XFT) && !defined(MULE) | |
344 return separate_textual_runs_xft_nomule (text_storage, run_storage, | |
345 str, len, cachel); | |
346 #endif | |
347 #if !defined(USE_XFT) && defined(MULE) | |
348 return separate_textual_runs_mule (text_storage, run_storage, | |
349 str, len, cachel); | |
350 #endif | |
351 #if !defined(USE_XFT) && !defined(MULE) | |
352 return separate_textual_runs_nomule (text_storage, run_storage, | |
353 str, len, cachel); | |
354 #endif | |
355 } |