1 | /* |
---|
2 | * Copyright 1994, 1995 by Paul Mattes. |
---|
3 | * Permission to use, copy, modify, and distribute this software and its |
---|
4 | * documentation for any purpose and without fee is hereby granted, |
---|
5 | * provided that the above copyright notice appear in all copies and that |
---|
6 | * both that copyright notice and this permission notice appear in |
---|
7 | * supporting documentation. |
---|
8 | */ |
---|
9 | |
---|
10 | /* |
---|
11 | * save.c |
---|
12 | * Implements the response to the WM_SAVE_YOURSELF message and |
---|
13 | * x3270 profiles. |
---|
14 | */ |
---|
15 | |
---|
16 | #include "globals.h" |
---|
17 | #include <X11/StringDefs.h> |
---|
18 | #include <X11/Xatom.h> |
---|
19 | #include <pwd.h> |
---|
20 | #include <errno.h> |
---|
21 | #include <time.h> |
---|
22 | #include "appres.h" |
---|
23 | #include "resources.h" |
---|
24 | |
---|
25 | #include "mainc.h" |
---|
26 | #include "savec.h" |
---|
27 | #include "popupsc.h" |
---|
28 | #include "utilc.h" |
---|
29 | |
---|
30 | |
---|
31 | /* Support for WM_SAVE_YOURSELF. */ |
---|
32 | |
---|
33 | extern Boolean keypad_changed; |
---|
34 | extern Boolean keypad_popped; |
---|
35 | extern Boolean model_changed; |
---|
36 | extern Boolean scrollbar_changed; |
---|
37 | extern Boolean efont_changed; |
---|
38 | extern Boolean oversize_changed; |
---|
39 | extern Boolean scheme_changed; |
---|
40 | extern Boolean keymap_changed; |
---|
41 | extern Boolean charset_changed; |
---|
42 | |
---|
43 | char *command_string = CN; |
---|
44 | |
---|
45 | static char *cmd; |
---|
46 | static int cmd_len; |
---|
47 | |
---|
48 | #define NWORDS 1024 |
---|
49 | |
---|
50 | static char **tmp_cmd; |
---|
51 | static int tcs; |
---|
52 | |
---|
53 | /* Search for an option in the tmp_cmd array. */ |
---|
54 | static int |
---|
55 | cmd_srch(s) |
---|
56 | char *s; |
---|
57 | { |
---|
58 | int i; |
---|
59 | |
---|
60 | for (i = 1; i < tcs; i++) |
---|
61 | if (tmp_cmd[i] && !strcmp(tmp_cmd[i], s)) |
---|
62 | return i; |
---|
63 | return 0; |
---|
64 | } |
---|
65 | |
---|
66 | /* Replace an options in the tmp_cmd array. */ |
---|
67 | static void |
---|
68 | cmd_replace(ix, s) |
---|
69 | int ix; |
---|
70 | char *s; |
---|
71 | { |
---|
72 | XtFree(tmp_cmd[ix]); |
---|
73 | tmp_cmd[ix] = XtNewString(s); |
---|
74 | } |
---|
75 | |
---|
76 | /* Append an option to the tmp_cmd array. */ |
---|
77 | static void |
---|
78 | cmd_append(s) |
---|
79 | char *s; |
---|
80 | { |
---|
81 | tmp_cmd[tcs++] = XtNewString(s); |
---|
82 | tmp_cmd[tcs] = (char *) NULL; |
---|
83 | } |
---|
84 | |
---|
85 | /* Delete an option from the tmp_cmd array. */ |
---|
86 | static void |
---|
87 | cmd_delete(ix) |
---|
88 | int ix; |
---|
89 | { |
---|
90 | XtFree(tmp_cmd[ix]); |
---|
91 | tmp_cmd[ix] = (char *) NULL; |
---|
92 | } |
---|
93 | |
---|
94 | /* Save the screen geometry. */ |
---|
95 | static void |
---|
96 | save_xy() |
---|
97 | { |
---|
98 | char tbuf[64]; |
---|
99 | Window window, frame, child; |
---|
100 | XWindowAttributes wa; |
---|
101 | int x, y; |
---|
102 | int ix; |
---|
103 | |
---|
104 | window = XtWindow(toplevel); |
---|
105 | if (!x_get_window_attributes(window, &wa)) |
---|
106 | return; |
---|
107 | (void) XTranslateCoordinates(display, window, wa.root, |
---|
108 | -wa.border_width, -wa.border_width, |
---|
109 | &x, &y, &child); |
---|
110 | |
---|
111 | frame = XtWindow(toplevel); |
---|
112 | while (True) { |
---|
113 | Window root, parent; |
---|
114 | Window *children; |
---|
115 | unsigned int nchildren; |
---|
116 | |
---|
117 | int status = XQueryTree(display, frame, &root, &parent, |
---|
118 | &children, &nchildren); |
---|
119 | if (parent == root || !parent || !status) |
---|
120 | break; |
---|
121 | frame = parent; |
---|
122 | if (status && children) |
---|
123 | XFree((char *)children); |
---|
124 | } |
---|
125 | if (frame != window) { |
---|
126 | if (!x_get_window_attributes(frame, &wa)) |
---|
127 | return; |
---|
128 | x = wa.x; |
---|
129 | y = wa.y; |
---|
130 | } |
---|
131 | |
---|
132 | (void) sprintf(tbuf, "+%d+%d", x, y); |
---|
133 | if ((ix = cmd_srch("-geometry"))) |
---|
134 | cmd_replace(ix + 1, tbuf); |
---|
135 | else { |
---|
136 | cmd_append("-geometry"); |
---|
137 | cmd_append(tbuf); |
---|
138 | } |
---|
139 | } |
---|
140 | |
---|
141 | /* Save the icon information: state, label, geometry. */ |
---|
142 | static void |
---|
143 | save_icon() |
---|
144 | { |
---|
145 | unsigned char *data; |
---|
146 | int iconX, iconY; |
---|
147 | char tbuf[64]; |
---|
148 | int ix; |
---|
149 | unsigned long nitems; |
---|
150 | |
---|
151 | { |
---|
152 | Atom actual_type; |
---|
153 | int actual_format; |
---|
154 | unsigned long leftover; |
---|
155 | |
---|
156 | if (XGetWindowProperty(display, XtWindow(toplevel), a_state, |
---|
157 | 0L, 2L, False, a_state, &actual_type, &actual_format, |
---|
158 | &nitems, &leftover, &data) != Success) |
---|
159 | return; |
---|
160 | if (actual_type != a_state || |
---|
161 | actual_format != 32 || |
---|
162 | nitems < 1) |
---|
163 | return; |
---|
164 | } |
---|
165 | |
---|
166 | ix = cmd_srch("-iconic"); |
---|
167 | if (*(unsigned long *)data == IconicState) { |
---|
168 | if (!ix) |
---|
169 | cmd_append("-iconic"); |
---|
170 | } else { |
---|
171 | if (ix) |
---|
172 | cmd_delete(ix); |
---|
173 | } |
---|
174 | |
---|
175 | if (nitems < 2) |
---|
176 | return; |
---|
177 | |
---|
178 | { |
---|
179 | Window icon_window; |
---|
180 | XWindowAttributes wa; |
---|
181 | Window child; |
---|
182 | |
---|
183 | icon_window = *(Window *)(data + sizeof(unsigned long)); |
---|
184 | if (icon_window == None) |
---|
185 | return; |
---|
186 | if (!x_get_window_attributes(icon_window, &wa)) |
---|
187 | return; |
---|
188 | (void) XTranslateCoordinates(display, icon_window, wa.root, |
---|
189 | -wa.border_width, -wa.border_width, &iconX, &iconY, |
---|
190 | &child); |
---|
191 | if (!iconX && !iconY) |
---|
192 | return; |
---|
193 | } |
---|
194 | |
---|
195 | (void) sprintf(tbuf, "%d", iconX); |
---|
196 | ix = cmd_srch(OptIconX); |
---|
197 | if (ix) |
---|
198 | cmd_replace(ix + 1, tbuf); |
---|
199 | else { |
---|
200 | cmd_append(OptIconX); |
---|
201 | cmd_append(tbuf); |
---|
202 | } |
---|
203 | |
---|
204 | (void) sprintf(tbuf, "%d", iconY); |
---|
205 | ix = cmd_srch(OptIconY); |
---|
206 | if (ix) |
---|
207 | cmd_replace(ix + 1, tbuf); |
---|
208 | else { |
---|
209 | cmd_append(OptIconY); |
---|
210 | cmd_append(tbuf); |
---|
211 | } |
---|
212 | return; |
---|
213 | } |
---|
214 | |
---|
215 | /* Save the keymap information. */ |
---|
216 | /*ARGSUSED*/ |
---|
217 | static void |
---|
218 | save_keymap() |
---|
219 | { |
---|
220 | /* Note: keymap propogation is deliberately disabled, because it |
---|
221 | may vary from workstation to workstation. The recommended |
---|
222 | way of specifying keymaps is through your .Xdefaults or the |
---|
223 | KEYMAP or KEYBD environment variables, which can be easily set |
---|
224 | in your .login or .profile to machine-specific values; the |
---|
225 | -keymap switch is really for debugging or testing keymaps. |
---|
226 | |
---|
227 | I'm sure I'll regret this. */ |
---|
228 | |
---|
229 | #if defined(notdef) /*[*/ |
---|
230 | if (appres.keymap) { |
---|
231 | add_string(v, OptKeymap); |
---|
232 | add_string(v, appres.keymap); |
---|
233 | } |
---|
234 | #endif /*]*/ |
---|
235 | } |
---|
236 | |
---|
237 | /* Save the model name. */ |
---|
238 | static void |
---|
239 | save_model() |
---|
240 | { |
---|
241 | int ix; |
---|
242 | |
---|
243 | if (!model_changed) |
---|
244 | return; |
---|
245 | if ((ix = cmd_srch(OptModel)) && strcmp(tmp_cmd[ix], model_name)) |
---|
246 | cmd_replace(ix + 1, model_name); |
---|
247 | else { |
---|
248 | cmd_append(OptModel); |
---|
249 | cmd_append(model_name); |
---|
250 | } |
---|
251 | } |
---|
252 | |
---|
253 | /* Save the keypad state. */ |
---|
254 | static void |
---|
255 | save_keypad() |
---|
256 | { |
---|
257 | int ix; |
---|
258 | |
---|
259 | ix = cmd_srch(OptKeypadOn); |
---|
260 | if (appres.keypad_on || keypad_popped) { |
---|
261 | if (!ix) |
---|
262 | cmd_append(OptKeypadOn); |
---|
263 | } else { |
---|
264 | if (ix) |
---|
265 | cmd_delete(ix); |
---|
266 | } |
---|
267 | } |
---|
268 | |
---|
269 | /* Save the scrollbar state. */ |
---|
270 | static void |
---|
271 | save_scrollbar() |
---|
272 | { |
---|
273 | int i_on, i_off; |
---|
274 | |
---|
275 | if (!scrollbar_changed) |
---|
276 | return; |
---|
277 | i_on = cmd_srch(OptScrollBar); |
---|
278 | i_off = cmd_srch(OptNoScrollBar); |
---|
279 | if (toggled(SCROLL_BAR)) { |
---|
280 | if (!i_on) { |
---|
281 | if (i_off) |
---|
282 | cmd_replace(i_off, OptScrollBar); |
---|
283 | else |
---|
284 | cmd_append(OptScrollBar); |
---|
285 | } |
---|
286 | } else { |
---|
287 | if (!i_off) { |
---|
288 | if (i_on) |
---|
289 | cmd_replace(i_on, OptNoScrollBar); |
---|
290 | else |
---|
291 | cmd_append(OptNoScrollBar); |
---|
292 | } |
---|
293 | } |
---|
294 | } |
---|
295 | |
---|
296 | /* Save the name of the host we are connected to. */ |
---|
297 | static void |
---|
298 | save_host() |
---|
299 | { |
---|
300 | char *space; |
---|
301 | |
---|
302 | if (!CONNECTED) |
---|
303 | return; |
---|
304 | space = strchr(full_current_host, ' '); |
---|
305 | if (space == (char *) NULL) |
---|
306 | cmd_append(full_current_host); |
---|
307 | else { |
---|
308 | char *tmp = XtNewString(full_current_host); |
---|
309 | char *port; |
---|
310 | |
---|
311 | space = strchr(tmp, ' '); |
---|
312 | *space = '\0'; |
---|
313 | cmd_append(tmp); |
---|
314 | port = space + 1; |
---|
315 | while (*port == ' ') |
---|
316 | port++; |
---|
317 | if (*port) |
---|
318 | cmd_append(port); |
---|
319 | XtFree(tmp); |
---|
320 | } |
---|
321 | } |
---|
322 | |
---|
323 | /* Save the settings of each of the toggles. */ |
---|
324 | static void |
---|
325 | save_toggles() |
---|
326 | { |
---|
327 | int i, j; |
---|
328 | int ix; |
---|
329 | |
---|
330 | for (i = 0; i < N_TOGGLES; i++) { |
---|
331 | if (!appres.toggle[i].changed) |
---|
332 | continue; |
---|
333 | |
---|
334 | /* |
---|
335 | * Find the last "-set" or "-clear" for this toggle. |
---|
336 | * If there is a preferred alias, delete them instead. |
---|
337 | */ |
---|
338 | ix = 0; |
---|
339 | for (j = 1; j < tcs; j++) |
---|
340 | if (tmp_cmd[j] && |
---|
341 | (!strcmp(tmp_cmd[j], OptSet) || |
---|
342 | !strcmp(tmp_cmd[j], OptClear)) && |
---|
343 | tmp_cmd[j+1] && |
---|
344 | !strcmp(tmp_cmd[j+1], toggle_names[i].name)) { |
---|
345 | if (i == SCROLL_BAR || i == DS_TRACE) { |
---|
346 | cmd_delete(j); |
---|
347 | cmd_delete(j + 1); |
---|
348 | } else |
---|
349 | ix = j; |
---|
350 | } |
---|
351 | |
---|
352 | /* Handle aliased switches. */ |
---|
353 | switch (i) { |
---|
354 | case SCROLL_BAR: |
---|
355 | continue; /* +sb/-sb done separately */ |
---|
356 | case DS_TRACE: |
---|
357 | ix = cmd_srch(OptDsTrace); |
---|
358 | if (appres.toggle[DS_TRACE].value) { |
---|
359 | if (!ix) |
---|
360 | cmd_append(OptDsTrace); |
---|
361 | } else { |
---|
362 | if (ix) |
---|
363 | cmd_delete(ix); |
---|
364 | } |
---|
365 | continue; |
---|
366 | } |
---|
367 | |
---|
368 | /* If need be, switch "-set" with "-clear", or append one. */ |
---|
369 | if (appres.toggle[i].value) { |
---|
370 | if (ix && strcmp(tmp_cmd[ix], OptSet)) |
---|
371 | cmd_replace(ix, OptSet); |
---|
372 | else if (!ix) { |
---|
373 | cmd_append(OptSet); |
---|
374 | cmd_append(toggle_names[i].name); |
---|
375 | } |
---|
376 | } else { |
---|
377 | if (ix && strcmp(tmp_cmd[ix], OptClear)) |
---|
378 | cmd_replace(ix, OptClear); |
---|
379 | else if (!ix) { |
---|
380 | cmd_append(OptClear); |
---|
381 | cmd_append(toggle_names[i].name); |
---|
382 | } |
---|
383 | } |
---|
384 | } |
---|
385 | } |
---|
386 | |
---|
387 | /* Remove a positional parameter from the command line. */ |
---|
388 | static void |
---|
389 | remove_positional(s) |
---|
390 | char *s; |
---|
391 | { |
---|
392 | char *c; |
---|
393 | |
---|
394 | c = cmd + cmd_len - 2; /* last byte of last arg */ |
---|
395 | while (*c && c >= cmd) |
---|
396 | c--; |
---|
397 | if (strcmp(s, c + 1)) |
---|
398 | XtError("Command-line switches must precede positional arguments"); |
---|
399 | cmd_len = c - cmd; |
---|
400 | } |
---|
401 | |
---|
402 | /* Save a copy of he XA_WM_COMMAND poperty. */ |
---|
403 | void |
---|
404 | save_init(argc, hostname, port) |
---|
405 | int argc; |
---|
406 | char *hostname; |
---|
407 | char *port; |
---|
408 | { |
---|
409 | Atom actual_type; |
---|
410 | int actual_format; |
---|
411 | unsigned long nitems; |
---|
412 | unsigned long bytes_after; |
---|
413 | |
---|
414 | /* |
---|
415 | * Fetch the initial value of the XA_COMMAND property and store |
---|
416 | * it in 'cmd'. |
---|
417 | */ |
---|
418 | XGetWindowProperty(display, XtWindow(toplevel), XA_WM_COMMAND, |
---|
419 | 0L, 1000000L, False, XA_STRING, &actual_type, &actual_format, |
---|
420 | &nitems, &bytes_after, (unsigned char **)&cmd); |
---|
421 | if (nitems == 0) |
---|
422 | XtError("Could not get initial XA_COMMAND property"); |
---|
423 | cmd_len = nitems * (actual_format / 8); |
---|
424 | |
---|
425 | /* |
---|
426 | * Now locate the hostname and port positional arguments, and |
---|
427 | * remove them. If they aren't the last two components of the |
---|
428 | * command line, abort. |
---|
429 | */ |
---|
430 | switch (argc) { |
---|
431 | case 3: |
---|
432 | remove_positional(port); |
---|
433 | /* fall through */ |
---|
434 | case 2: |
---|
435 | remove_positional(hostname); |
---|
436 | break; |
---|
437 | } |
---|
438 | } |
---|
439 | |
---|
440 | /* Handle a WM_SAVE_YOURSELF ICCM. */ |
---|
441 | void |
---|
442 | save_yourself() |
---|
443 | { |
---|
444 | int i; |
---|
445 | char *c, *c2; |
---|
446 | int len; |
---|
447 | |
---|
448 | if (command_string != CN) { |
---|
449 | XtFree(command_string); |
---|
450 | command_string = CN; |
---|
451 | } |
---|
452 | |
---|
453 | /* Copy the original command line into tmp_cmd. */ |
---|
454 | tmp_cmd = (char **) XtMalloc(sizeof(char *) * NWORDS); |
---|
455 | tcs = 0; |
---|
456 | i = 0; |
---|
457 | c = cmd; |
---|
458 | while (i < cmd_len) { |
---|
459 | c = cmd + i; |
---|
460 | tmp_cmd[tcs++] = XtNewString(c); |
---|
461 | i += strlen(c); |
---|
462 | i++; |
---|
463 | } |
---|
464 | tmp_cmd[tcs] = (char *) NULL; |
---|
465 | |
---|
466 | /* Replace the first element with the program name. */ |
---|
467 | cmd_replace(0, programname); |
---|
468 | |
---|
469 | /* Save options. */ |
---|
470 | save_xy(); |
---|
471 | save_icon(); |
---|
472 | save_keymap(); |
---|
473 | save_model(); |
---|
474 | save_keypad(); |
---|
475 | save_scrollbar(); |
---|
476 | save_host(); |
---|
477 | save_toggles(); |
---|
478 | |
---|
479 | /* Copy what's left into contiguous memory. */ |
---|
480 | len = 0; |
---|
481 | for (i = 0; i < tcs; i++) |
---|
482 | if (tmp_cmd[i]) |
---|
483 | len += strlen(tmp_cmd[i]) + 1; |
---|
484 | c = XtMalloc(len); |
---|
485 | c[0] = '\0'; |
---|
486 | c2 = c; |
---|
487 | for (i = 0; i < tcs; i++) |
---|
488 | if (tmp_cmd[i]) { |
---|
489 | (void) strcpy(c2, tmp_cmd[i]); |
---|
490 | c2 += strlen(c2) + 1; |
---|
491 | XtFree(tmp_cmd[i]); |
---|
492 | } |
---|
493 | XtFree((XtPointer)tmp_cmd); |
---|
494 | |
---|
495 | /* Change the property. */ |
---|
496 | XChangeProperty(display, XtWindow(toplevel), XA_WM_COMMAND, |
---|
497 | XA_STRING, 8, PropModeReplace, (unsigned char *)c, len); |
---|
498 | |
---|
499 | /* Save a readable copy of the command string for posterity. */ |
---|
500 | command_string = c; |
---|
501 | while (((c2 = strchr(c, '\0')) != CN) && |
---|
502 | (c2 - command_string < len-1)) { |
---|
503 | *c2 = ' '; |
---|
504 | c = c2 + 1; |
---|
505 | } |
---|
506 | } |
---|
507 | |
---|
508 | |
---|
509 | /* Support for x3270 profiles. */ |
---|
510 | |
---|
511 | #define PROFILE_ENV "X3270PRO" |
---|
512 | #define NO_PROFILE_ENV "NOX3270PRO" |
---|
513 | #define DEFAULT_PROFILE "~/.x3270pro" |
---|
514 | |
---|
515 | extern XrmOptionDescRec options[]; |
---|
516 | extern int num_options; |
---|
517 | |
---|
518 | char *profile_name = CN; |
---|
519 | static char *xcmd; |
---|
520 | static int xargc; |
---|
521 | static char **xargv; |
---|
522 | |
---|
523 | /* Save one option in the file. */ |
---|
524 | static void |
---|
525 | save_opt(f, full_name, opt_name, res_name, value) |
---|
526 | FILE *f; |
---|
527 | char *full_name; |
---|
528 | char *opt_name; |
---|
529 | char *res_name; |
---|
530 | char *value; |
---|
531 | { |
---|
532 | (void) fprintf(f, "! %s (%s)\nx3270.%s: %s\n", |
---|
533 | full_name, opt_name, res_name, value); |
---|
534 | } |
---|
535 | |
---|
536 | /* Save the current options settings in a profile. */ |
---|
537 | int |
---|
538 | save_options(n) |
---|
539 | char *n; |
---|
540 | { |
---|
541 | FILE *f; |
---|
542 | Boolean exists = False; |
---|
543 | char *ct; |
---|
544 | int i; |
---|
545 | extern char *build; |
---|
546 | long clock; |
---|
547 | char buf[64]; |
---|
548 | Boolean any_toggles = False; |
---|
549 | |
---|
550 | if (n == CN || *n == '\0') |
---|
551 | return -1; |
---|
552 | |
---|
553 | /* Open the file. */ |
---|
554 | n = do_subst(n, True, True); |
---|
555 | f = fopen(n, "r"); |
---|
556 | if (f != (FILE *)NULL) { |
---|
557 | (void) fclose(f); |
---|
558 | exists = True; |
---|
559 | } |
---|
560 | f = fopen(n, "a"); |
---|
561 | if (f == (FILE *)NULL) { |
---|
562 | popup_an_errno(errno, "Cannot open %s", n); |
---|
563 | XtFree(n); |
---|
564 | return -1; |
---|
565 | } |
---|
566 | |
---|
567 | /* Save the name. */ |
---|
568 | if (profile_name == CN) |
---|
569 | XtFree(profile_name); |
---|
570 | profile_name = n; |
---|
571 | |
---|
572 | /* Print the header. */ |
---|
573 | clock = time((long *)0); |
---|
574 | ct = ctime(&clock); |
---|
575 | if (ct[strlen(ct)-1] == '\n') |
---|
576 | ct[strlen(ct)-1] = '\0'; |
---|
577 | if (exists) |
---|
578 | (void) fprintf(f, "! File updated %s by %s\n", ct, build); |
---|
579 | else |
---|
580 | (void) fprintf(f, |
---|
581 | "! x3270 profile\n\ |
---|
582 | ! File created %s by %s\n\ |
---|
583 | ! This file overrides xrdb and .Xdefaults.\n\ |
---|
584 | ! To skip reading this file, set %s in the environment.\n\ |
---|
585 | !\n", |
---|
586 | ct, build, NO_PROFILE_ENV); |
---|
587 | |
---|
588 | /* Save most of the toggles. */ |
---|
589 | for (i = 0; i < N_TOGGLES; i++) { |
---|
590 | if (!appres.toggle[i].changed) |
---|
591 | continue; |
---|
592 | if (i == DS_TRACE || i == SCREEN_TRACE || i == EVENT_TRACE) |
---|
593 | continue; |
---|
594 | if (!any_toggles) { |
---|
595 | (void) fprintf(f, "! toggles (%s, %s)\n", |
---|
596 | OptSet, OptClear); |
---|
597 | any_toggles = True; |
---|
598 | } |
---|
599 | (void) fprintf(f, "x3270.%s: %s\n", toggle_names[i].name, |
---|
600 | appres.toggle[i].value ? ResTrue : ResFalse); |
---|
601 | } |
---|
602 | |
---|
603 | /* Save the keypad state. */ |
---|
604 | if (keypad_changed) |
---|
605 | save_opt(f, "keypad state", OptKeypadOn, ResKeypadOn, |
---|
606 | (appres.keypad_on || keypad_popped) ? |
---|
607 | ResTrue : ResFalse); |
---|
608 | |
---|
609 | /* Save other menu-changeable options. */ |
---|
610 | if (efont_changed) |
---|
611 | save_opt(f, "emulator font", OptEmulatorFont, ResEmulatorFont, |
---|
612 | efontname); |
---|
613 | if (model_changed) { |
---|
614 | (void) sprintf(buf, "%d", model_num); |
---|
615 | save_opt(f, "model", OptModel, ResModel, buf); |
---|
616 | } |
---|
617 | if (oversize_changed) { |
---|
618 | (void) sprintf(buf, "%dx%d", ov_cols, ov_rows); |
---|
619 | save_opt(f, "oversize", OptOversize, ResOversize, buf); |
---|
620 | } |
---|
621 | if (scheme_changed && appres.color_scheme != CN) |
---|
622 | save_opt(f, "color scheme", OptColorScheme, ResColorScheme, |
---|
623 | appres.color_scheme); |
---|
624 | if (keymap_changed && appres.key_map != (char *)NULL) |
---|
625 | save_opt(f, "keymap", OptKeymap, ResKeymap, appres.key_map); |
---|
626 | if (charset_changed && appres.charset != (char *)NULL) |
---|
627 | save_opt(f, "charset", OptCharset, ResCharset, appres.charset); |
---|
628 | |
---|
629 | /* Done. */ |
---|
630 | (void) fclose(f); |
---|
631 | |
---|
632 | return 0; |
---|
633 | } |
---|
634 | |
---|
635 | /* Save a copy of the command-line options. */ |
---|
636 | void |
---|
637 | save_args(argc, argv) |
---|
638 | int argc; |
---|
639 | char *argv[]; |
---|
640 | { |
---|
641 | int i; |
---|
642 | int len = 0; |
---|
643 | |
---|
644 | for (i = 0; i < argc; i++) |
---|
645 | len += strlen(argv[i]) + 1; |
---|
646 | xcmd = XtMalloc(len + 1); |
---|
647 | xargv = (char **)XtMalloc((argc + 1) * sizeof(char *)); |
---|
648 | len = 0; |
---|
649 | for (i = 0; i < argc; i++) { |
---|
650 | xargv[i] = xcmd + len; |
---|
651 | (void) strcpy(xcmd + len, argv[i]); |
---|
652 | len += strlen(argv[i]) + 1; |
---|
653 | } |
---|
654 | xargv[i] = CN; |
---|
655 | *(xcmd + len) = '\0'; |
---|
656 | xargc = argc; |
---|
657 | } |
---|
658 | |
---|
659 | /* Merge in the options settings from a profile. */ |
---|
660 | void |
---|
661 | merge_profile(d) |
---|
662 | XrmDatabase *d; |
---|
663 | { |
---|
664 | char *fname; |
---|
665 | XrmDatabase dd; |
---|
666 | |
---|
667 | /* Open the file. */ |
---|
668 | if (getenv(NO_PROFILE_ENV) != CN) { |
---|
669 | profile_name = do_subst(DEFAULT_PROFILE, True, True); |
---|
670 | return; |
---|
671 | } |
---|
672 | fname = getenv(PROFILE_ENV); |
---|
673 | if (fname == CN || *fname == '\0') |
---|
674 | fname = DEFAULT_PROFILE; |
---|
675 | profile_name = do_subst(fname, True, True); |
---|
676 | |
---|
677 | /* Create a resource database from the file. */ |
---|
678 | dd = XrmGetFileDatabase(profile_name); |
---|
679 | if (dd == NULL) |
---|
680 | goto done; |
---|
681 | |
---|
682 | /* Merge in the profile options. */ |
---|
683 | XrmMergeDatabases(dd, d); |
---|
684 | |
---|
685 | /* Merge the saved command-line options back on top of those. */ |
---|
686 | dd = NULL; |
---|
687 | XrmParseCommand(&dd, options, num_options, programname, &xargc, xargv); |
---|
688 | XrmMergeDatabases(dd, d); |
---|
689 | |
---|
690 | done: |
---|
691 | /* Free the saved command-line options. */ |
---|
692 | XtFree(xcmd); |
---|
693 | xcmd = CN; |
---|
694 | XtFree((char *)xargv); |
---|
695 | xargv = (char **)NULL; |
---|
696 | } |
---|