Mercurial > hg > xemacs-beta
comparison src/xmu.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | abe6d1db359e |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* This file contains compatibility routines for systems without Xmu. | |
2 * You would be better served by installing Xmu on your machine or | |
3 * yelling at your vendor to ship it. | |
4 */ | |
5 | |
6 /* XEmacs changes: rindex -> strrchr */ | |
7 | |
8 /* Synched up with: Not in FSF. */ | |
9 | |
10 #include <config.h> | |
11 | |
12 #ifndef HAVE_XMU | |
13 /* | |
14 * Copyright 1989 Massachusetts Institute of Technology | |
15 * | |
16 * Permission to use, copy, modify, and distribute this software and its | |
17 * documentation for any purpose and without fee is hereby granted, provided | |
18 * that the above copyright notice appear in all copies and that both that | |
19 * copyright notice and this permission notice appear in supporting | |
20 * documentation, and that the name of M.I.T. not be used in advertising | |
21 * or publicity pertaining to distribution of the software without specific, | |
22 * written prior permission. M.I.T. makes no representations about the | |
23 * suitability of this software for any purpose. It is provided "as is" | |
24 * without express or implied warranty. | |
25 * | |
26 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL | |
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. | |
28 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
30 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
31 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
32 */ | |
33 #include <X11/cursorfont.h> | |
34 #include <X11/Xlib.h> | |
35 #include <X11/Xutil.h> | |
36 #include <X11/Intrinsic.h> | |
37 | |
38 /* for XmuCopyISOLatin1Lowered */ | |
39 #define XK_LATIN1 | |
40 #include <X11/keysymdef.h> | |
41 #undef XK_LATIN1 | |
42 | |
43 #if (XtSpecificationRelease >= 5) | |
44 /* | |
45 * Don't know why, but this works with X11R5, not X11R4. | |
46 * Anyway, _XExtension is defined in Xlib.h in X11R4, so we do not need | |
47 * Xlibint in that case... | |
48 */ | |
49 #include <X11/Xlibint.h> | |
50 #endif | |
51 #include <X11/Xproto.h> | |
52 #include <stdio.h> | |
53 #include <ctype.h> | |
54 | |
55 | |
56 int XmuCursorNameToIndex (CONST char *name) | |
57 { | |
58 static CONST struct _CursorName { | |
59 CONST char *name; | |
60 unsigned int shape; | |
61 } cursor_names[] = { | |
62 {"x_cursor", XC_X_cursor}, | |
63 {"arrow", XC_arrow}, | |
64 {"based_arrow_down", XC_based_arrow_down}, | |
65 {"based_arrow_up", XC_based_arrow_up}, | |
66 {"boat", XC_boat}, | |
67 {"bogosity", XC_bogosity}, | |
68 {"bottom_left_corner", XC_bottom_left_corner}, | |
69 {"bottom_right_corner", XC_bottom_right_corner}, | |
70 {"bottom_side", XC_bottom_side}, | |
71 {"bottom_tee", XC_bottom_tee}, | |
72 {"box_spiral", XC_box_spiral}, | |
73 {"center_ptr", XC_center_ptr}, | |
74 {"circle", XC_circle}, | |
75 {"clock", XC_clock}, | |
76 {"coffee_mug", XC_coffee_mug}, | |
77 {"cross", XC_cross}, | |
78 {"cross_reverse", XC_cross_reverse}, | |
79 {"crosshair", XC_crosshair}, | |
80 {"diamond_cross", XC_diamond_cross}, | |
81 {"dot", XC_dot}, | |
82 {"dotbox", XC_dotbox}, | |
83 {"double_arrow", XC_double_arrow}, | |
84 {"draft_large", XC_draft_large}, | |
85 {"draft_small", XC_draft_small}, | |
86 {"draped_box", XC_draped_box}, | |
87 {"exchange", XC_exchange}, | |
88 {"fleur", XC_fleur}, | |
89 {"gobbler", XC_gobbler}, | |
90 {"gumby", XC_gumby}, | |
91 {"hand1", XC_hand1}, | |
92 {"hand2", XC_hand2}, | |
93 {"heart", XC_heart}, | |
94 {"icon", XC_icon}, | |
95 {"iron_cross", XC_iron_cross}, | |
96 {"left_ptr", XC_left_ptr}, | |
97 {"left_side", XC_left_side}, | |
98 {"left_tee", XC_left_tee}, | |
99 {"leftbutton", XC_leftbutton}, | |
100 {"ll_angle", XC_ll_angle}, | |
101 {"lr_angle", XC_lr_angle}, | |
102 {"man", XC_man}, | |
103 {"middlebutton", XC_middlebutton}, | |
104 {"mouse", XC_mouse}, | |
105 {"pencil", XC_pencil}, | |
106 {"pirate", XC_pirate}, | |
107 {"plus", XC_plus}, | |
108 {"question_arrow", XC_question_arrow}, | |
109 {"right_ptr", XC_right_ptr}, | |
110 {"right_side", XC_right_side}, | |
111 {"right_tee", XC_right_tee}, | |
112 {"rightbutton", XC_rightbutton}, | |
113 {"rtl_logo", XC_rtl_logo}, | |
114 {"sailboat", XC_sailboat}, | |
115 {"sb_down_arrow", XC_sb_down_arrow}, | |
116 {"sb_h_double_arrow", XC_sb_h_double_arrow}, | |
117 {"sb_left_arrow", XC_sb_left_arrow}, | |
118 {"sb_right_arrow", XC_sb_right_arrow}, | |
119 {"sb_up_arrow", XC_sb_up_arrow}, | |
120 {"sb_v_double_arrow", XC_sb_v_double_arrow}, | |
121 {"shuttle", XC_shuttle}, | |
122 {"sizing", XC_sizing}, | |
123 {"spider", XC_spider}, | |
124 {"spraycan", XC_spraycan}, | |
125 {"star", XC_star}, | |
126 {"target", XC_target}, | |
127 {"tcross", XC_tcross}, | |
128 {"top_left_arrow", XC_top_left_arrow}, | |
129 {"top_left_corner", XC_top_left_corner}, | |
130 {"top_right_corner", XC_top_right_corner}, | |
131 {"top_side", XC_top_side}, | |
132 {"top_tee", XC_top_tee}, | |
133 {"trek", XC_trek}, | |
134 {"ul_angle", XC_ul_angle}, | |
135 {"umbrella", XC_umbrella}, | |
136 {"ur_angle", XC_ur_angle}, | |
137 {"watch", XC_watch}, | |
138 {"xterm", XC_xterm}, | |
139 }; | |
140 CONST struct _CursorName *table; | |
141 int i; | |
142 char tmp[40]; | |
143 | |
144 if (strlen (name) >= sizeof tmp) return -1; | |
145 for (i=0; i<strlen(name); i++) | |
146 if (isupper((unsigned char) name[i])) | |
147 tmp[i] = tolower((unsigned char) name[i]); | |
148 else | |
149 tmp[i] = name[i]; | |
150 tmp[i] = 0; | |
151 | |
152 for (i=0, table=cursor_names; i < XtNumber(cursor_names); i++, table++ ) { | |
153 if (strcmp(tmp, table->name) == 0) return table->shape; | |
154 } | |
155 | |
156 return -1; | |
157 } | |
158 | |
159 | |
160 /* | |
161 * Based on an optimized version provided by Jim Becker, August 5, 1988. | |
162 */ | |
163 | |
164 | |
165 #define MAX_SIZE 255 | |
166 | |
167 /* shared data for the image read/parse logic */ | |
168 static short hexTable[256]; /* conversion value */ | |
169 static int hex_initialized; /* easier to fill in at run time */ | |
170 | |
171 | |
172 /* | |
173 * Table index for the hex values. Initialized once, first time. | |
174 * Used for translation value or delimiter significance lookup. | |
175 */ | |
176 static void initHexTable (void) | |
177 { | |
178 /* | |
179 * We build the table at run time for several reasons: | |
180 * | |
181 * 1. portable to non-ASCII machines. | |
182 * 2. still reentrant since we set the init flag after setting table. | |
183 * 3. easier to extend. | |
184 * 4. less prone to bugs. | |
185 */ | |
186 hexTable['0'] = 0; hexTable['1'] = 1; | |
187 hexTable['2'] = 2; hexTable['3'] = 3; | |
188 hexTable['4'] = 4; hexTable['5'] = 5; | |
189 hexTable['6'] = 6; hexTable['7'] = 7; | |
190 hexTable['8'] = 8; hexTable['9'] = 9; | |
191 hexTable['A'] = 10; hexTable['B'] = 11; | |
192 hexTable['C'] = 12; hexTable['D'] = 13; | |
193 hexTable['E'] = 14; hexTable['F'] = 15; | |
194 hexTable['a'] = 10; hexTable['b'] = 11; | |
195 hexTable['c'] = 12; hexTable['d'] = 13; | |
196 hexTable['e'] = 14; hexTable['f'] = 15; | |
197 | |
198 /* delimiters of significance are flagged w/ negative value */ | |
199 hexTable[' '] = -1; hexTable[','] = -1; | |
200 hexTable['}'] = -1; hexTable['\n'] = -1; | |
201 hexTable['\t'] = -1; | |
202 | |
203 hex_initialized = 1; | |
204 } | |
205 | |
206 /* | |
207 * read next hex value in the input stream, return -1 if EOF | |
208 */ | |
209 static int NextInt (FILE *fstream) | |
210 { | |
211 int ch; | |
212 int value = 0; | |
213 int gotone = 0; | |
214 int done = 0; | |
215 | |
216 /* loop, accumulate hex value until find delimiter */ | |
217 /* skip any initial delimiters found in read stream */ | |
218 | |
219 while (!done) { | |
220 ch = getc(fstream); | |
221 if (ch == EOF) { | |
222 value = -1; | |
223 done++; | |
224 } else { | |
225 /* trim high bits, check type and accumulate */ | |
226 ch &= 0xff; | |
227 if (isascii(ch) && isxdigit(ch)) { | |
228 value = (value << 4) + hexTable[ch]; | |
229 gotone++; | |
230 } else if ((hexTable[ch]) < 0 && gotone) | |
231 done++; | |
232 } | |
233 } | |
234 return value; | |
235 } | |
236 | |
237 | |
238 /* | |
239 * The data returned by the following routine is always in left-most byte | |
240 * first and left-most bit first. If it doesn't return BitmapSuccess then | |
241 * its arguments won't have been touched. This routine should look as much | |
242 * like the Xlib routine XReadBitmapfile as possible. | |
243 */ | |
244 int XmuReadBitmapData ( | |
245 FILE *fstream, /* handle on file */ | |
246 unsigned int *width, /* RETURNED */ | |
247 unsigned int *height, /* RETURNED */ | |
248 unsigned char **datap, /* RETURNED */ | |
249 int *x_hot, int *y_hot) /* RETURNED */ | |
250 { | |
251 unsigned char *data = NULL; /* working variable */ | |
252 char line[MAX_SIZE]; /* input line from file */ | |
253 int size; /* number of bytes of data */ | |
254 char name_and_type[MAX_SIZE]; /* an input line */ | |
255 char *type; /* for parsing */ | |
256 int value; /* from an input line */ | |
257 int version10p; /* boolean, old format */ | |
258 int padding; /* to handle alignment */ | |
259 int bytes_per_line; /* per scanline of data */ | |
260 unsigned int ww = 0; /* width */ | |
261 unsigned int hh = 0; /* height */ | |
262 int hx = -1; /* x hotspot */ | |
263 int hy = -1; /* y hotspot */ | |
264 | |
265 #ifndef Xmalloc | |
266 #define Xmalloc(size) malloc(size) | |
267 #endif | |
268 | |
269 /* first time initialization */ | |
270 if (!hex_initialized) initHexTable(); | |
271 | |
272 /* error cleanup and return macro */ | |
273 #define RETURN(code) { if (data) free (data); return code; } | |
274 | |
275 while (fgets(line, MAX_SIZE, fstream)) { | |
276 if (strlen(line) == MAX_SIZE-1) { | |
277 RETURN (BitmapFileInvalid); | |
278 } | |
279 if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) { | |
280 if (!(type = strrchr(name_and_type, '_'))) | |
281 type = name_and_type; | |
282 else | |
283 type++; | |
284 | |
285 if (!strcmp("width", type)) | |
286 ww = (unsigned int) value; | |
287 if (!strcmp("height", type)) | |
288 hh = (unsigned int) value; | |
289 if (!strcmp("hot", type)) { | |
290 if (type-- == name_and_type || type-- == name_and_type) | |
291 continue; | |
292 if (!strcmp("x_hot", type)) | |
293 hx = value; | |
294 if (!strcmp("y_hot", type)) | |
295 hy = value; | |
296 } | |
297 continue; | |
298 } | |
299 | |
300 if (sscanf(line, "static short %s = {", name_and_type) == 1) | |
301 version10p = 1; | |
302 else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1) | |
303 version10p = 0; | |
304 else if (sscanf(line, "static char %s = {", name_and_type) == 1) | |
305 version10p = 0; | |
306 else | |
307 continue; | |
308 | |
309 if (!(type = strrchr(name_and_type, '_'))) | |
310 type = name_and_type; | |
311 else | |
312 type++; | |
313 | |
314 if (strcmp("bits[]", type)) | |
315 continue; | |
316 | |
317 if (!ww || !hh) | |
318 RETURN (BitmapFileInvalid); | |
319 | |
320 if ((ww % 16) && ((ww % 16) < 9) && version10p) | |
321 padding = 1; | |
322 else | |
323 padding = 0; | |
324 | |
325 bytes_per_line = (ww+7)/8 + padding; | |
326 | |
327 size = bytes_per_line * hh; | |
328 data = (unsigned char *) Xmalloc ((unsigned int) size); | |
329 if (!data) | |
330 RETURN (BitmapNoMemory); | |
331 | |
332 if (version10p) { | |
333 unsigned char *ptr; | |
334 int bytes; | |
335 | |
336 for (bytes=0, ptr=data; bytes<size; (bytes += 2)) { | |
337 if ((value = NextInt(fstream)) < 0) | |
338 RETURN (BitmapFileInvalid); | |
339 *(ptr++) = value; | |
340 if (!padding || ((bytes+2) % bytes_per_line)) | |
341 *(ptr++) = value >> 8; | |
342 } | |
343 } else { | |
344 unsigned char *ptr; | |
345 int bytes; | |
346 | |
347 for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) { | |
348 if ((value = NextInt(fstream)) < 0) | |
349 RETURN (BitmapFileInvalid); | |
350 *ptr=value; | |
351 } | |
352 } | |
353 break; | |
354 } /* end while */ | |
355 | |
356 if (data == NULL) { | |
357 RETURN (BitmapFileInvalid); | |
358 } | |
359 | |
360 *datap = data; | |
361 data = NULL; | |
362 *width = ww; | |
363 *height = hh; | |
364 if (x_hot) *x_hot = hx; | |
365 if (y_hot) *y_hot = hy; | |
366 | |
367 RETURN (BitmapSuccess); | |
368 } | |
369 | |
370 | |
371 int XmuReadBitmapDataFromFile (CONST char *filename, | |
372 /* Remaining args are RETURNED */ | |
373 unsigned int *width, | |
374 unsigned int *height, | |
375 unsigned char **datap, | |
376 int *x_hot, int *y_hot) | |
377 { | |
378 FILE *fstream; | |
379 int status; | |
380 | |
381 if ((fstream = fopen (filename, "r")) == NULL) { | |
382 return BitmapOpenFailed; | |
383 } | |
384 status = XmuReadBitmapData (fstream, width, height, datap, x_hot, y_hot); | |
385 fclose (fstream); | |
386 return status; | |
387 } | |
388 | |
389 /* | |
390 * XmuPrintDefaultErrorMessage - print a nice error that looks like the usual | |
391 * message. Return 1 if the caller should consider exiting, else 0. | |
392 */ | |
393 int XmuPrintDefaultErrorMessage (Display *dpy, XErrorEvent *event, FILE *fp) | |
394 { | |
395 char buffer[BUFSIZ]; | |
396 char mesg[BUFSIZ]; | |
397 char number[32]; | |
398 char *mtype = "XlibMessage"; | |
399 _XExtension *ext = (_XExtension *)NULL; | |
400 XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); | |
401 XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); | |
402 fprintf(fp, "%s: %s\n ", mesg, buffer); | |
403 XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", | |
404 mesg, BUFSIZ); | |
405 fprintf(fp, mesg, event->request_code); | |
406 if (event->request_code < 128) { | |
407 sprintf(number, "%d", event->request_code); | |
408 XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); | |
409 } else { | |
410 /* XXX this is non-portable */ | |
411 for (ext = dpy->ext_procs; | |
412 ext && (ext->codes.major_opcode != event->request_code); | |
413 ext = ext->next) | |
414 ; | |
415 if (ext) | |
416 strcpy(buffer, ext->name); | |
417 else | |
418 buffer[0] = '\0'; | |
419 } | |
420 fprintf(fp, " (%s)", buffer); | |
421 fputs("\n ", fp); | |
422 #if (XtSpecificationRelease >= 5) | |
423 if (event->request_code >= 128) { | |
424 XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", | |
425 mesg, BUFSIZ); | |
426 fprintf(fp, mesg, event->minor_code); | |
427 if (ext) { | |
428 sprintf(mesg, "%s.%d", ext->name, event->minor_code); | |
429 XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); | |
430 fprintf(fp, " (%s)", buffer); | |
431 } | |
432 fputs("\n ", fp); | |
433 } | |
434 if (event->error_code >= 128) { | |
435 /* let extensions try to print the values */ | |
436 /* XXX this is non-portable code */ | |
437 for (ext = dpy->ext_procs; ext; ext = ext->next) { | |
438 if (ext->error_values) | |
439 (*ext->error_values)(dpy, event, fp); | |
440 } | |
441 /* the rest is a fallback, providing a simple default */ | |
442 /* kludge, try to find the extension that caused it */ | |
443 buffer[0] = '\0'; | |
444 for (ext = dpy->ext_procs; ext; ext = ext->next) { | |
445 if (ext->error_string) | |
446 (*ext->error_string)(dpy, event->error_code, &ext->codes, | |
447 buffer, BUFSIZ); | |
448 if (buffer[0]) | |
449 break; | |
450 } | |
451 if (buffer[0]) | |
452 sprintf(buffer, "%s.%d", ext->name, | |
453 event->error_code - ext->codes.first_error); | |
454 else | |
455 strcpy(buffer, "Value"); | |
456 XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); | |
457 if (*mesg) { | |
458 fprintf(fp, mesg, event->resourceid); | |
459 fputs("\n ", fp); | |
460 } | |
461 } else if ((event->error_code == BadWindow) || | |
462 (event->error_code == BadPixmap) || | |
463 (event->error_code == BadCursor) || | |
464 (event->error_code == BadFont) || | |
465 (event->error_code == BadDrawable) || | |
466 (event->error_code == BadColor) || | |
467 (event->error_code == BadGC) || | |
468 (event->error_code == BadIDChoice) || | |
469 (event->error_code == BadValue) || | |
470 (event->error_code == BadAtom)) { | |
471 if (event->error_code == BadValue) | |
472 XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", | |
473 mesg, BUFSIZ); | |
474 else if (event->error_code == BadAtom) | |
475 XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", | |
476 mesg, BUFSIZ); | |
477 else | |
478 XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", | |
479 mesg, BUFSIZ); | |
480 fprintf(fp, mesg, event->resourceid); | |
481 fputs("\n ", fp); | |
482 } | |
483 #elif (XtSpecificationRelease == 4) | |
484 XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", | |
485 mesg, BUFSIZ); | |
486 fprintf(fp, mesg, event->minor_code); | |
487 fputs("\n ", fp); | |
488 if (ext) { | |
489 sprintf(mesg, "%s.%d", ext->name, event->minor_code); | |
490 XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); | |
491 fprintf(fp, " (%s)", buffer); | |
492 } | |
493 XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", | |
494 mesg, BUFSIZ); | |
495 fprintf(fp, mesg, event->resourceid); | |
496 fputs("\n ", fp); | |
497 #else | |
498 ERROR! Unsupported release of X11 | |
499 #endif | |
500 XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", | |
501 mesg, BUFSIZ); | |
502 fprintf(fp, mesg, event->serial); | |
503 fputs("\n ", fp); | |
504 XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", | |
505 mesg, BUFSIZ); | |
506 fprintf(fp, mesg, NextRequest(dpy)-1); | |
507 fputs("\n", fp); | |
508 if (event->error_code == BadImplementation) return 0; | |
509 return 1; | |
510 } | |
511 | |
512 | |
513 /* | |
514 * XmuSimpleErrorHandler - ignore errors for XQueryTree, XGetWindowAttributes, | |
515 * and XGetGeometry; print a message for everything else. In all case, do | |
516 * not exit. | |
517 */ | |
518 int XmuSimpleErrorHandler (Display *dpy, XErrorEvent *errorp) | |
519 { | |
520 switch (errorp->request_code) { | |
521 case X_QueryTree: | |
522 case X_GetWindowAttributes: | |
523 if (errorp->error_code == BadWindow) return 0; | |
524 break; | |
525 case X_GetGeometry: | |
526 if (errorp->error_code == BadDrawable) return 0; | |
527 break; | |
528 } | |
529 /* got a "real" X error */ | |
530 return XmuPrintDefaultErrorMessage (dpy, errorp, stderr); | |
531 } | |
532 | |
533 void XmuCopyISOLatin1Lowered(char *dst, CONST char *src) | |
534 { | |
535 unsigned char *dest = (unsigned char *) dst; | |
536 unsigned char *source = (unsigned char *) src; | |
537 | |
538 for ( ; *source; source++, dest++) | |
539 { | |
540 if ((*source >= XK_A) && (*source <= XK_Z)) | |
541 *dest = *source + (XK_a - XK_A); | |
542 else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis)) | |
543 *dest = *source + (XK_agrave - XK_Agrave); | |
544 else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn)) | |
545 *dest = *source + (XK_oslash - XK_Ooblique); | |
546 else | |
547 *dest = *source; | |
548 } | |
549 *dest = '\0'; | |
550 } | |
551 #endif /* !HAVE_XMU */ |