… | |
… | |
33 | You must define either the 'ATHENA' or 'MOTIF' symbol when compiling. |
33 | You must define either the 'ATHENA' or 'MOTIF' symbol when compiling. |
34 | #endif |
34 | #endif |
35 | |
35 | |
36 | #include <ctype.h> |
36 | #include <ctype.h> |
37 | #include <stdio.h> |
37 | #include <stdio.h> |
38 | #include <string.h> /* for strcmp() */ |
38 | #include <string.h> /* for strcmp() */ |
39 | #ifdef __STDC__ |
39 | #include <stdarg.h> |
40 | #include <stdlib.h> /* for exit()... */ |
40 | #include <stdlib.h> /* for exit()... */ |
41 | #endif |
|
|
42 | #ifndef VMS |
|
|
43 | #include <unistd.h> /* for read(), write() */ |
41 | #include <unistd.h> /* for read(), write() */ |
44 | #endif |
|
|
45 | #include <X11/Xatom.h> /* for pre-defined atom names */ |
42 | #include <X11/Xatom.h> /* for pre-defined atom names */ |
46 | #include <X11/StringDefs.h> /* for XtNforeground et.al. */ |
43 | #include <X11/StringDefs.h> /* for XtNforeground et.al. */ |
47 | #include <X11/Intrinsic.h> |
44 | #include <X11/Intrinsic.h> |
|
|
45 | #include <locale.h> |
48 | |
46 | |
49 | #ifdef ATHENA |
47 | #ifdef ATHENA |
50 | #ifndef VMS |
48 | #ifndef VMS |
51 | #include <X11/Xaw/Form.h> |
49 | #include <X11/Xaw/Form.h> |
52 | #else |
50 | #else |
… | |
… | |
60 | #endif |
58 | #endif |
61 | |
59 | |
62 | #include "cb.h" |
60 | #include "cb.h" |
63 | #include "patchlevel.h" |
61 | #include "patchlevel.h" |
64 | |
62 | |
65 | #define eq(a,b) (strcmp((a),(b)) == 0) |
63 | #define eq(a,b) (strcmp((a),(b)) == 0) |
66 | #define max(a,b) ((a) > (b)? (a): (b)) |
64 | #define max(a,b) ((a) > (b)? (a): (b)) |
67 | |
65 | |
68 | #define XtNbufferCount "bufferCount" /* Application resources */ |
66 | #define XtNbufferCount "bufferCount" /* Application resources */ |
69 | #define XtCBufferCount "BufferCount" |
67 | #define XtCBufferCount "BufferCount" |
70 | #define XtNlayout "layout" |
68 | #define XtNlayout "layout" |
71 | #define XtCLayout "Layout" |
69 | #define XtCLayout "Layout" |
72 | |
70 | |
73 | #define PGM_NAME "xcb" |
71 | #define PGM_NAME "xcb" |
74 | #define PGM_CLASS "Xcb" |
72 | #define PGM_CLASS "Xcb" |
75 | #define BUFINC 2048 |
73 | #define BUFINC 2048 |
76 | |
74 | |
77 | static Display *dpy; |
75 | static Display *dpy; |
78 | static Window root; |
76 | static Window root; |
79 | static XtAppContext app; |
77 | static XtAppContext app; |
80 | static Widget top, box, *wdg; |
78 | static Widget top, box, *wdg; |
… | |
… | |
83 | static Atom *atom; |
81 | static Atom *atom; |
84 | static int natoms, nbuffs; |
82 | static int natoms, nbuffs; |
85 | static Window seln; |
83 | static Window seln; |
86 | static int use_utf8 = 0; |
84 | static int use_utf8 = 0; |
87 | |
85 | |
88 | static Atom convert_to; /* convert selection to this cut buffer */ |
86 | static Atom convert_to; /* convert selection to this cut buffer */ |
89 | |
|
|
90 | #ifdef XVIEW |
|
|
91 | static Atom caret, clipboard, yield; |
|
|
92 | static Atom length, lengthc; |
|
|
93 | #endif |
|
|
94 | |
87 | |
95 | #ifndef X_HAVE_UTF8_STRING |
88 | #ifndef X_HAVE_UTF8_STRING |
96 | #define Xutf8TextPropertyToTextList XmbTextPropertyToTextList |
89 | #define Xutf8TextPropertyToTextList XmbTextPropertyToTextList |
97 | #define Xutf8TextListToTextProperty XmbTextListToTextProperty |
90 | #define Xutf8TextListToTextProperty XmbTextListToTextProperty |
98 | #endif |
91 | #endif |
|
|
92 | |
|
|
93 | #define FONT_ELEMENT_SIZE 50 |
|
|
94 | |
|
|
95 | static const char * |
|
|
96 | i_strstr (const char *str, const char *ptn) |
|
|
97 | { |
|
|
98 | const char *s2, *p2; |
|
|
99 | for (; *str; str++) |
|
|
100 | { |
|
|
101 | for (s2 = str, p2 = ptn;; s2++, p2++) |
|
|
102 | { |
|
|
103 | if (!*p2) |
|
|
104 | return str; |
|
|
105 | if (toupper (*s2) != toupper (*p2)) |
|
|
106 | break; |
|
|
107 | } |
|
|
108 | } |
|
|
109 | return NULL; |
|
|
110 | } |
|
|
111 | |
|
|
112 | static const char * |
|
|
113 | Font_GetElement (const char *pattern, char *buf, int bufsiz, ...) |
|
|
114 | { |
|
|
115 | const char *p, *v; |
|
|
116 | char *p2; |
|
|
117 | va_list va; |
|
|
118 | |
|
|
119 | va_start (va, bufsiz); |
|
|
120 | buf[bufsiz - 1] = 0; |
|
|
121 | buf[bufsiz - 2] = '*'; |
|
|
122 | while ((v = va_arg (va, char *)) != NULL) |
|
|
123 | { |
|
|
124 | p = i_strstr (pattern, v); |
|
|
125 | if (p) |
|
|
126 | { |
|
|
127 | strncpy (buf, p + 1, bufsiz - 2); |
|
|
128 | p2 = strchr (buf, '-'); |
|
|
129 | if (p2) |
|
|
130 | *p2 = 0; |
|
|
131 | va_end (va); |
|
|
132 | return p; |
|
|
133 | } |
|
|
134 | } |
|
|
135 | va_end (va); |
|
|
136 | strncpy (buf, "*", bufsiz); |
|
|
137 | return NULL; |
|
|
138 | } |
|
|
139 | |
|
|
140 | static const char * |
|
|
141 | Font_GetSize (const char *pattern, int *size) |
|
|
142 | { |
|
|
143 | const char *p; |
|
|
144 | const char *p2 = NULL; |
|
|
145 | int n = 0; |
|
|
146 | |
|
|
147 | for (p = pattern; 1; p++) |
|
|
148 | { |
|
|
149 | if (!*p) |
|
|
150 | { |
|
|
151 | if (p2 != NULL && n > 1 && n < 72) |
|
|
152 | { |
|
|
153 | *size = n; |
|
|
154 | return p2 + 1; |
|
|
155 | } |
|
|
156 | else |
|
|
157 | { |
|
|
158 | *size = 16; |
|
|
159 | return NULL; |
|
|
160 | } |
|
|
161 | } |
|
|
162 | else if (*p == '-') |
|
|
163 | { |
|
|
164 | if (n > 1 && n < 72 && p2 != NULL) |
|
|
165 | { |
|
|
166 | *size = n; |
|
|
167 | return p2 + 1; |
|
|
168 | } |
|
|
169 | p2 = p; |
|
|
170 | n = 0; |
|
|
171 | } |
|
|
172 | else if (*p >= '0' && *p <= '9' && p2 != NULL) |
|
|
173 | { |
|
|
174 | n *= 10; |
|
|
175 | n += *p - '0'; |
|
|
176 | } |
|
|
177 | else |
|
|
178 | { |
|
|
179 | p2 = NULL; |
|
|
180 | n = 0; |
|
|
181 | } |
|
|
182 | } |
|
|
183 | } |
|
|
184 | |
|
|
185 | /* from http://www.debian.org/doc/manuals/intro-i18n/ */ |
|
|
186 | static XFontSet |
|
|
187 | XCreateFontSetWithGuess (Display * d, const char *pattern, char ***miss, int *n_miss, char **def) |
|
|
188 | { |
|
|
189 | XFontSet fs; |
|
|
190 | char *pattern2; |
|
|
191 | int pixel_size, bufsiz; |
|
|
192 | char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE]; |
|
|
193 | |
|
|
194 | /* No problem? or 'fs' for pattern analysis */ |
|
|
195 | fs = XCreateFontSet (d, pattern, miss, n_miss, def); |
|
|
196 | if (fs && !*n_miss) |
|
|
197 | return fs; /* no need for font guessing */ |
|
|
198 | |
|
|
199 | /* for non-iso8859-1 language and iso8859-1 specification */ |
|
|
200 | /* This 'fs' is only for pattern analysis. */ |
|
|
201 | if (!fs) |
|
|
202 | { |
|
|
203 | if (*n_miss) |
|
|
204 | XFreeStringList (*miss); |
|
|
205 | |
|
|
206 | setlocale (LC_CTYPE, "C"); |
|
|
207 | fs = XCreateFontSet (d, pattern, miss, n_miss, def); |
|
|
208 | setlocale (LC_CTYPE, ""); |
|
|
209 | } |
|
|
210 | |
|
|
211 | /* make XLFD font name for pattern analysis */ |
|
|
212 | if (fs) |
|
|
213 | { |
|
|
214 | XFontStruct **fontstructs; |
|
|
215 | char **fontnames; |
|
|
216 | XFontsOfFontSet (fs, &fontstructs, &fontnames); |
|
|
217 | pattern = fontnames[0]; |
|
|
218 | } |
|
|
219 | |
|
|
220 | /* read elements of font name */ |
|
|
221 | Font_GetElement (pattern, weight, FONT_ELEMENT_SIZE, |
|
|
222 | "-medium-", "-bold-", "-demibold-", "-regular-", NULL); |
|
|
223 | Font_GetElement (pattern, slant, FONT_ELEMENT_SIZE, |
|
|
224 | "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL); |
|
|
225 | Font_GetSize (pattern, &pixel_size); |
|
|
226 | |
|
|
227 | /* modify elements of font name to fit usual font names */ |
|
|
228 | if (!strcmp (weight, "*")) |
|
|
229 | strncpy (weight, "medium", FONT_ELEMENT_SIZE); |
|
|
230 | if (!strcmp (slant, "*")) |
|
|
231 | strncpy (slant, "r", FONT_ELEMENT_SIZE); |
|
|
232 | if (pixel_size < 3) |
|
|
233 | pixel_size = 3; |
|
|
234 | else if (pixel_size > 97) |
|
|
235 | pixel_size = 97; |
|
|
236 | |
|
|
237 | /* build font pattern for better matching for various charsets */ |
|
|
238 | bufsiz = strlen (pattern) + FONT_ELEMENT_SIZE * 2 + 2 * 2 + 58; |
|
|
239 | pattern2 = (char *) malloc (bufsiz); |
|
|
240 | if (pattern2) |
|
|
241 | { |
|
|
242 | snprintf (pattern2, bufsiz - 1, "%s," |
|
|
243 | "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*," |
|
|
244 | "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*", |
|
|
245 | pattern, |
|
|
246 | weight, slant, pixel_size, |
|
|
247 | pixel_size); |
|
|
248 | pattern = pattern2; |
|
|
249 | } |
|
|
250 | if (*n_miss) |
|
|
251 | XFreeStringList (*miss); |
|
|
252 | if (fs) |
|
|
253 | XFreeFontSet (d, fs); |
|
|
254 | |
|
|
255 | /* create fontset */ |
|
|
256 | fs = XCreateFontSet (d, pattern, miss, n_miss, def); |
|
|
257 | if (pattern2) |
|
|
258 | free (pattern2); |
|
|
259 | |
|
|
260 | return fs; |
|
|
261 | } |
|
|
262 | |
|
|
263 | static |
|
|
264 | Boolean |
|
|
265 | CvtStringToFontSet (dpy, args, num_args, fromVal, toVal, closure_ret) |
|
|
266 | Display *dpy; |
|
|
267 | XrmValuePtr args; |
|
|
268 | Cardinal *num_args; |
|
|
269 | XrmValuePtr fromVal; |
|
|
270 | XrmValuePtr toVal; |
|
|
271 | XtPointer *closure_ret; |
|
|
272 | { |
|
|
273 | XFontSet f; |
|
|
274 | char **missing_charset_list; |
|
|
275 | int missing_charset_count; |
|
|
276 | char *def_string; |
|
|
277 | |
|
|
278 | f = XCreateFontSetWithGuess (dpy, (char *) fromVal->addr, |
|
|
279 | &missing_charset_list, &missing_charset_count, &def_string); |
|
|
280 | /* Free any returned missing charset list */ |
|
|
281 | if (missing_charset_count) |
|
|
282 | { |
|
|
283 | fprintf (stderr, "Missing charsets in String to FontSet conversion (%s)\n", missing_charset_list[0]); |
|
|
284 | XFreeStringList (missing_charset_list); |
|
|
285 | } |
|
|
286 | |
|
|
287 | if (!f) |
|
|
288 | { |
|
|
289 | f = XCreateFontSetWithGuess (dpy, "-*-*-*-R-*-*-*-120-*-*-*-*", |
|
|
290 | &missing_charset_list, &missing_charset_count, &def_string); |
|
|
291 | } |
|
|
292 | |
|
|
293 | *(XFontSet *) (toVal->addr) = f; |
|
|
294 | |
|
|
295 | return f ? True : False; |
|
|
296 | } |
99 | |
297 | |
100 | /* |
298 | /* |
101 | * Fetch the contents of cut buffer n from the root window. |
299 | * Fetch the contents of cut buffer n from the root window. |
102 | */ |
300 | */ |
103 | static char * |
301 | static char * |
… | |
… | |
112 | int count; |
310 | int count; |
113 | XTextProperty pt; |
311 | XTextProperty pt; |
114 | |
312 | |
115 | *nb = 0; |
313 | *nb = 0; |
116 | if (XGetWindowProperty (dpy, root, a, |
314 | if (XGetWindowProperty (dpy, root, a, |
117 | 0L, 10000000L, False, AnyPropertyType, |
315 | 0L, 10000000L, False, AnyPropertyType, |
118 | &pt.encoding, &pt.format, &pt.nitems, |
316 | &pt.encoding, &pt.format, &pt.nitems, |
119 | &after, &pt.value) != Success || !pt.nitems) |
317 | &after, &pt.value) != Success || !pt.nitems) |
120 | return strdup (""); |
318 | return strdup (""); |
121 | |
319 | |
122 | if (pt.nitems) |
320 | if (pt.nitems) |
123 | { |
321 | { |
124 | (force_mb ? XmbTextPropertyToTextList : Xutf8TextPropertyToTextList) |
322 | (force_mb ? XmbTextPropertyToTextList : Xutf8TextPropertyToTextList) |
125 | (dpy, &pt, &list, &count); |
323 | (dpy, &pt, &list, &count); |
126 | |
324 | |
127 | data = strdup (list[0]); |
325 | data = strdup (list[0]); |
128 | *nb = strlen (data); |
326 | *nb = strlen (data); |
129 | |
327 | |
130 | XFreeStringList (list); |
328 | XFreeStringList (list); |
… | |
… | |
150 | |
348 | |
151 | (force_mb ? XmbTextListToTextProperty : Xutf8TextListToTextProperty) |
349 | (force_mb ? XmbTextListToTextProperty : Xutf8TextListToTextProperty) |
152 | (dpy, &p, 1, XStdICCTextStyle, &pt); |
350 | (dpy, &p, 1, XStdICCTextStyle, &pt); |
153 | |
351 | |
154 | XChangeProperty (dpy, root, atom, pt.encoding, |
352 | XChangeProperty (dpy, root, atom, pt.encoding, |
155 | 8, PropModeReplace, pt.value, pt.nitems); |
353 | 8, PropModeReplace, pt.value, pt.nitems); |
156 | |
354 | |
157 | XFree (pt.value); |
355 | XFree (pt.value); |
158 | } |
356 | } |
159 | |
357 | |
160 | /* |
358 | /* |
… | |
… | |
168 | |
366 | |
169 | if (n >= natoms) |
367 | if (n >= natoms) |
170 | { |
368 | { |
171 | atom = (Atom *) XtRealloc ((char *) atom, (n + 1) * sizeof (Atom)); |
369 | atom = (Atom *) XtRealloc ((char *) atom, (n + 1) * sizeof (Atom)); |
172 | while (natoms < n + 1) |
370 | while (natoms < n + 1) |
173 | atom[natoms++] = 0; |
371 | atom[natoms++] = 0; |
174 | } |
372 | } |
175 | |
373 | |
176 | if (!atom[n]) |
374 | if (!atom[n]) |
177 | { |
375 | { |
178 | sprintf (tmp, "CUT_BUFFER%d", n); |
376 | sprintf (tmp, "CUT_BUFFER%d", n); |
… | |
… | |
219 | /* we rely on clipping... */ |
417 | /* we rely on clipping... */ |
220 | /*cols = ((int) cb->core.width + cb->font_width - 1) |
418 | /*cols = ((int) cb->core.width + cb->font_width - 1) |
221 | / cb->font_width; */ |
419 | / cb->font_width; */ |
222 | /*len = min(len, cols); */ |
420 | /*len = min(len, cols); */ |
223 | if (len > 0) |
421 | if (len > 0) |
224 | { |
422 | { |
225 | y -= cb->font_ascent; |
423 | y -= cb->font_ascent; |
226 | #if X_HAVE_UTF8_STRING |
424 | #if X_HAVE_UTF8_STRING |
227 | Xutf8DrawImageString |
425 | Xutf8DrawImageString |
228 | #else |
426 | #else |
229 | XmbDrawImageString |
427 | XmbDrawImageString |
230 | #endif |
428 | #endif |
231 | (dpy, cb->core.window, cb->fontset, gc, 0, y, str, len); |
429 | (dpy, cb->core.window, cb->fontset, gc, 0, y, str, len); |
232 | } |
430 | } |
233 | } |
431 | } |
234 | } |
432 | } |
235 | |
433 | |
236 | /* |
434 | /* |
237 | * ============================================================================ |
435 | * ============================================================================ |
… | |
… | |
239 | * the cb widget. Each cb widget displays a single cut buffer value |
437 | * the cb widget. Each cb widget displays a single cut buffer value |
240 | * in a window, and provides cut and paste access to that buffer. |
438 | * in a window, and provides cut and paste access to that buffer. |
241 | */ |
439 | */ |
242 | |
440 | |
243 | static void |
441 | static void |
244 | cb_initialize (req, wdg, args, nargs) /*ARGSUSED */ |
442 | cb_initialize (req, wdg, args, nargs) /*ARGSUSED */ |
245 | Widget req, wdg; |
443 | Widget req, wdg; |
246 | ArgList args; |
444 | ArgList args; |
247 | Cardinal *nargs; |
445 | Cardinal *nargs; |
248 | { |
446 | { |
249 | CbWidget cb = (CbWidget) wdg; |
447 | CbWidget cb = (CbWidget) wdg; |
… | |
… | |
287 | * Lines which extend beyond the subwindow's borders are clipped; no |
485 | * Lines which extend beyond the subwindow's borders are clipped; no |
288 | * wrap-around processing is done. |
486 | * wrap-around processing is done. |
289 | * Keep it simple. |
487 | * Keep it simple. |
290 | */ |
488 | */ |
291 | static void |
489 | static void |
292 | cb_redisplay (wdg, event, region) /*ARGSUSED */ |
490 | cb_redisplay (wdg, event, region) /*ARGSUSED */ |
293 | Widget wdg; |
491 | Widget wdg; |
294 | XEvent *event; |
492 | XEvent *event; |
295 | Region region; |
493 | Region region; |
296 | { |
494 | { |
297 | CbWidget cb = (CbWidget) wdg; |
495 | CbWidget cb = (CbWidget) wdg; |
… | |
… | |
301 | y = 0; |
499 | y = 0; |
302 | p = pp = base = fetch_buffer (cb->atom, &nbytes, 0); |
500 | p = pp = base = fetch_buffer (cb->atom, &nbytes, 0); |
303 | while (pp < base + nbytes) |
501 | while (pp < base + nbytes) |
304 | { |
502 | { |
305 | if (*pp == '\n') |
503 | if (*pp == '\n') |
306 | { |
504 | { |
307 | place_text (cb, p, pp - p, y); |
505 | place_text (cb, p, pp - p, y); |
308 | p = pp + 1; |
506 | p = pp + 1; |
309 | y += cb->font_height; |
507 | y += cb->font_height; |
310 | } |
508 | } |
311 | pp++; |
509 | pp++; |
312 | } |
510 | } |
313 | place_text (cb, p, pp - p, y); |
511 | place_text (cb, p, pp - p, y); |
314 | XFree (base); |
512 | XFree (base); |
315 | } |
513 | } |
… | |
… | |
340 | * which means it must know when another xcb widget has selection |
538 | * which means it must know when another xcb widget has selection |
341 | * ownership, which brings about the need for the 'seln' global variable. |
539 | * ownership, which brings about the need for the 'seln' global variable. |
342 | * This breaks all the rules for object oriented widgets. Disgusting, no? |
540 | * This breaks all the rules for object oriented widgets. Disgusting, no? |
343 | */ |
541 | */ |
344 | static void |
542 | static void |
345 | cb_cut (wdg, event, parms, nparms) /*ARGSUSED */ |
543 | cb_cut (wdg, event, parms, nparms) /*ARGSUSED */ |
346 | Widget wdg; |
544 | Widget wdg; |
347 | XEvent *event; |
545 | XEvent *event; |
348 | String *parms; |
546 | String *parms; |
349 | Cardinal *nparms; |
547 | Cardinal *nparms; |
350 | { |
548 | { |
… | |
… | |
368 | if (w == win) |
566 | if (w == win) |
369 | { |
567 | { |
370 | seln = win; |
568 | seln = win; |
371 | XClearArea (dpy, win, 0, 0, 0, 0, False); |
569 | XClearArea (dpy, win, 0, 0, 0, 0, False); |
372 | cb_redisplay (wdg, (XEvent *) 0, (Region) 0); |
570 | cb_redisplay (wdg, (XEvent *) 0, (Region) 0); |
373 | #ifdef XVIEW |
|
|
374 | XSetSelectionOwner (dpy, caret, win, event->xbutton.time); |
|
|
375 | XSetSelectionOwner (dpy, clipboard, win, event->xbutton.time); |
|
|
376 | #endif |
|
|
377 | } |
571 | } |
378 | } |
572 | } |
379 | |
573 | |
380 | static void |
574 | static void |
381 | cb_paste (wdg, event, parms, nparms) /*ARGSUSED */ |
575 | cb_paste (wdg, event, parms, nparms) /*ARGSUSED */ |
382 | Widget wdg; |
576 | Widget wdg; |
383 | XEvent *event; |
577 | XEvent *event; |
384 | String *parms; |
578 | String *parms; |
385 | Cardinal *nparms; |
579 | Cardinal *nparms; |
386 | { |
580 | { |
… | |
… | |
390 | int n; |
584 | int n; |
391 | |
585 | |
392 | w = XGetSelectionOwner (dpy, XA_PRIMARY); |
586 | w = XGetSelectionOwner (dpy, XA_PRIMARY); |
393 | if (w == None) |
587 | if (w == None) |
394 | { |
588 | { |
395 | ptr = fetch_buffer (atom[0], &n, 0); /* copy from cb0 */ |
589 | ptr = fetch_buffer (atom[0], &n, 0); /* copy from cb0 */ |
396 | store_buffer (ptr, n, cb->atom, 0); |
590 | store_buffer (ptr, n, cb->atom, 0); |
397 | XFree (ptr); |
591 | XFree (ptr); |
398 | } |
592 | } |
399 | else if (w != cb->core.window) |
593 | else if (w != cb->core.window) |
400 | XConvertSelection (dpy, XA_PRIMARY, xa_utf8_string, |
594 | XConvertSelection (dpy, XA_PRIMARY, xa_utf8_string, |
401 | convert_to = cb->atom, XtWindow(wdg), event->xbutton.time); |
595 | convert_to = cb->atom, XtWindow (wdg), event->xbutton.time); |
402 | } |
596 | } |
403 | |
597 | |
404 | static void |
598 | static void |
405 | cb_clear (wdg, event, parms, nparms) /*ARGSUSED */ |
599 | cb_clear (wdg, event, parms, nparms) /*ARGSUSED */ |
406 | Widget wdg; |
600 | Widget wdg; |
407 | XEvent *event; |
601 | XEvent *event; |
408 | String *parms; |
602 | String *parms; |
409 | Cardinal *nparms; |
603 | Cardinal *nparms; |
410 | { |
604 | { |
… | |
… | |
418 | XSetSelectionOwner (dpy, XA_PRIMARY, None, event->xbutton.time); |
612 | XSetSelectionOwner (dpy, XA_PRIMARY, None, event->xbutton.time); |
419 | } |
613 | } |
420 | } |
614 | } |
421 | |
615 | |
422 | static void |
616 | static void |
423 | cb_rotate (wdg, event, parms, nparms) /*ARGSUSED */ |
617 | cb_rotate (wdg, event, parms, nparms) /*ARGSUSED */ |
424 | Widget wdg; |
618 | Widget wdg; |
425 | XEvent *event; |
619 | XEvent *event; |
426 | String *parms; |
620 | String *parms; |
427 | Cardinal *nparms; |
621 | Cardinal *nparms; |
428 | { |
622 | { |
… | |
… | |
434 | if (n != 0) |
628 | if (n != 0) |
435 | XRotateWindowProperties (dpy, root, atom, nbuffs, n); |
629 | XRotateWindowProperties (dpy, root, atom, nbuffs, n); |
436 | } |
630 | } |
437 | |
631 | |
438 | static void |
632 | static void |
439 | cb_quit (wdg, event, parms, nparms) /*ARGSUSED */ |
633 | cb_quit (wdg, event, parms, nparms) /*ARGSUSED */ |
440 | Widget wdg; |
634 | Widget wdg; |
441 | XEvent *event; |
635 | XEvent *event; |
442 | String *parms; |
636 | String *parms; |
443 | Cardinal *nparms; |
637 | Cardinal *nparms; |
444 | { |
638 | { |
… | |
… | |
447 | |
641 | |
448 | /* |
642 | /* |
449 | * Clear and redraw the widget's window. |
643 | * Clear and redraw the widget's window. |
450 | */ |
644 | */ |
451 | static void |
645 | static void |
452 | cb_refresh (wdg, event, parms, nparms) /*ARGSUSED */ |
646 | cb_refresh (wdg, event, parms, nparms) /*ARGSUSED */ |
453 | Widget wdg; |
647 | Widget wdg; |
454 | XEvent *event; |
648 | XEvent *event; |
455 | String *parms; |
649 | String *parms; |
456 | Cardinal *nparms; |
650 | Cardinal *nparms; |
457 | { |
651 | { |
… | |
… | |
465 | * (No conversion facilities are provided by this program). |
659 | * (No conversion facilities are provided by this program). |
466 | * The selection request is met by copying the current contents |
660 | * The selection request is met by copying the current contents |
467 | * of the cut buffer to the target window+atom. |
661 | * of the cut buffer to the target window+atom. |
468 | */ |
662 | */ |
469 | static void |
663 | static void |
470 | cb_selreq (wdg, event, parms, nparms) /*ARGSUSED */ |
664 | cb_selreq (wdg, event, parms, nparms) /*ARGSUSED */ |
471 | Widget wdg; |
665 | Widget wdg; |
472 | XEvent *event; |
666 | XEvent *event; |
473 | String *parms; |
667 | String *parms; |
474 | Cardinal *nparms; |
668 | Cardinal *nparms; |
475 | { |
669 | { |
… | |
… | |
477 | char *ptr; |
671 | char *ptr; |
478 | XSelectionEvent notify; |
672 | XSelectionEvent notify; |
479 | XSelectionRequestEvent *rq; |
673 | XSelectionRequestEvent *rq; |
480 | CbWidget cb = (CbWidget) wdg; |
674 | CbWidget cb = (CbWidget) wdg; |
481 | Window win = cb->core.window; |
675 | Window win = cb->core.window; |
482 | |
|
|
483 | #ifdef XVIEW |
|
|
484 | unsigned long data; |
|
|
485 | #endif |
|
|
486 | |
676 | |
487 | rq = (XSelectionRequestEvent *) event; |
677 | rq = (XSelectionRequestEvent *) event; |
488 | |
678 | |
489 | notify.type = SelectionNotify; |
679 | notify.type = SelectionNotify; |
490 | notify.display = rq->display; |
680 | notify.display = rq->display; |
… | |
… | |
492 | notify.selection = rq->selection; |
682 | notify.selection = rq->selection; |
493 | notify.target = rq->target; |
683 | notify.target = rq->target; |
494 | notify.property = None; |
684 | notify.property = None; |
495 | notify.time = rq->time; |
685 | notify.time = rq->time; |
496 | |
686 | |
497 | #ifdef XVIEW |
687 | if (win == seln) |
498 | if (rq->selection == XA_PRIMARY) |
|
|
499 | { |
688 | { |
|
|
689 | XICCEncodingStyle style; |
|
|
690 | Atom target = None; |
|
|
691 | |
500 | if (rq->target == yield) |
692 | if (rq->target == XA_STRING) |
501 | { |
693 | { |
502 | /* tell 'em we'll give it up */ |
694 | target = XA_STRING; |
503 | data = 1; |
695 | style = XStringStyle; |
504 | XChangeProperty (dpy, rq->requestor, rq->property, |
696 | } |
505 | rq->target, 32, PropModeReplace, |
697 | else if (rq->target == xa_text) |
506 | (unsigned char *) &data, 1); |
698 | { |
507 | notify.property = rq->property; |
699 | target = xa_compound_text; |
508 | } |
700 | style = XStdICCTextStyle; |
509 | else |
701 | } |
510 | { |
702 | else if (rq->target == xa_compound_text) |
|
|
703 | { |
|
|
704 | target = xa_compound_text; |
|
|
705 | style = XCompoundTextStyle; |
|
|
706 | } |
|
|
707 | #ifdef X_HAVE_UTF8_STRING |
|
|
708 | else if (rq->target == xa_utf8_string) |
|
|
709 | { |
|
|
710 | target = xa_utf8_string; |
|
|
711 | style = XUTF8StringStyle; |
|
|
712 | } |
511 | #endif |
713 | #endif |
512 | |
714 | |
513 | if (win == seln) |
|
|
514 | { |
|
|
515 | XICCEncodingStyle style; |
|
|
516 | Atom target = None; |
|
|
517 | |
|
|
518 | if (rq->target == XA_STRING) |
|
|
519 | { |
|
|
520 | target = XA_STRING; |
|
|
521 | style = XStringStyle; |
|
|
522 | } |
|
|
523 | else if (rq->target == xa_text) |
|
|
524 | { |
|
|
525 | target = xa_compound_text; |
|
|
526 | style = XStdICCTextStyle; |
|
|
527 | } |
|
|
528 | else if (rq->target == xa_compound_text) |
|
|
529 | { |
|
|
530 | target = xa_compound_text; |
|
|
531 | style = XCompoundTextStyle; |
|
|
532 | } |
|
|
533 | #ifdef X_HAVE_UTF8_STRING |
|
|
534 | else if (rq->target == xa_utf8_string) |
|
|
535 | { |
|
|
536 | target = xa_utf8_string; |
|
|
537 | style = XUTF8StringStyle; |
|
|
538 | } |
|
|
539 | #endif |
|
|
540 | |
|
|
541 | if (target != None) |
715 | if (target != None) |
542 | { |
716 | { |
543 | XTextProperty pt; |
717 | XTextProperty pt; |
544 | char *fl; |
718 | char *fl; |
545 | |
719 | |
546 | fl = fetch_buffer (cb->atom, &nbytes, 0); |
720 | fl = fetch_buffer (cb->atom, &nbytes, 0); |
547 | Xutf8TextListToTextProperty (dpy, &fl, 1, style, &pt); |
721 | Xutf8TextListToTextProperty (dpy, &fl, 1, style, &pt); |
548 | XFree (fl); |
722 | XFree (fl); |
549 | |
723 | |
550 | XChangeProperty (dpy, rq->requestor, rq->property, |
|
|
551 | pt.encoding, 8, PropModeReplace, |
|
|
552 | pt.value, pt.nitems); |
|
|
553 | |
|
|
554 | notify.property = rq->property; |
|
|
555 | XFree (pt.value); |
|
|
556 | } |
|
|
557 | } |
|
|
558 | |
|
|
559 | #ifdef XVIEW |
|
|
560 | } |
|
|
561 | } |
|
|
562 | else if (rq->selection == caret) |
|
|
563 | { |
|
|
564 | if (rq->target == yield) |
|
|
565 | { |
|
|
566 | /* |
|
|
567 | * Give up the caret (which meant that we |
|
|
568 | * own the clipboard) |
|
|
569 | */ |
|
|
570 | XSetSelectionOwner (dpy, caret, None, |
|
|
571 | event->xselectionrequest.time); |
|
|
572 | data = 1; |
|
|
573 | XChangeProperty (dpy, rq->requestor, rq->property, |
724 | XChangeProperty (dpy, rq->requestor, rq->property, |
574 | rq->target, 32, PropModeReplace, |
725 | pt.encoding, 8, PropModeReplace, |
575 | (unsigned char *) &data, 1); |
726 | pt.value, pt.nitems); |
|
|
727 | |
576 | notify.property = rq->property; |
728 | notify.property = rq->property; |
577 | } |
729 | XFree (pt.value); |
578 | } |
730 | } |
579 | else if (rq->selection == clipboard && win == seln) |
|
|
580 | { |
731 | } |
581 | ptr = fetch_buffer (cb->atom, &nbytes, 0); |
|
|
582 | if (rq->target == lengthc || rq->target == length) |
|
|
583 | { |
|
|
584 | /* |
|
|
585 | * Send the length of the selection. |
|
|
586 | */ |
|
|
587 | data = nbytes; |
|
|
588 | XChangeProperty (dpy, rq->requestor, rq->property, |
|
|
589 | rq->target, 32, PropModeReplace, |
|
|
590 | (unsigned char *) &data, 1); |
|
|
591 | notify.property = rq->property; |
|
|
592 | } |
|
|
593 | else if (rq->target == XA_STRING || |
|
|
594 | rq->target == xa_text || rq->target == xa_compound_text) |
|
|
595 | { |
|
|
596 | /* |
|
|
597 | * Send the selection itself. |
|
|
598 | * All of our selections will be XA_STRING, |
|
|
599 | * but if they ask for COMPOUND_TEXT, it's ok |
|
|
600 | * to say that that's what we've got... |
|
|
601 | */ |
|
|
602 | XChangeProperty (dpy, rq->requestor, rq->property, |
|
|
603 | (rq->target == xa_compound_text ? xa_compound_text : XA_STRING), 8, |
|
|
604 | PropModeReplace, ptr, nbytes); |
|
|
605 | notify.property = rq->property; |
|
|
606 | } |
|
|
607 | XFree (ptr); |
|
|
608 | } |
|
|
609 | #endif |
|
|
610 | |
732 | |
611 | XSendEvent (dpy, rq->requestor, False, 0, (XEvent *) & notify); |
733 | XSendEvent (dpy, rq->requestor, False, 0, (XEvent *) & notify); |
612 | } |
734 | } |
613 | |
735 | |
614 | /* |
736 | /* |
615 | * Boo hiss, someone has taken the PRIMARY selection ownership |
737 | * Boo hiss, someone has taken the PRIMARY selection ownership |
616 | * away from this widget. The current window contents must |
738 | * away from this widget. The current window contents must |
617 | * be redrawn without highlighting. |
739 | * be redrawn without highlighting. |
618 | */ |
740 | */ |
619 | static void |
741 | static void |
620 | cb_selclear (wdg, event, parms, nparms) /*ARGSUSED */ |
742 | cb_selclear (wdg, event, parms, nparms) /*ARGSUSED */ |
621 | Widget wdg; |
743 | Widget wdg; |
622 | XEvent *event; |
744 | XEvent *event; |
623 | String *parms; |
745 | String *parms; |
624 | Cardinal *nparms; |
746 | Cardinal *nparms; |
625 | { |
747 | { |
626 | CbWidget cb = (CbWidget) wdg; |
748 | CbWidget cb = (CbWidget) wdg; |
627 | |
749 | |
628 | #ifdef XVIEW |
|
|
629 | Window w; |
|
|
630 | Time t; |
|
|
631 | #endif |
|
|
632 | |
|
|
633 | if (event->xproperty.atom != XA_PRIMARY) |
750 | if (event->xproperty.atom != XA_PRIMARY) |
634 | return; |
751 | return; |
635 | |
752 | |
636 | seln = 0; |
753 | seln = 0; |
637 | XClearArea (dpy, cb->core.window, 0, 0, 0, 0, False); |
754 | XClearArea (dpy, cb->core.window, 0, 0, 0, 0, False); |
638 | cb_redisplay (wdg, (XEvent *) 0, (Region) 0); |
755 | cb_redisplay (wdg, (XEvent *) 0, (Region) 0); |
639 | #ifdef XVIEW |
|
|
640 | /* |
|
|
641 | * Since we don't have ownership of PRIMARY anymore, |
|
|
642 | * we'd better get rid of CLIPBOARD and _SUN_SELN_CARET, |
|
|
643 | * if they're still ours. |
|
|
644 | */ |
|
|
645 | t = event->xselectionclear.time; |
|
|
646 | w = XGetSelectionOwner (dpy, caret); |
|
|
647 | if (w == cb->core.window) |
|
|
648 | XSetSelectionOwner (dpy, caret, None, t); |
|
|
649 | w = XGetSelectionOwner (dpy, clipboard); |
|
|
650 | if (w == cb->core.window) |
|
|
651 | XSetSelectionOwner (dpy, clipboard, None, t); |
|
|
652 | #endif |
|
|
653 | } |
756 | } |
654 | |
757 | |
655 | static XtResource resources[] = |
758 | static XtResource resources[] = |
656 | { |
759 | { |
657 | #define offset(field) XtOffset(CbWidget, field) |
760 | #define offset(field) XtOffset(CbWidget, field) |
658 | /* {name, class, type, size, offset, default_type, default_addr}, */ |
761 | /* {name, class, type, size, offset, default_type, default_addr}, */ |
659 | {XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), |
762 | {XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), |
660 | offset (fgnd), XtRString, (XtPointer) "XtDefaultForeground"}, |
763 | offset (fgnd), XtRString, (XtPointer) "XtDefaultForeground"}, |
661 | {XtNfontSet, XtCFontSet, XtRFontSet, sizeof (XFontSet), |
764 | {XtNfontSet, XtCFontSet, XtRFontSet, sizeof (XFontSet), |
662 | offset (fontset), XtRString, (XtPointer) "XtDefaultFontSet"}, |
765 | offset (fontset), XtRString, (XtPointer) "XtDefaultFontSet"}, |
663 | {XtNatom, XtCAtom, XtRAtom, sizeof (Atom), /* internal use */ |
766 | {XtNatom, XtCAtom, XtRAtom, sizeof (Atom), /* internal use */ |
664 | offset (atom), XtRImmediate, (XtPointer) 0}, |
767 | offset (atom), XtRImmediate, (XtPointer) 0}, |
665 | #undef offset |
768 | #undef offset |
666 | }; |
769 | }; |
667 | |
770 | |
668 | static XtActionsRec actions[] = |
771 | static XtActionsRec actions[] = |
… | |
… | |
676 | {"selreq", cb_selreq}, |
779 | {"selreq", cb_selreq}, |
677 | {"selclear", cb_selclear}, |
780 | {"selclear", cb_selclear}, |
678 | }; |
781 | }; |
679 | |
782 | |
680 | static char cb_transl[] = "\ |
783 | static char cb_transl[] = "\ |
681 | <Btn1Down>: cut() \n\ |
784 | <Btn1Down>: cut() \n\ |
682 | Shift <Btn2Down>: clear() \n\ |
785 | Shift <Btn2Down>: clear() \n\ |
683 | <Btn2Down>: paste() \n\ |
786 | <Btn2Down>: paste() \n\ |
684 | Shift <Btn3Down>: rotate(-1) \n\ |
787 | Shift <Btn3Down>: rotate(-1) \n\ |
685 | <Btn3Down>: rotate(1) \n\ |
788 | <Btn3Down>: rotate(1) \n\ |
686 | <Key>Left: rotate(-1) \n\ |
789 | <Key>Left: rotate(-1) \n\ |
687 | <Key>Right: rotate(1) \n\ |
790 | <Key>Right: rotate(1) \n\ |
688 | <Key>Up: rotate(-1) \n\ |
791 | <Key>Up: rotate(-1) \n\ |
689 | <Key>Down: rotate(1) \n\ |
792 | <Key>Down: rotate(1) \n\ |
690 | <Key>q: quit() \n\ |
793 | <Key>q: quit() \n\ |
691 | <SelReq>: selreq() \n\ |
794 | <SelReq>: selreq() \n\ |
692 | <SelClr>: selclear() \n\ |
795 | <SelClr>: selclear() \n\ |
693 | "; |
796 | "; |
694 | |
797 | |
695 | CbClassRec cbClassRec = |
798 | CbClassRec cbClassRec = |
696 | { |
799 | { |
697 | { |
800 | { |
698 | (WidgetClass) & widgetClassRec, /* superclass */ |
801 | (WidgetClass) & widgetClassRec, /* superclass */ |
699 | "Buffer", /* class_name */ |
802 | "Buffer", /* class_name */ |
700 | sizeof (CbRec), /* widget_size */ |
803 | sizeof (CbRec), /* widget_size */ |
701 | NULL, /* class_initialize */ |
804 | NULL, /* class_initialize */ |
702 | NULL, /* class_part_initialize */ |
805 | NULL, /* class_part_initialize */ |
703 | FALSE, /* class_inited */ |
806 | FALSE, /* class_inited */ |
704 | cb_initialize, /* initialize */ |
807 | cb_initialize, /* initialize */ |
705 | NULL, /* initialize_hook */ |
808 | NULL, /* initialize_hook */ |
706 | cb_realize, /* realize */ |
809 | cb_realize, /* realize */ |
707 | actions, /* actions */ |
810 | actions, /* actions */ |
708 | XtNumber (actions), /* num_actions */ |
811 | XtNumber (actions), /* num_actions */ |
709 | resources, /* resources */ |
812 | resources, /* resources */ |
710 | XtNumber (resources), /* num_resources */ |
813 | XtNumber (resources), /* num_resources */ |
711 | NULLQUARK, /* xrm_class */ |
814 | NULLQUARK, /* xrm_class */ |
712 | TRUE, /* compress_motion */ |
815 | TRUE, /* compress_motion */ |
713 | TRUE, /* compress_exposure */ |
816 | TRUE, /* compress_exposure */ |
714 | TRUE, /* compress_enterleave */ |
817 | TRUE, /* compress_enterleave */ |
715 | FALSE, /* visible_interest */ |
818 | FALSE, /* visible_interest */ |
716 | cb_destroy, /* destroy */ |
819 | cb_destroy, /* destroy */ |
717 | NULL, /* resize */ |
820 | NULL, /* resize */ |
718 | cb_redisplay, /* expose */ |
821 | cb_redisplay, /* expose */ |
719 | NULL, /* set_values */ |
822 | NULL, /* set_values */ |
720 | NULL, /* set_values_hook */ |
823 | NULL, /* set_values_hook */ |
721 | XtInheritSetValuesAlmost, /* set_values_almost */ |
824 | XtInheritSetValuesAlmost, /* set_values_almost */ |
722 | NULL, /* get_values_hook */ |
825 | NULL, /* get_values_hook */ |
723 | NULL, /* accept_focus */ |
826 | NULL, /* accept_focus */ |
724 | XtVersion, /* version */ |
827 | XtVersion, /* version */ |
725 | NULL, /* callback_private */ |
828 | NULL, /* callback_private */ |
726 | cb_transl, /* tm_table */ |
829 | cb_transl, /* tm_table */ |
727 | XtInheritQueryGeometry, /* query_geometry */ |
830 | XtInheritQueryGeometry, /* query_geometry */ |
728 | XtInheritDisplayAccelerator, /* display_accelerator */ |
831 | XtInheritDisplayAccelerator, /* display_accelerator */ |
729 | NULL /* extension */ |
832 | NULL /* extension */ |
730 | }, |
833 | }, |
731 | }; |
834 | }; |
732 | |
835 | |
733 | WidgetClass cbWidgetClass = (WidgetClass) & cbClassRec; |
836 | WidgetClass cbWidgetClass = (WidgetClass) & cbClassRec; |
734 | |
837 | |
… | |
… | |
741 | |
844 | |
742 | static void |
845 | static void |
743 | usage () |
846 | usage () |
744 | { |
847 | { |
745 | fprintf (stderr, |
848 | fprintf (stderr, |
746 | "Usage: %s [Xt option] [-l layout] [-n count] [-p|-s|-S list] [-r count]\n", |
849 | "Usage: %s [Xt option] [-l layout] [-n count] [-p|-s|-S list] [-r count]\n", |
747 | PGM_NAME); |
850 | PGM_NAME); |
748 | exit (1); |
851 | exit (1); |
749 | } |
852 | } |
750 | |
853 | |
751 | /* |
854 | /* |
752 | * Gracefully exit after an XIO error, or after a "delete window" |
855 | * Gracefully exit after an XIO error, or after a "delete window" |
753 | * directive from the window manager. |
856 | * directive from the window manager. |
754 | * xioerror() avoids messy error messages sometimes seen from xterm |
857 | * xioerror() avoids messy error messages sometimes seen from xterm |
755 | * or in the xdm-errors file when forcibly destroying the client program. |
858 | * or in the xdm-errors file when forcibly destroying the client program. |
756 | */ |
859 | */ |
757 | static int |
860 | static int |
758 | xioerror (d) /*ARGSUSED */ |
861 | xioerror (d) /*ARGSUSED */ |
759 | Display *d; |
862 | Display *d; |
760 | { |
863 | { |
761 | exit (1); /*NOTREACHED */ |
864 | exit (1); /*NOTREACHED */ |
762 | } |
865 | } |
763 | |
866 | |
764 | static void |
867 | static void |
765 | wmdel (wdg, ptr, ep, cont) /*ARGSUSED */ |
868 | wmdel (wdg, ptr, ep, cont) /*ARGSUSED */ |
766 | Widget wdg; |
869 | Widget wdg; |
767 | XtPointer ptr; |
870 | XtPointer ptr; |
768 | XEvent *ep; |
871 | XEvent *ep; |
769 | Boolean *cont; |
872 | Boolean *cont; |
770 | { |
873 | { |
… | |
… | |
787 | if (a) |
890 | if (a) |
788 | { |
891 | { |
789 | ptr = fetch_buffer (a, &nb, !use_utf8); |
892 | ptr = fetch_buffer (a, &nb, !use_utf8); |
790 | |
893 | |
791 | if (write (1, ptr, nb) != nb) |
894 | if (write (1, ptr, nb) != nb) |
792 | { |
895 | { |
793 | fprintf (stderr, "Write error\n"); |
896 | fprintf (stderr, "Write error\n"); |
794 | exit (1); |
897 | exit (1); |
795 | } |
898 | } |
796 | |
899 | |
797 | XFree (ptr); |
900 | XFree (ptr); |
798 | } |
901 | } |
799 | } |
902 | } |
800 | |
903 | |
… | |
… | |
840 | |
943 | |
841 | atm = get_atom (n, False); |
944 | atm = get_atom (n, False); |
842 | if (XGetSelectionOwner (dpy, XA_PRIMARY) == None) |
945 | if (XGetSelectionOwner (dpy, XA_PRIMARY) == None) |
843 | { |
946 | { |
844 | if (n != 0) |
947 | if (n != 0) |
845 | { |
948 | { |
846 | data = fetch_buffer (atom[0], &nbytes, 0); |
949 | data = fetch_buffer (atom[0], &nbytes, 0); |
847 | store_buffer (data, nbytes, atm, 0); |
950 | store_buffer (data, nbytes, atm, 0); |
848 | XFree (data); |
951 | XFree (data); |
849 | } |
952 | } |
850 | return; |
953 | return; |
851 | } |
954 | } |
852 | |
955 | |
853 | XSelectInput (dpy, root, PropertyChangeMask); |
956 | XSelectInput (dpy, root, PropertyChangeMask); |
854 | XConvertSelection (dpy, XA_PRIMARY, xa_utf8_string, atm, root, CurrentTime); |
957 | XConvertSelection (dpy, XA_PRIMARY, xa_utf8_string, atm, root, CurrentTime); |
… | |
… | |
856 | |
959 | |
857 | for (;;) |
960 | for (;;) |
858 | { |
961 | { |
859 | XtAppNextEvent (app, &event); |
962 | XtAppNextEvent (app, &event); |
860 | if (event.type == PropertyNotify |
963 | if (event.type == PropertyNotify |
861 | && event.xproperty.window == root |
964 | && event.xproperty.window == root |
862 | && event.xproperty.atom == atm |
965 | && event.xproperty.atom == atm |
863 | && event.xproperty.state == PropertyNewValue) |
966 | && event.xproperty.state == PropertyNewValue) |
864 | { |
967 | { |
865 | return; |
968 | return; |
866 | } |
969 | } |
867 | |
970 | |
868 | XtDispatchEvent (&event); /* This cannot happen. !!?? */ |
971 | XtDispatchEvent (&event); /* This cannot happen. !!?? */ |
869 | } |
972 | } |
870 | } |
973 | } |
871 | |
974 | |
872 | /* |
975 | /* |
873 | * Process an ASCII list of cut buffer numbers. |
976 | * Process an ASCII list of cut buffer numbers. |
… | |
… | |
887 | int m, n, x; |
990 | int m, n, x; |
888 | |
991 | |
889 | while (*list) |
992 | while (*list) |
890 | { |
993 | { |
891 | if (!isdigit (*list)) |
994 | if (!isdigit (*list)) |
892 | usage (); |
995 | usage (); |
893 | for (m = 0; isdigit (*list); list++) |
996 | for (m = 0; isdigit (*list); list++) |
894 | m = m * 10 + *list - '0'; |
997 | m = m * 10 + *list - '0'; |
895 | |
998 | |
896 | (*fn) (m, data, nbytes); |
999 | (*fn) (m, data, nbytes); |
897 | |
1000 | |
898 | if (*list == '-') |
1001 | if (*list == '-') |
899 | { |
1002 | { |
900 | list++; |
1003 | list++; |
901 | if (!isdigit (*list)) |
1004 | if (!isdigit (*list)) |
902 | usage (); |
1005 | usage (); |
903 | for (n = 0; isdigit (*list); list++) |
1006 | for (n = 0; isdigit (*list); list++) |
904 | n = n * 10 + *list - '0'; |
1007 | n = n * 10 + *list - '0'; |
905 | |
1008 | |
906 | x = (m > n) ? -1 : 1; |
1009 | x = (m > n) ? -1 : 1; |
907 | while (m != n) |
1010 | while (m != n) |
908 | { |
1011 | { |
909 | m += x; |
1012 | m += x; |
910 | (*fn) (m, data, nbytes); |
1013 | (*fn) (m, data, nbytes); |
911 | } |
1014 | } |
912 | } |
1015 | } |
913 | |
1016 | |
914 | if (*list == ',') |
1017 | if (*list == ',') |
915 | list++; |
1018 | list++; |
916 | else if (*list) |
1019 | else if (*list) |
917 | usage (); |
1020 | usage (); |
918 | } |
1021 | } |
919 | } |
1022 | } |
920 | |
1023 | |
921 | /* |
1024 | /* |
922 | * Perform a task mode command, i.e. |
1025 | * Perform a task mode command, i.e. |
… | |
… | |
934 | ptr = (char *) 0; |
1037 | ptr = (char *) 0; |
935 | n = nb = 0; |
1038 | n = nb = 0; |
936 | |
1039 | |
937 | switch (cmd) |
1040 | switch (cmd) |
938 | { |
1041 | { |
939 | case 'p': /* print one or more buffers */ |
1042 | case 'p': /* print one or more buffers */ |
940 | dolist (arg, doprint, (char *) 0, 0); |
1043 | dolist (arg, doprint, (char *) 0, 0); |
941 | break; |
1044 | break; |
942 | case 'r': /* rotate the buffer contents */ |
1045 | case 'r': /* rotate the buffer contents */ |
943 | n = atoi (arg); |
1046 | n = atoi (arg); |
944 | |
1047 | |
945 | if (n == 0) |
1048 | if (n == 0) |
946 | break; |
1049 | break; |
947 | |
1050 | |
948 | initialize_properties (); |
1051 | initialize_properties (); |
949 | |
1052 | |
950 | XRotateWindowProperties (dpy, root, atom, nbuffs, n); |
1053 | XRotateWindowProperties (dpy, root, atom, nbuffs, n); |
951 | break; |
1054 | break; |
952 | case 's': /* store data in one or more buffers */ |
1055 | case 's': /* store data in one or more buffers */ |
953 | do |
1056 | do |
954 | { |
1057 | { |
955 | ptr = XtRealloc (ptr, nb + BUFINC); |
1058 | ptr = XtRealloc (ptr, nb + BUFINC); |
956 | i = BUFINC; |
1059 | i = BUFINC; |
957 | do |
1060 | do |
958 | { |
1061 | { |
959 | n = read (0, ptr + nb, i); |
1062 | n = read (0, ptr + nb, i); |
960 | nb += n; |
1063 | nb += n; |
961 | i -= n; |
1064 | i -= n; |
962 | } |
1065 | } |
963 | while (n > 0 && i > 0); |
1066 | while (n > 0 && i > 0); |
964 | } |
1067 | } |
965 | while (n > 0); |
1068 | while (n > 0); |
966 | |
1069 | |
967 | if (n == -1) |
1070 | if (n == -1) |
968 | { |
1071 | { |
969 | fprintf (stderr, "Read error\n"); |
1072 | fprintf (stderr, "Read error\n"); |
970 | exit (1); |
1073 | exit (1); |
971 | } |
1074 | } |
972 | |
1075 | |
973 | dolist (arg, doset, ptr, nb); |
1076 | dolist (arg, doset, ptr, nb); |
974 | XtFree (ptr); |
1077 | XtFree (ptr); |
975 | break; |
1078 | break; |
976 | case 'S': |
1079 | case 'S': |
… | |
… | |
988 | |
1091 | |
989 | static ares_t ares; |
1092 | static ares_t ares; |
990 | |
1093 | |
991 | static XtResource res[] = |
1094 | static XtResource res[] = |
992 | { |
1095 | { |
993 | #define offset(field) XtOffset(ares_ptr, field) |
1096 | #define offset(field) XtOffset(ares_ptr, field) |
994 | {XtNbufferCount, XtCBufferCount, XtRInt, sizeof (int), |
1097 | {XtNbufferCount, XtCBufferCount, XtRInt, sizeof (int), |
995 | offset (nbuffs), XtRImmediate, (XtPointer) 8}, |
1098 | offset (nbuffs), XtRImmediate, (XtPointer) 8}, |
996 | {XtNlayout, XtCLayout, XtRString, sizeof (char *), |
1099 | {XtNlayout, XtCLayout, XtRString, sizeof (char *), |
997 | offset (layout), XtRImmediate, "horiz"}, |
1100 | offset (layout), XtRImmediate, "horiz"}, |
998 | #undef offset |
1101 | #undef offset |
999 | }; |
1102 | }; |
1000 | |
1103 | |
1001 | static char *def[] = |
1104 | static char *def[] = |
1002 | { /* default resource values */ |
1105 | { /* default resource values */ |
1003 | ".bufferCount: 8", |
1106 | ".bufferCount: 8", |
1004 | ".layout: horizontal", |
1107 | ".layout: horizontal", |
1005 | "*fontSet: XtDefaultFontSet", |
1108 | "*fontSet: XtDefaultFontSet", |
1006 | "*Buffer.width: 60", |
1109 | "*Buffer.width: 60", |
1007 | "*Buffer.height: 60", |
1110 | "*Buffer.height: 60", |
1008 | 0, |
1111 | 0, |
1009 | }; |
1112 | }; |
1010 | |
1113 | |
1011 | static XrmOptionDescRec opt[] = |
1114 | static XrmOptionDescRec opt[] = |
1012 | { |
1115 | { |
… | |
… | |
1050 | XtSetLanguageProc (0, 0, 0); |
1153 | XtSetLanguageProc (0, 0, 0); |
1051 | top = XtAppInitialize (&app, PGM_CLASS, opt, 2, &argc, argv, def, 0, 0); |
1154 | top = XtAppInitialize (&app, PGM_CLASS, opt, 2, &argc, argv, def, 0, 0); |
1052 | dpy = XtDisplay (top); |
1155 | dpy = XtDisplay (top); |
1053 | root = RootWindow (dpy, DefaultScreen (dpy)); |
1156 | root = RootWindow (dpy, DefaultScreen (dpy)); |
1054 | |
1157 | |
|
|
1158 | XtSetTypeConverter(XtRString, /* source type */ |
|
|
1159 | XtRFontSet, /* target type */ |
|
|
1160 | CvtStringToFontSet, /* converter routine */ |
|
|
1161 | (XtConvertArgList) NULL, |
|
|
1162 | /* args for converter routine */ |
|
|
1163 | 0, /*# args for converter routine */ |
|
|
1164 | XtCacheAll, /* caching instructions */ |
|
|
1165 | NULL); /* destructor function */ |
|
|
1166 | |
1055 | XtGetApplicationResources (top, &ares, res, XtNumber (res), 0, 0); |
1167 | XtGetApplicationResources (top, &ares, res, XtNumber (res), 0, 0); |
1056 | nbuffs = max (ares.nbuffs, 1); |
1168 | nbuffs = max (ares.nbuffs, 1); |
1057 | |
1169 | |
1058 | /* search for the -u and -v switches first */ |
1170 | /* search for the -u and -v switches first */ |
1059 | for (p = argv + 1; p < argv + argc; p++) |
1171 | for (p = argv + 1; p < argv + argc; p++) |
1060 | { |
1172 | { |
1061 | if (eq (*p, "-u")) |
1173 | if (eq (*p, "-u")) |
1062 | use_utf8 = 1; |
1174 | use_utf8 = 1; |
1063 | else if (eq (*p, "-V")) |
1175 | else if (eq (*p, "-V")) |
1064 | { |
1176 | { |
1065 | printf ("xcb version %s\n", version); |
1177 | printf ("xcb version %s\n", version); |
1066 | exit (0); |
1178 | exit (0); |
1067 | } |
1179 | } |
1068 | } |
1180 | } |
1069 | |
1181 | |
1070 | /* |
1182 | /* |
1071 | * If the command line contains one of the task mode |
1183 | * If the command line contains one of the task mode |
1072 | * switches (print, set, rotate), it is processed here. |
1184 | * switches (print, set, rotate), it is processed here. |
… | |
… | |
1074 | * one is processed. |
1186 | * one is processed. |
1075 | */ |
1187 | */ |
1076 | for (p = argv + 1; p < argv + argc; p++) |
1188 | for (p = argv + 1; p < argv + argc; p++) |
1077 | { |
1189 | { |
1078 | if (eq (*p, "-p") || eq (*p, "-r") || eq (*p, "-s") || eq (*p, "-S")) |
1190 | if (eq (*p, "-p") || eq (*p, "-r") || eq (*p, "-s") || eq (*p, "-S")) |
1079 | { |
1191 | { |
1080 | if (p == argv + argc - 1) |
1192 | if (p == argv + argc - 1) |
1081 | usage (); |
1193 | usage (); |
1082 | |
1194 | |
1083 | dotask (p[0][1], p[1]); |
1195 | dotask (p[0][1], p[1]); |
1084 | XCloseDisplay (dpy); |
1196 | XCloseDisplay (dpy); |
1085 | exit (0); |
1197 | exit (0); |
1086 | } |
1198 | } |
1087 | } |
1199 | } |
1088 | |
1200 | |
1089 | /* |
1201 | /* |
1090 | * If no task mode request has been made of us, this code |
1202 | * If no task mode request has been made of us, this code |
1091 | * proceeds with the rest of the windows initialization. |
1203 | * proceeds with the rest of the windows initialization. |
… | |
… | |
1104 | for (i = 0; i < nbuffs; i++) |
1216 | for (i = 0; i < nbuffs; i++) |
1105 | { |
1217 | { |
1106 | XtSetArg (args[0], XtNatom, get_atom (i, False)); |
1218 | XtSetArg (args[0], XtNatom, get_atom (i, False)); |
1107 | n = 1; |
1219 | n = 1; |
1108 | if (i > 0) |
1220 | if (i > 0) |
1109 | { |
1221 | { |
1110 | if (ares.layout[0] == 'h') |
1222 | if (ares.layout[0] == 'h') |
1111 | { |
1223 | { |
1112 | XtSetArg (args[1], XtNfromHoriz, wdg[i - 1]); |
1224 | XtSetArg (args[1], XtNfromHoriz, wdg[i - 1]); |
1113 | XtSetArg (args[2], XtNfromVert, 0); |
1225 | XtSetArg (args[2], XtNfromVert, 0); |
1114 | n = 3; |
1226 | n = 3; |
1115 | } |
1227 | } |
1116 | |
1228 | |
1117 | if (ares.layout[0] == 'v') |
1229 | if (ares.layout[0] == 'v') |
1118 | { |
1230 | { |
1119 | XtSetArg (args[1], XtNfromVert, wdg[i - 1]); |
1231 | XtSetArg (args[1], XtNfromVert, wdg[i - 1]); |
1120 | XtSetArg (args[2], XtNfromHoriz, 0); |
1232 | XtSetArg (args[2], XtNfromHoriz, 0); |
1121 | n = 3; |
1233 | n = 3; |
1122 | } |
1234 | } |
1123 | } |
1235 | } |
1124 | |
1236 | |
1125 | sprintf (name, "buffer%d", i); |
1237 | sprintf (name, "buffer%d", i); |
1126 | wdg[i] = XtCreateWidget (name, cbWidgetClass, box, args, n); |
1238 | wdg[i] = XtCreateWidget (name, cbWidgetClass, box, args, n); |
1127 | XtManageChild (wdg[i]); |
1239 | XtManageChild (wdg[i]); |
1128 | } |
1240 | } |
… | |
… | |
1176 | xa_utf8_string = XInternAtom (dpy, "UTF8_STRING", False); |
1288 | xa_utf8_string = XInternAtom (dpy, "UTF8_STRING", False); |
1177 | xa_text = XInternAtom (dpy, "TEXT", False); |
1289 | xa_text = XInternAtom (dpy, "TEXT", False); |
1178 | |
1290 | |
1179 | if (!xa_utf8_string) |
1291 | if (!xa_utf8_string) |
1180 | xa_utf8_string = xa_compound_text; |
1292 | xa_utf8_string = xa_compound_text; |
1181 | |
|
|
1182 | #ifdef XVIEW |
|
|
1183 | clipboard = XInternAtom (dpy, "CLIPBOARD", False); |
|
|
1184 | caret = XInternAtom (dpy, "_SUN_SELN_CARET", False); |
|
|
1185 | yield = XInternAtom (dpy, "_SUN_SELN_YIELD", False); |
|
|
1186 | length = XInternAtom (dpy, "LENGTH", False); |
|
|
1187 | lengthc = XInternAtom (dpy, "LENGTH_CHARS", False); |
|
|
1188 | #endif |
|
|
1189 | |
1293 | |
1190 | initialize_properties (); |
1294 | initialize_properties (); |
1191 | } |
1295 | } |
1192 | |
1296 | |
1193 | /* |
1297 | /* |
… | |
… | |
1240 | XConvertSelection (dpy, XA_PRIMARY, target, |
1344 | XConvertSelection (dpy, XA_PRIMARY, target, |
1241 | convert_to, event.xselection.requestor, event.xselection.time); |
1345 | convert_to, event.xselection.requestor, event.xselection.time); |
1242 | } |
1346 | } |
1243 | } |
1347 | } |
1244 | else |
1348 | else |
1245 | { |
|
|
1246 | (void) XtDispatchEvent (&event); |
1349 | (void) XtDispatchEvent (&event); |
1247 | } |
|
|
1248 | } |
1350 | } |
1249 | } |
1351 | } |
1250 | |
1352 | |
1251 | main (argc, argv) |
1353 | main (argc, argv) |
1252 | int argc; |
1354 | int argc; |