comparison src/redisplay-x.c @ 3659:98af8a976fc3

[xemacs-hg @ 2006-11-05 22:31:31 by aidan] Support specifying fonts for particular character sets in Mule; support translation to ISO 10646-1 for Mule character sets without an otherwise matching font; move to a vector of X11-charset-X11-registry instead of a regex for the charset-registry property.
author aidan
date Sun, 05 Nov 2006 22:31:46 +0000
parents 2b84dd8eb906
children ec0171167c5d
comparison
equal deleted inserted replaced
3658:0db1aaedbbef 3659:98af8a976fc3
39 #include "gutter.h" 39 #include "gutter.h"
40 #include "redisplay.h" 40 #include "redisplay.h"
41 #include "sysdep.h" 41 #include "sysdep.h"
42 #include "window.h" 42 #include "window.h"
43 43
44 #ifdef MULE
45 #include "mule-ccl.h" 44 #include "mule-ccl.h"
46 #endif 45 #include "charset.h"
47 46
48 #include "console-x-impl.h" 47 #include "console-x-impl.h"
49 #include "glyphs-x.h" 48 #include "glyphs-x.h"
50 #include "objects-x-impl.h" 49 #include "objects-x-impl.h"
51 #include "xgccache.h" 50 #include "xgccache.h"
152 */ 151 */
153 152
154 static int 153 static int
155 separate_textual_runs (unsigned char *text_storage, 154 separate_textual_runs (unsigned char *text_storage,
156 struct textual_run *run_storage, 155 struct textual_run *run_storage,
157 const Ichar *str, Charcount len) 156 const Ichar *str, Charcount len,
157 struct face_cachel *cachel)
158 { 158 {
159 Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a 159 Lisp_Object prev_charset = Qunbound; /* not Qnil because that is a
160 possible valid charset when 160 possible valid charset when
161 MULE is not defined */ 161 MULE is not defined */
162 int runs_so_far = 0; 162 int runs_so_far = 0, i;
163 int i; 163 Ibyte charset_leading_byte = LEADING_BYTE_ASCII;
164 #ifdef MULE 164 int dimension = 1, graphic = 0, need_ccl_conversion = 0;
165 Lisp_Object ccl_prog;
165 struct ccl_program char_converter; 166 struct ccl_program char_converter;
166 int need_ccl_conversion = 0; 167
167 #endif 168 #ifdef USE_XFT
169 #define translate_to_ucs_2 1 /* Translate to UTF-16 unconditionally. */
170 #define MAYBE_ASSIGN_TRANSLATE_TO_UCS_2(arg) (void)(arg) /* Empty,
171 may avoid some
172 warnings. */
173 #else /* USE_XFT */
174 #ifndef MULE
175 #define translate_to_ucs_2 0 /* We don't support falling back to
176 iso10646-1 without MULE */
177 #define MAYBE_ASSIGN_TRANSLATE_TO_UCS_2(arg) (void)(arg)
178 #else /* if MULE */
179 int translate_to_ucs_2 = 0;
180 #define MAYBE_ASSIGN_TRANSLATE_TO_UCS_2(arg) translate_to_ucs_2 = (arg)
181 #endif /* MULE */
182 #endif /* !USE_XFT */
168 183
169 for (i = 0; i < len; i++) 184 for (i = 0; i < len; i++)
170 { 185 {
171 Ichar ch = str[i]; 186 Ichar ch = str[i];
172 Lisp_Object charset; 187 Lisp_Object charset;
173 int byte1, byte2; /* #### why aren't these UExtbytes? */ 188 int byte1, byte2; /* Not UExbytes because BREAKUP_ICHAR takes
174 int dimension; 189 the addresses of its arguments and
175 int graphic; 190 dereferences those addresses as integer
176 191 pointers. */
177 BREAKUP_ICHAR (ch, charset, byte1, byte2); 192 BREAKUP_ICHAR (ch, charset, byte1, byte2);
178 dimension = XCHARSET_DIMENSION (charset);
179 graphic = XCHARSET_GRAPHIC (charset);
180 193
181 if (!EQ (charset, prev_charset)) 194 if (!EQ (charset, prev_charset))
182 { 195 {
183 run_storage[runs_so_far].ptr = text_storage; 196 run_storage[runs_so_far].ptr = text_storage;
184 run_storage[runs_so_far].charset = charset; 197 run_storage[runs_so_far].charset = charset;
185 #ifdef USE_XFT
186 run_storage[runs_so_far].dimension = 2;
187 #else
188 run_storage[runs_so_far].dimension = dimension;
189 #endif
190 198
191 if (runs_so_far) 199 if (runs_so_far)
192 { 200 {
193 run_storage[runs_so_far - 1].len = 201 run_storage[runs_so_far - 1].len =
194 text_storage - run_storage[runs_so_far - 1].ptr; 202 text_storage - run_storage[runs_so_far - 1].ptr;
195 if (run_storage[runs_so_far - 1].dimension == 2) 203 /* Checks the value for dimension from the previous run. */
196 run_storage[runs_so_far - 1].len >>= 1; 204 if (2 == dimension) run_storage[runs_so_far - 1].len >>= 1;
197 } 205 }
206
207 charset_leading_byte = XCHARSET_LEADING_BYTE(charset);
208
209 MAYBE_ASSIGN_TRANSLATE_TO_UCS_2
210 (bit_vector_bit(FACE_CACHEL_FONT_FINAL_STAGE
211 (cachel),
212 charset_leading_byte - MIN_LEADING_BYTE));
213
214 if (translate_to_ucs_2)
215 {
216 dimension = 2;
217 run_storage[runs_so_far].dimension = 2;
218 }
219 else
220 {
221 dimension = XCHARSET_DIMENSION (charset);
222 run_storage[runs_so_far].dimension = dimension;
223 #ifdef MULE
224 ccl_prog = XCHARSET_CCL_PROGRAM (charset);
225 if ((!NILP (ccl_prog))
226 && (setup_ccl_program (&char_converter, ccl_prog) >= 0))
227 {
228 need_ccl_conversion = 1;
229 }
230 else
231 {
232 /* The graphic property is only relevant if we're neither
233 doing the CCL conversion nor doing the UTF-16
234 conversion; it's irrelevant otherwise. */
235 graphic = XCHARSET_GRAPHIC (charset);
236 need_ccl_conversion = 0;
237 }
238 #endif /* MULE */
239 }
240 prev_charset = charset;
241
198 runs_so_far++; 242 runs_so_far++;
199 prev_charset = charset; 243 }
244
245 if (translate_to_ucs_2)
246 {
247 UINT_16_BIT ucs2;
248 int ucs = ichar_to_unicode(ch);
249
250 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to
251 REPLACMENT CHARACTER. */
252 ucs2 = (ucs & ~0xFFFF) ? 0xFFFD : ucs;
253
254 /* Ignoring the "graphic" handling. */
255 #ifdef USE_XFT
256 byte1 = ((unsigned char *) (&ucs2))[0];
257 byte2 = ((unsigned char *) (&ucs2))[1];
258 #else
259 byte1 = ((unsigned char *) (&ucs2))[1];
260 byte2 = ((unsigned char *) (&ucs2))[0];
261 #endif /* USE_XFT */
262 }
200 #ifdef MULE 263 #ifdef MULE
201 { 264 else if (need_ccl_conversion)
202 Lisp_Object ccl_prog = XCHARSET_CCL_PROGRAM (charset); 265 {
203 if ((!NILP (ccl_prog)) 266 char_converter.reg[0] = charset_leading_byte;
204 && (setup_ccl_program (&char_converter, ccl_prog) >= 0))
205 need_ccl_conversion = 1;
206 }
207 #endif
208 }
209
210 #ifndef USE_XFT
211 if (graphic == 0)
212 {
213 byte1 &= 0x7F;
214 byte2 &= 0x7F;
215 }
216 else if (graphic == 1)
217 {
218 byte1 |= 0x80;
219 byte2 |= 0x80;
220 }
221 #ifdef MULE
222 if (need_ccl_conversion)
223 {
224 char_converter.reg[0] = XCHARSET_ID (charset);
225 char_converter.reg[1] = byte1; 267 char_converter.reg[1] = byte1;
226 char_converter.reg[2] = byte2; 268 char_converter.reg[2] = byte2;
227 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING); 269 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING);
228 byte1 = char_converter.reg[1]; 270 byte1 = char_converter.reg[1];
229 byte2 = char_converter.reg[2]; 271 byte2 = char_converter.reg[2];
230 } 272 }
273 else if (graphic == 0)
274 {
275 byte1 &= 0x7F;
276 byte2 &= 0x7F;
277 }
278 else
279 {
280 byte1 |= 0x80;
281 byte2 |= 0x80;
282 }
231 #endif /* MULE */ 283 #endif /* MULE */
232 *text_storage++ = (unsigned char) byte1; 284
233 /* This dimension stuff is broken if you want to use a two-dimensional 285 *text_storage++ = (unsigned char)byte1;
234 X11 font to display a single-dimensional character set, as is 286
235 appropriate for the IPA (use one of the -iso10646-1 fonts) or some 287 /* dimension can be two in non-Mule if we're translating to
236 of the other non-standard character sets. */ 288 Unicode. */
237 if (dimension == 2) 289 if (2 == dimension) *text_storage++ = (unsigned char)byte2;
238 *text_storage++ = (unsigned char) byte2;
239 #else /* USE_XFT */
240 /* #### This is bogus as hell. XftChar16, aka FcChar16, is actually
241 unsigned short, and therefore is not suitable for indexing matrix
242 fonts such as the JIS fonts supplied with X11. But if this were
243 consistent, the XftDraw*8 and XftDraw*16 functions are pretty
244 incoherent, as then we not should allow anything but ISO 8859/1
245 (ie, the first 256 code points of Unicode) in XftDraw*8. So it
246 looks like this depends on the font, not the charset. */
247 {
248 XftChar16 xftchar16 = 0xFFFD; /* unsigned short */
249 #ifndef MULE
250 int unicode = ch;
251 #else
252 int unicode = ichar_to_unicode (ch);
253 if (unicode < 0)
254 /* abort(); */ /* #### serious error, tables are corrupt
255 Unfortunately, not a valid assumption; this can happen with
256 composite characters. Fake it. */
257 unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
258 else if (need_ccl_conversion)
259 /* #### maybe we should just ignore this and hope the font wins? */
260 unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
261 else if (unicode > 65535)
262 unicode = 0xFFFD; /* REPLACEMENT CHARACTER, can't represent */
263 else
264 #endif
265 xftchar16 = (XftChar16) unicode;
266 /* #### endianness dependency? No,
267 apparently xft handles endianness for us;
268 the "big-endian" code works on Intel and PPC */
269 #if 1
270 /* big-endian or auto-endian */
271 byte1 = ((unsigned char *) (&xftchar16))[0];
272 byte2 = ((unsigned char *) (&xftchar16))[1];
273 #else
274 /* little-endian */
275 byte1 = ((unsigned char *) (&xftchar16))[1];
276 byte2 = ((unsigned char *) (&xftchar16))[0];
277 #endif
278 }
279 *text_storage++ = (unsigned char) byte1;
280 *text_storage++ = (unsigned char) byte2;
281 #endif /* USE_XFT */
282 } 290 }
283 291
284 if (runs_so_far) 292 if (runs_so_far)
285 { 293 {
286 run_storage[runs_so_far - 1].len = 294 run_storage[runs_so_far - 1].len =
287 text_storage - run_storage[runs_so_far - 1].ptr; 295 text_storage - run_storage[runs_so_far - 1].ptr;
288 if (run_storage[runs_so_far - 1].dimension == 2) 296 /* Dimension retains the relevant value for the run before it. */
297 if (2 == dimension)
289 run_storage[runs_so_far - 1].len >>= 1; 298 run_storage[runs_so_far - 1].len >>= 1;
290 } 299 }
291 300
292 return runs_so_far; 301 return runs_so_far;
293 } 302 }
359 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len); 368 unsigned char *text_storage = (unsigned char *) ALLOCA (2 * len);
360 struct textual_run *runs = alloca_array (struct textual_run, len); 369 struct textual_run *runs = alloca_array (struct textual_run, len);
361 int nruns; 370 int nruns;
362 int i; 371 int i;
363 372
364 nruns = separate_textual_runs (text_storage, runs, str, len); 373 nruns = separate_textual_runs (text_storage, runs, str, len,
374 cachel);
365 375
366 for (i = 0; i < nruns; i++) 376 for (i = 0; i < nruns; i++)
367 width_so_far += x_text_width_single_run (f, cachel, runs + i); 377 width_so_far += x_text_width_single_run (f, cachel, runs + i);
368 378
369 return width_so_far; 379 return width_so_far;
1012 ypos, clip_end - clip_start, 1022 ypos, clip_end - clip_start,
1013 height); 1023 height);
1014 } 1024 }
1015 1025
1016 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0), 1026 nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0),
1017 Dynarr_length (buf)); 1027 Dynarr_length (buf), cachel);
1018 1028
1019 for (i = 0; i < nruns; i++) 1029 for (i = 0; i < nruns; i++)
1020 { 1030 {
1021 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset); 1031 Lisp_Object font = FACE_CACHEL_FONT (cachel, runs[i].charset);
1022 Lisp_Font_Instance *fi = XFONT_INSTANCE (font); 1032 Lisp_Font_Instance *fi = XFONT_INSTANCE (font);