Mercurial > hg > xemacs-beta
comparison src/redisplay-x.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 | 11daf37dae4d |
children | eab9498ecc0e |
comparison
equal
deleted
inserted
replaced
4880:ae81a2c00f4f | 4881:a4322ac49e37 |
---|---|
75 #ifdef USE_XFT | 75 #ifdef USE_XFT |
76 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ | 76 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ |
77 ? ((unsigned long) (x)) : ((unsigned long) (y))) | 77 ? ((unsigned long) (x)) : ((unsigned long) (y))) |
78 #endif /* USE_XFT */ | 78 #endif /* USE_XFT */ |
79 | 79 |
80 | 80 #include "redisplay-xlike-inc.c" |
81 /* Note: We do not use the Xmb*() functions and XFontSets, nor the | |
82 Motif XFontLists and CompoundStrings. | |
83 Those functions are generally losing for a number of reasons. | |
84 Most important, they only support one locale (e.g. you could | |
85 display Japanese and ASCII text, but not mixed Japanese/Chinese | |
86 text). You could maybe call setlocale() frequently to try to deal | |
87 with this, but that would generally fail because an XFontSet is | |
88 tied to one locale and won't have the other character sets in it. | |
89 | |
90 fontconfig (the font database for Xft) has some specifier-like | |
91 properties, but it's not sufficient (witness the existence of | |
92 Pango). Pango might do the trick, but it's not a cross-platform | |
93 solution; it would need significant advantages to be worth the | |
94 effort. | |
95 */ | |
96 | |
97 /* #### Break me out into a separate header */ | |
98 struct textual_run | |
99 { | |
100 Lisp_Object charset; | |
101 unsigned char *ptr; | |
102 int len; | |
103 int dimension; | |
104 }; | |
105 | |
106 /* Separate out the text in DYN into a series of textual runs of a | |
107 particular charset. Also convert the characters as necessary into | |
108 the format needed by XDrawImageString(), XDrawImageString16(), et | |
109 al. This means converting to one or two byte format, possibly | |
110 tweaking the high bits, and possibly running a CCL program. You | |
111 must pre-allocate the space used and pass it in. (This is done so | |
112 you can ALLOCA () the space.) (sizeof(bufchar) * len) bytes must be | |
113 allocated for TEXT_STORAGE and (len * sizeof (struct textual_run)) | |
114 bytes of RUN_STORAGE, where LEN is the length of the dynarr. | |
115 | |
116 bufchar might not be fixed width (in the case of UTF-8). | |
117 | |
118 Returns the number of runs actually used. */ | |
119 | |
120 /* Notes on Xft implementation | |
121 | |
122 - With Unicode, we're no longer going to have repertoires reified as | |
123 charsets. (Not that we ever really did, what with corporate variants, | |
124 and so on.) So we really should be querying the face for the desired | |
125 font, rather than the character for the charset, and that's what would | |
126 determine the separation into runs. | |
127 - The widechar versions of fontconfig (and therefore Xft) functions | |
128 seem to be just bigendian Unicode. So there's actually no need to use | |
129 the 8-bit versions in computing runs and runes, it would seem. | |
130 */ | |
131 | |
132 #if !defined(USE_XFT) && !defined(MULE) | |
133 static int | |
134 separate_textual_runs_nomule (unsigned char *text_storage, | |
135 struct textual_run *run_storage, | |
136 const Ichar *str, Charcount len, | |
137 struct face_cachel *UNUSED(cachel)) | |
138 { | |
139 if (!len) | |
140 return 0; | |
141 | |
142 run_storage[0].ptr = text_storage; | |
143 run_storage[0].len = len; | |
144 run_storage[0].dimension = 1; | |
145 run_storage[0].charset = Qnil; | |
146 | |
147 while (len--) | |
148 *text_storage++ = *str++; | |
149 return 1; | |
150 } | |
151 #endif | |
152 | |
153 #if defined(USE_XFT) && !defined(MULE) | |
154 /* | |
155 Note that in this configuration the "Croatian hack" of using an 8-bit, | |
156 non-Latin-1 font to get localized display without Mule simply isn't | |
157 available. That's by design -- Unicode does not aid or abet that kind | |
158 of punning. | |
159 This means that the cast to XftChar16 gives the correct "conversion" to | |
160 UCS-2. | |
161 #### Is there an alignment issue with text_storage? | |
162 */ | |
163 static int | |
164 separate_textual_runs_xft_nomule (unsigned char *text_storage, | |
165 struct textual_run *run_storage, | |
166 const Ichar *str, Charcount len, | |
167 struct face_cachel *UNUSED(cachel)) | |
168 { | |
169 int i; | |
170 if (!len) | |
171 return 0; | |
172 | |
173 run_storage[0].ptr = text_storage; | |
174 run_storage[0].len = len; | |
175 run_storage[0].dimension = 2; | |
176 run_storage[0].charset = Qnil; | |
177 | |
178 for (i = 0; i < len; i++) | |
179 { | |
180 *(XftChar16 *)text_storage = str[i]; | |
181 text_storage += sizeof(XftChar16); | |
182 } | |
183 return 1; | |
184 } | |
185 #endif | |
186 | |
187 #if defined(USE_XFT) && defined(MULE) | |
188 static int | |
189 separate_textual_runs_xft_mule (unsigned char *text_storage, | |
190 struct textual_run *run_storage, | |
191 const Ichar *str, Charcount len, | |
192 struct face_cachel *UNUSED(cachel)) | |
193 { | |
194 Lisp_Object prev_charset = Qunbound; | |
195 int runs_so_far = 0, i; | |
196 | |
197 run_storage[0].ptr = text_storage; | |
198 run_storage[0].len = len; | |
199 run_storage[0].dimension = 2; | |
200 run_storage[0].charset = Qnil; | |
201 | |
202 for (i = 0; i < len; i++) | |
203 { | |
204 Ichar ch = str[i]; | |
205 Lisp_Object charset = ichar_charset(ch); | |
206 int ucs = ichar_to_unicode(ch); | |
207 | |
208 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to | |
209 REPLACMENT CHARACTER. */ | |
210 /* That means we can't handle characters outside of the BMP for now */ | |
211 ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs; | |
212 | |
213 if (!EQ (charset, prev_charset)) | |
214 { | |
215 if (runs_so_far) | |
216 run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1; | |
217 run_storage[runs_so_far].ptr = text_storage; | |
218 run_storage[runs_so_far].dimension = 2; | |
219 run_storage[runs_so_far].charset = charset; | |
220 prev_charset = charset; | |
221 runs_so_far++; | |
222 } | |
223 | |
224 *(XftChar16 *)text_storage = ucs; | |
225 text_storage += sizeof(XftChar16); | |
226 } | |
227 | |
228 if (runs_so_far) | |
229 run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1; | |
230 return runs_so_far; | |
231 } | |
232 #endif | |
233 | |
234 #if !defined(USE_XFT) && defined(MULE) | |
235 /* | |
236 This is the most complex function of this group, due to the various | |
237 indexing schemes used by different fonts. For our purposes, they | |
238 fall into three classes. Some fonts are indexed compatibly with ISO | |
239 2022; those fonts just use the Mule internal representation directly | |
240 (typically the high bit must be reset; this is determined by the `graphic' | |
241 flag). Some fonts are indexed by Unicode, specifically by UCS-2. These | |
242 are all translated using `ichar_to_unicode'. Finally some fonts have | |
243 irregular indexes, and must be translated ad hoc. In XEmacs ad hoc | |
244 translations are accomplished with CCL programs. */ | |
245 static int | |
246 separate_textual_runs_mule (unsigned char *text_storage, | |
247 struct textual_run *run_storage, | |
248 const Ichar *str, Charcount len, | |
249 struct face_cachel *cachel) | |
250 { | |
251 Lisp_Object prev_charset = Qunbound; | |
252 int runs_so_far = 0, i; | |
253 Ibyte charset_leading_byte = LEADING_BYTE_ASCII; | |
254 int dimension = 1, graphic = 0, need_ccl_conversion = 0; | |
255 Lisp_Object ccl_prog; | |
256 struct ccl_program char_converter; | |
257 | |
258 int translate_to_ucs_2 = 0; | |
259 | |
260 for (i = 0; i < len; i++) | |
261 { | |
262 Ichar ch = str[i]; | |
263 Lisp_Object charset; | |
264 int byte1, byte2; /* BREAKUP_ICHAR dereferences the addresses | |
265 of its arguments as pointer to int. */ | |
266 BREAKUP_ICHAR (ch, charset, byte1, byte2); | |
267 | |
268 if (!EQ (charset, prev_charset)) | |
269 { | |
270 /* At this point, dimension' and `prev_charset' refer to just- | |
271 completed run. `runs_so_far' and `text_storage' refer to the | |
272 run about to start. */ | |
273 if (runs_so_far) | |
274 { | |
275 /* Update metadata for previous run. */ | |
276 run_storage[runs_so_far - 1].len = | |
277 text_storage - run_storage[runs_so_far - 1].ptr; | |
278 if (2 == dimension) run_storage[runs_so_far - 1].len >>= 1; | |
279 } | |
280 | |
281 /* Compute metadata for current run. | |
282 First, classify font. | |
283 If the font is indexed by UCS-2, set `translate_to_ucs_2'. | |
284 Else if the charset has a CCL program, set `need_ccl_conversion'. | |
285 Else if the font is indexed by an ISO 2022 "graphic register", | |
286 set `graphic'. | |
287 These flags are almost mutually exclusive, but we're sloppy | |
288 about resetting "shadowed" flags. So the flags must be checked | |
289 in the proper order in computing byte1 and byte2, below. */ | |
290 charset_leading_byte = XCHARSET_LEADING_BYTE(charset); | |
291 translate_to_ucs_2 = | |
292 bit_vector_bit (FACE_CACHEL_FONT_FINAL_STAGE (cachel), | |
293 charset_leading_byte - MIN_LEADING_BYTE); | |
294 if (translate_to_ucs_2) | |
295 { | |
296 dimension = 2; | |
297 } | |
298 else | |
299 { | |
300 dimension = XCHARSET_DIMENSION (charset); | |
301 | |
302 /* Check for CCL charset. | |
303 If setup_ccl_program fails, we'll get a garbaged display. | |
304 This should never happen, and even if it does, it should | |
305 be harmless (unless the X server has buggy handling of | |
306 characters undefined in the font). It may be marginally | |
307 more useful to users and debuggers than substituting a | |
308 fixed replacement character. */ | |
309 ccl_prog = XCHARSET_CCL_PROGRAM (charset); | |
310 if ((!NILP (ccl_prog)) | |
311 && (setup_ccl_program (&char_converter, ccl_prog) >= 0)) | |
312 { | |
313 need_ccl_conversion = 1; | |
314 } | |
315 else | |
316 { | |
317 /* The charset must have an ISO 2022-compatible font index. | |
318 There are 2 "registers" (what such fonts use as index). | |
319 GL (graphic == 0) has the high bit of each octet reset, | |
320 GR (graphic == 1) has it set. */ | |
321 graphic = XCHARSET_GRAPHIC (charset); | |
322 need_ccl_conversion = 0; | |
323 } | |
324 } | |
325 | |
326 /* Initialize metadata for current run. */ | |
327 run_storage[runs_so_far].ptr = text_storage; | |
328 run_storage[runs_so_far].charset = charset; | |
329 run_storage[runs_so_far].dimension = dimension; | |
330 | |
331 /* Update loop variables. */ | |
332 prev_charset = charset; | |
333 runs_so_far++; | |
334 } | |
335 | |
336 /* Must check flags in this order. See comment above. */ | |
337 if (translate_to_ucs_2) | |
338 { | |
339 int ucs = ichar_to_unicode(ch); | |
340 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to | |
341 REPLACMENT CHARACTER. */ | |
342 ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs; | |
343 | |
344 byte1 = ucs >> 8; | |
345 byte2 = ucs; | |
346 } | |
347 else if (need_ccl_conversion) | |
348 { | |
349 char_converter.reg[0] = charset_leading_byte; | |
350 char_converter.reg[1] = byte1; | |
351 char_converter.reg[2] = byte2; | |
352 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING); | |
353 byte1 = char_converter.reg[1]; | |
354 byte2 = char_converter.reg[2]; | |
355 } | |
356 else if (graphic == 0) | |
357 { | |
358 byte1 &= 0x7F; | |
359 byte2 &= 0x7F; | |
360 } | |
361 else | |
362 { | |
363 byte1 |= 0x80; | |
364 byte2 |= 0x80; | |
365 } | |
366 | |
367 *text_storage++ = (unsigned char)byte1; | |
368 | |
369 if (2 == dimension) *text_storage++ = (unsigned char)byte2; | |
370 } | |
371 | |
372 if (runs_so_far) | |
373 { | |
374 run_storage[runs_so_far - 1].len = | |
375 text_storage - run_storage[runs_so_far - 1].ptr; | |
376 /* Dimension retains the relevant value for the run before it. */ | |
377 if (2 == dimension) | |
378 run_storage[runs_so_far - 1].len >>= 1; | |
379 } | |
380 | |
381 return runs_so_far; | |
382 } | |
383 #endif | |
384 | |
385 static int | |
386 separate_textual_runs (unsigned char *text_storage, | |
387 struct textual_run *run_storage, | |
388 const Ichar *str, Charcount len, | |
389 struct face_cachel *cachel) | |
390 { | |
391 #if defined(USE_XFT) && defined(MULE) | |
392 return separate_textual_runs_xft_mule(text_storage, run_storage, str, len, cachel); | |
393 #endif | |
394 #if defined(USE_XFT) && !defined(MULE) | |
395 return separate_textual_runs_xft_nomule(text_storage, run_storage, str, len, cachel); | |
396 #endif | |
397 #if !defined(USE_XFT) && defined(MULE) | |
398 return separate_textual_runs_mule(text_storage, run_storage, str, len, cachel); | |
399 #endif | |
400 #if !defined(USE_XFT) && !defined(MULE) | |
401 return separate_textual_runs_nomule(text_storage, run_storage, str, len, cachel); | |
402 #endif | |
403 } | |
404 | 81 |
405 /****************************************************************************/ | 82 /****************************************************************************/ |
406 /* */ | 83 /* */ |
407 /* X output routines */ | 84 /* X output routines */ |
408 /* */ | 85 /* */ |