~ubuntu-branches/ubuntu/karmic/x11-xserver-utils/karmic

« back to all changes in this revision

Viewing changes to xrdb/xrdb.c

  • Committer: Bazaar Package Importer
  • Author(s): Brice Goglin, Julien Cristau, Brice Goglin
  • Date: 2007-08-17 09:58:34 UTC
  • Revision ID: james.westby@ubuntu.com-20070817095834-ywge2nyzj1s3rqnd
Tags: 7.3+1
[ Julien Cristau ]
* iceauth 1.0.2.
  + removes blank line in the manpage (closes: #25285).
* xmodmap 1.0.3.
  + manpage updated to state that -pm is the default (closes: #236198)
* xgamma 1.0.2.
  + the manpage now explains how to print the gamma value more clearly
    (closes: #296021).
* xsetroot 1.0.2.
* xrdb 1.0.4.
  + fixes manpage typo (closes: #276286).
* Add upstream URL to debian/copyright, and update it from xgamma's COPYING
  file.

[ Brice Goglin ]
* Add menu entries for xrefresh and xvidtune.
* sessreg 1.0.3.
* xset 1.0.3.
* Add myself to Uploaders, and remove Branden with his permission.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * xrdb - X resource manager database utility
 
3
 *
 
4
 * $Xorg: xrdb.c,v 1.6 2000/08/17 19:54:56 cpqbld Exp $
 
5
 * $XdotOrg: app/xrdb/xrdb.c,v 1.5 2006/04/03 18:23:14 alanc Exp $
 
6
 */
 
7
 
 
8
/*
 
9
 *                        COPYRIGHT 1987, 1991
 
10
 *                 DIGITAL EQUIPMENT CORPORATION
 
11
 *                     MAYNARD, MASSACHUSETTS
 
12
 *                 MASSACHUSETTS INSTITUTE OF TECHNOLOGY
 
13
 *                     CAMBRIDGE, MASSACHUSETTS
 
14
 *                      ALL RIGHTS RESERVED.
 
15
 *
 
16
 * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
 
17
 * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
 
18
 * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
 
19
 * ANY PURPOSE.  IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
 
20
 *
 
21
 * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
 
22
 * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
 
23
 * SET FORTH ABOVE.
 
24
 *
 
25
 *
 
26
 * Permission to use, copy, modify, and distribute this software and its
 
27
 * documentation for any purpose and without fee is hereby granted, provided
 
28
 * that the above copyright notice appear in all copies and that both that
 
29
 * copyright notice and this permission notice appear in supporting
 
30
 * documentation, and that the name of Digital Equipment Corporation not be
 
31
 * used in advertising or publicity pertaining to distribution of the software
 
32
 * without specific, written prior permission.
 
33
 */
 
34
/* $XFree86: xc/programs/xrdb/xrdb.c,v 3.16tsi Exp $ */
 
35
 
 
36
/*
 
37
 * this program is used to load, or dump the resource manager database
 
38
 * in the server.
 
39
 *
 
40
 * Original Author: Jim Gettys, August 28, 1987
 
41
 * Extensively Modified: Phil Karlton, January 5, 1987
 
42
 * Modified a Bunch More: Bob Scheifler, February, 1991
 
43
 */
 
44
 
 
45
#ifdef HAVE_CONFIG_H
 
46
#include <config.h>
 
47
#endif
 
48
 
 
49
#include <X11/Xlib.h>
 
50
#include <X11/Xutil.h>
 
51
#include <X11/Xatom.h>
 
52
#include <X11/Xos.h>
 
53
#include <X11/Xmu/SysUtil.h>
 
54
#include <stdio.h>
 
55
#include <ctype.h>
 
56
#include <errno.h>
 
57
#include <stdlib.h>
 
58
#include <stdarg.h>
 
59
 
 
60
#ifdef NEED_SYS_PARAM_H
 
61
# include <sys/param.h>         /* defines MAXHOSTNAMELEN on BSD & Linux */
 
62
#endif
 
63
 
 
64
#ifdef NEED_NETDB_H
 
65
# include <netdb.h>             /* defines MAXHOSTNAMELEN on Solaris */
 
66
#endif
 
67
 
 
68
#define SCREEN_RESOURCES "SCREEN_RESOURCES"
 
69
 
 
70
#ifndef CPP
 
71
#ifdef __UNIXOS2__
 
72
/* expected to be in path */
 
73
#define CPP "cpp"
 
74
#else
 
75
#define CPP "/usr/lib/cpp"
 
76
#endif /* __UNIXOS2__ */
 
77
#endif /* CPP */
 
78
 
 
79
#define INIT_BUFFER_SIZE 10000
 
80
#define INIT_ENTRY_SIZE 500
 
81
 
 
82
#define RALL 0
 
83
#define RGLOBAL 1
 
84
#define RSCREEN 2
 
85
#define RSCREENS 3
 
86
 
 
87
#define OPSYMBOLS 0
 
88
#define OPQUERY 1
 
89
#define OPREMOVE 2
 
90
#define OPEDIT 3
 
91
#define OPLOAD 4
 
92
#define OPMERGE 5
 
93
#define OPOVERRIDE 6
 
94
 
 
95
#define RESOURCE_PROPERTY_NAME "RESOURCE_MANAGER"
 
96
#define BACKUP_SUFFIX ".bak"            /* for editting */
 
97
 
 
98
typedef struct _Entry {
 
99
    char *tag, *value;
 
100
    int lineno;
 
101
    Bool usable;
 
102
} Entry;
 
103
typedef struct _Buffer {
 
104
    char *buff;
 
105
    int  room, used;
 
106
} Buffer;
 
107
typedef struct _Entries {
 
108
    Entry *entry;
 
109
    int   room, used;
 
110
} Entries;
 
111
 
 
112
/* dynamically allocated strings */
 
113
#define CHUNK_SIZE 4096
 
114
typedef struct _String {
 
115
    char *val;
 
116
    int room, used;
 
117
} String;
 
118
 
 
119
char *ProgramName;
 
120
Bool quiet = False;
 
121
char tmpname[32];
 
122
char *filename = NULL;
 
123
#ifdef PATHETICCPP
 
124
Bool need_real_defines = False;
 
125
char tmpname2[32];
 
126
#ifdef WIN32
 
127
char tmpname3[32];
 
128
#endif
 
129
#endif
 
130
int oper = OPLOAD;
 
131
char *editFile = NULL;
 
132
char *cpp_program = CPP;
 
133
char *backup_suffix = BACKUP_SUFFIX;
 
134
Bool dont_execute = False;
 
135
String defines;
 
136
int defines_base;
 
137
#define MAX_CMD_DEFINES 512
 
138
char *cmd_defines[MAX_CMD_DEFINES];
 
139
int num_cmd_defines = 0;
 
140
String includes;
 
141
Display *dpy;
 
142
Buffer buffer;
 
143
Entries newDB;
 
144
 
 
145
static void fatal(char *, ...);
 
146
static void addstring ( String *arg, const char *s );
 
147
static void FormatEntries ( Buffer *buffer, Entries *entries );
 
148
static void StoreProperty ( Display *dpy, Window root, Atom res_prop );
 
149
static void Process ( int scrno, Bool doScreen, Bool execute );
 
150
static void ShuffleEntries ( Entries *db, Entries *dbs, int num );
 
151
static void ReProcess ( int scrno, Bool doScreen );
 
152
 
 
153
static void 
 
154
InitBuffer(Buffer *b)
 
155
{
 
156
    b->room = INIT_BUFFER_SIZE;
 
157
    b->used = 0;
 
158
    b->buff = (char *)malloc(INIT_BUFFER_SIZE*sizeof(char));
 
159
}
 
160
 
 
161
#ifdef notyet
 
162
static void 
 
163
FreeBuffer(Buffer *b)
 
164
{
 
165
    free(b->buff);
 
166
}
 
167
#endif
 
168
 
 
169
static void 
 
170
AppendToBuffer(Buffer *b, char *str, int len)
 
171
{
 
172
    while (b->used + len > b->room) {
 
173
        b->buff = (char *)realloc(b->buff, 2*b->room*(sizeof(char)));
 
174
        b->room *= 2;
 
175
    }
 
176
    strncpy(b->buff + b->used, str, len);
 
177
    b->used += len;
 
178
}
 
179
 
 
180
static void 
 
181
InitEntries(Entries *e)
 
182
{
 
183
    e->room = INIT_ENTRY_SIZE;
 
184
    e->used = 0;
 
185
    e->entry = (Entry *)malloc(INIT_ENTRY_SIZE*sizeof(Entry));
 
186
}
 
187
 
 
188
static void 
 
189
FreeEntries(Entries *e)
 
190
{
 
191
    register int i;
 
192
 
 
193
    for (i = 0; i < e->used; i++) {
 
194
        if (e->entry[i].usable) {
 
195
            free(e->entry[i].tag);
 
196
            free(e->entry[i].value);
 
197
        }
 
198
    }
 
199
    free((char *)e->entry);
 
200
}
 
201
 
 
202
static void 
 
203
AddEntry(Entries *e, Entry *entry)
 
204
{
 
205
    register int n;
 
206
 
 
207
    for (n = 0; n < e->used; n++) {
 
208
        if (!strcmp(e->entry[n].tag, entry->tag)) {
 
209
            /* overwrite old entry */
 
210
            if (e->entry[n].lineno && !quiet) {
 
211
                fprintf (stderr, 
 
212
                         "%s:  \"%s\" on line %d overrides entry on line %d\n",
 
213
                         ProgramName, entry->tag, entry->lineno, 
 
214
                         e->entry[n].lineno);
 
215
            }
 
216
            free(e->entry[n].tag);
 
217
            free(e->entry[n].value);
 
218
            entry->usable = True;
 
219
            e->entry[n] = *entry;
 
220
            return;  /* ok to leave, now there's only one of each tag in db */
 
221
        }
 
222
    }
 
223
 
 
224
    if (e->used == e->room) {
 
225
        e->entry = (Entry *)realloc((char *)e->entry,
 
226
                                    2*e->room*(sizeof(Entry)));
 
227
        e->room *= 2;
 
228
    }
 
229
    entry->usable = True;
 
230
    e->entry[e->used++] = *entry;
 
231
}
 
232
 
 
233
 
 
234
static int 
 
235
CompareEntries(const void *e1, const void *e2)
 
236
{
 
237
    return strcmp(((Entry *)e1)->tag, ((Entry *)e2)->tag);
 
238
}
 
239
 
 
240
static void 
 
241
AppendEntryToBuffer(Buffer *buffer, Entry *entry)
 
242
{
 
243
    AppendToBuffer(buffer, entry->tag, strlen(entry->tag));
 
244
    AppendToBuffer(buffer, ":\t", 2);
 
245
    AppendToBuffer(buffer, entry->value, strlen(entry->value));
 
246
    AppendToBuffer(buffer, "\n", 1);
 
247
}
 
248
 
 
249
/*
 
250
 * Return the position of the first unescaped occurrence of dest in string.
 
251
 * If lines is non-null, return the number of newlines skipped over.
 
252
 */
 
253
static char *
 
254
FindFirst(char *string, char dest, int *lines)
 
255
{
 
256
    if (lines)
 
257
        *lines = 0;
 
258
    for (;;) {
 
259
        if (*string == '\0')
 
260
            return NULL;
 
261
        if (*string == '\\') {
 
262
            if (*++string == '\0')
 
263
                return NULL;
 
264
        } else if (*string == dest)
 
265
            return string;
 
266
        if (*string == '\n'  &&  lines)
 
267
            (*lines)++;
 
268
        string++;
 
269
    }
 
270
}
 
271
 
 
272
static void 
 
273
GetEntries(Entries *entries, Buffer *buff, int bequiet)
 
274
{
 
275
    register char *line, *colon, *temp, *str;
 
276
    Entry entry;
 
277
    register int length;
 
278
    int lineno = 0;
 
279
    int lines_skipped;
 
280
 
 
281
    str = buff->buff;
 
282
    if (!str) return;
 
283
    for ( ; str < buff->buff + buff->used;
 
284
          str = line + 1, lineno += lines_skipped) {
 
285
        line = FindFirst(str, '\n', &lines_skipped);
 
286
        lineno++;
 
287
        if (!line)
 
288
            line = buff->buff + buff->used;
 
289
        if (*str == '!')
 
290
            continue;
 
291
        if (*str == '\n')
 
292
            continue;
 
293
        if (!bequiet && *str == '#') {
 
294
            int dummy;
 
295
            if (sscanf (str, "# %d", &dummy) == 1 ||
 
296
                sscanf (str, "# line %d", &dummy) == 1)
 
297
                lineno = dummy - 1;
 
298
            continue;
 
299
        }
 
300
        for (temp = str; 
 
301
             *temp && *temp != '\n' && isascii(*temp) && isspace(*temp); 
 
302
             temp++) ;
 
303
        if (!*temp || *temp == '\n') continue;
 
304
 
 
305
        colon = FindFirst(str, ':', NULL);
 
306
        if (!colon || colon > line) {
 
307
            if (!bequiet && !quiet)
 
308
                fprintf (stderr, 
 
309
                         "%s: colon missing on line %d, ignoring line\n",
 
310
                         ProgramName, lineno);
 
311
            continue;
 
312
        }
 
313
 
 
314
        /* strip leading and trailing blanks from name and store result */
 
315
        while (*str == ' ' || *str == '\t')
 
316
            str++;
 
317
        length = colon - str;
 
318
        while (length && (str[length-1] == ' ' || str[length-1] == '\t'))
 
319
            length--;
 
320
        temp = (char *)malloc(length + 1);
 
321
        strncpy(temp, str, length);
 
322
        temp[length] = '\0';
 
323
        entry.tag = temp;
 
324
 
 
325
        /* strip leading and trailing blanks from value and store result */
 
326
        colon++;
 
327
        while (*colon == ' ' || *colon == '\t')
 
328
            colon++;
 
329
        length = line - colon;
 
330
        temp = (char *)malloc(length + 1);
 
331
        strncpy(temp, colon, length);
 
332
        temp[length] = '\0';
 
333
        entry.value = temp;
 
334
        entry.lineno = bequiet ? 0 : lineno;
 
335
 
 
336
        AddEntry(entries, &entry);
 
337
    }
 
338
}
 
339
 
 
340
static void
 
341
GetEntriesString(Entries *entries, char *str)
 
342
{
 
343
    Buffer buff;
 
344
 
 
345
    if (str && *str) {
 
346
        buff.buff = str;
 
347
        buff.used = strlen(str);
 
348
        GetEntries(entries, &buff, 1);
 
349
    }
 
350
}
 
351
 
 
352
static void 
 
353
ReadFile(Buffer *buffer, FILE *input)
 
354
{
 
355
             char       buf[BUFSIZ + 1];
 
356
    register int        bytes;
 
357
 
 
358
    buffer->used = 0;
 
359
    while (!feof(input) && (bytes = fread(buf, 1, BUFSIZ, input)) > 0) {
 
360
#ifdef WIN32
 
361
        char *p;
 
362
        buf[bytes] = '\0';
 
363
        for (p = buf; p = strchr(p, '\r'); ) {
 
364
            if (p[-1] == '\\' && p[1] == '\n') {
 
365
                bytes -= 3;
 
366
                strcpy(p - 1, p + 2);
 
367
            }
 
368
        }
 
369
#endif
 
370
        AppendToBuffer(buffer, buf, bytes);
 
371
    }
 
372
    AppendToBuffer(buffer, "", 1);
 
373
}
 
374
 
 
375
static void
 
376
AddDef(String *buff, char *title, char *value)
 
377
{
 
378
#ifdef PATHETICCPP
 
379
    if (need_real_defines) {
 
380
        addstring(buff, "\n#define ");
 
381
        addstring(buff, title);
 
382
        if (value && (value[0] != '\0')) {
 
383
            addstring(buff, " ");
 
384
            addstring(buff, value);
 
385
        }
 
386
        return;
 
387
    }
 
388
#endif
 
389
    if (buff->used) {
 
390
        if (oper == OPSYMBOLS)
 
391
            addstring(buff, "\n-D");
 
392
        else
 
393
            addstring(buff, " -D");
 
394
    } else
 
395
        addstring(buff, "-D");
 
396
    addstring(buff, title);
 
397
    if (value && (value[0] != '\0')) {
 
398
        addstring(buff, "=");
 
399
        addstring(buff, value);
 
400
    }
 
401
}
 
402
 
 
403
static void
 
404
AddDefQ(String *buff, char *title, char *value)
 
405
{
 
406
#ifdef PATHETICCPP
 
407
    if (need_real_defines)
 
408
        AddDef(buff, title, value);
 
409
    else
 
410
#endif
 
411
    if (value && (value[0] != '\0')) {
 
412
        AddDef(buff, title, "\"");
 
413
        addstring(buff, value);
 
414
        addstring(buff, "\"");
 
415
    } else
 
416
        AddDef(buff, title, NULL);
 
417
}
 
418
 
 
419
static void
 
420
AddNum(String *buff, char *title, int value)
 
421
{
 
422
    char num[20];
 
423
    snprintf(num, sizeof(num), "%d", value);
 
424
    AddDef(buff, title, num);
 
425
}
 
426
 
 
427
static void
 
428
AddSimpleDef(String *buff, char *title)
 
429
{
 
430
    AddDef(buff, title, (char *)NULL);
 
431
}
 
432
 
 
433
static void
 
434
AddDefTok(String *buff, char *prefix, char *title)
 
435
{
 
436
    char *s;
 
437
    char name[512];
 
438
    char c;
 
439
 
 
440
    snprintf(name, sizeof(name), "%s%s", prefix, title);
 
441
    for (s = name; (c = *s); s++) {
 
442
        if (!isalpha(c) && !isdigit(c) && c != '_')
 
443
            *s = '_';
 
444
    }
 
445
    AddSimpleDef(buff, name);
 
446
}
 
447
 
 
448
static void
 
449
AddUndef(String *buff, char *title)
 
450
{
 
451
#ifdef PATHETICCPP
 
452
    if (need_real_defines) {
 
453
        addstring(buff, "\n#undef ");
 
454
        addstring(buff, title);
 
455
        return;
 
456
    }
 
457
#endif
 
458
    if (buff->used) {
 
459
        if (oper == OPSYMBOLS)
 
460
            addstring(buff, "\n-U");
 
461
        else
 
462
            addstring(buff, " -U");
 
463
    } else
 
464
        addstring(buff, "-U");
 
465
    addstring(buff, title);
 
466
}
 
467
 
 
468
static void 
 
469
DoCmdDefines(String *buff)
 
470
{
 
471
    int i;
 
472
    char *arg, *val;
 
473
 
 
474
    for (i = 0; i < num_cmd_defines; i++) {
 
475
        arg = cmd_defines[i];
 
476
        if (arg[1] == 'D') {
 
477
            val = strchr(arg, '=');
 
478
            if (val) {
 
479
                *val = '\0';
 
480
                AddDefQ(buff, arg + 2, val + 1);
 
481
                *val = '=';
 
482
            } else
 
483
                AddSimpleDef(buff, arg + 2);
 
484
        } else
 
485
            AddUndef(buff, arg + 2);
 
486
    }
 
487
}
 
488
 
 
489
static int 
 
490
Resolution(int pixels, int mm)
 
491
{
 
492
    return ((pixels * 100000 / mm) + 50) / 100;
 
493
}
 
494
 
 
495
 
 
496
static void
 
497
DoDisplayDefines(Display *display, String *defs, char *host)
 
498
{
 
499
#ifndef MAXHOSTNAMELEN
 
500
#define MAXHOSTNAMELEN 255
 
501
#endif
 
502
    char client[MAXHOSTNAMELEN], server[MAXHOSTNAMELEN], *colon;
 
503
    char **extnames;
 
504
    int n;
 
505
    
 
506
    XmuGetHostname(client, MAXHOSTNAMELEN);
 
507
    strncpy(server, XDisplayName(host), sizeof(server));
 
508
    server[sizeof(server) - 1] = '\0';
 
509
    /* search for final colon to skip over any embedded colons in IPv6
 
510
       numeric address forms */
 
511
    colon = strrchr(server, ':');
 
512
    n = 0;
 
513
    if (colon) {
 
514
        /* remove extra colon if there are exactly two, since it indicates 
 
515
           DECnet.  Three colons is an IPv6 address ending in :: though. */
 
516
        if ((colon > server) && (*(colon-1) == ':') &&
 
517
          ( ((colon - 1) == server) || (*(colon-2) != ':') ) ) {
 
518
            *(colon-1) = ':';
 
519
        }
 
520
        *colon++ = '\0';
 
521
        sscanf(colon, "%d", &n);
 
522
    }
 
523
    if (!*server || !strcmp(server, "unix") || !strcmp(server, "localhost"))
 
524
        strcpy(server, client);
 
525
    AddDef(defs, "HOST", server); /* R3 compatibility */
 
526
    AddDef(defs, "SERVERHOST", server);
 
527
    AddDefTok(defs, "SRVR_", server);
 
528
    AddNum(defs, "DISPLAY_NUM", n);
 
529
    AddDef(defs, "CLIENTHOST", client);
 
530
    AddDefTok(defs, "CLNT_", client);
 
531
    AddNum(defs, "VERSION", ProtocolVersion(display));
 
532
    AddNum(defs, "REVISION", ProtocolRevision(display));
 
533
    AddDefQ(defs, "VENDOR", ServerVendor(display));
 
534
    AddDefTok(defs, "VNDR_", ServerVendor(display));
 
535
    AddNum(defs, "RELEASE", VendorRelease(display));
 
536
    AddNum(defs, "NUM_SCREENS", ScreenCount(display));
 
537
    extnames = XListExtensions(display, &n);
 
538
    while (--n >= 0)
 
539
        AddDefTok(defs, "EXT_", extnames[n]);
 
540
    XFreeExtensionList(extnames);
 
541
}
 
542
 
 
543
char *ClassNames[] = {
 
544
    "StaticGray",
 
545
    "GrayScale",
 
546
    "StaticColor",
 
547
    "PseudoColor",
 
548
    "TrueColor",
 
549
    "DirectColor"
 
550
};
 
551
 
 
552
static void
 
553
DoScreenDefines(Display *display, int scrno, String *defs)
 
554
{
 
555
    Screen *screen;
 
556
    Visual *visual;
 
557
    XVisualInfo vinfo, *vinfos;
 
558
    int nv, i, j;
 
559
    char name[50];
 
560
    
 
561
    screen = ScreenOfDisplay(display, scrno);
 
562
    visual = DefaultVisualOfScreen(screen);
 
563
    vinfo.screen = scrno;
 
564
    vinfos = XGetVisualInfo(display, VisualScreenMask, &vinfo, &nv);
 
565
    AddNum(defs, "SCREEN_NUM", scrno);
 
566
    AddNum(defs, "WIDTH", screen->width);
 
567
    AddNum(defs, "HEIGHT", screen->height);
 
568
    AddNum(defs, "X_RESOLUTION", Resolution(screen->width,screen->mwidth));
 
569
    AddNum(defs, "Y_RESOLUTION", Resolution(screen->height,screen->mheight));
 
570
    AddNum(defs, "PLANES", DisplayPlanes(display, scrno));
 
571
    AddNum(defs, "BITS_PER_RGB", visual->bits_per_rgb);
 
572
    AddDef(defs, "CLASS", ClassNames[visual->class]);
 
573
    snprintf(name, sizeof(name), "CLASS_%s", ClassNames[visual->class]);
 
574
    AddNum(defs, name, (int)visual->visualid);
 
575
    switch(visual->class) {
 
576
        case StaticColor:
 
577
        case PseudoColor:
 
578
        case TrueColor:
 
579
        case DirectColor:
 
580
            AddSimpleDef(defs, "COLOR");
 
581
            break;
 
582
    }
 
583
    for (i = 0; i < nv; i++) {
 
584
        for (j = i; --j >= 0; ) {
 
585
            if (vinfos[j].class == vinfos[i].class &&
 
586
                vinfos[j].depth == vinfos[i].depth)
 
587
                break;
 
588
        }
 
589
        if (j < 0) {
 
590
            snprintf(name, sizeof(name), "CLASS_%s_%d",
 
591
                    ClassNames[vinfos[i].class], vinfos[i].depth);
 
592
            AddNum(defs, name, (int)vinfos[i].visualid);
 
593
        }
 
594
    }
 
595
    XFree((char *)vinfos);
 
596
}
 
597
 
 
598
static Entry *
 
599
FindEntry(Entries *db, Buffer  *b)
 
600
{
 
601
    int i;
 
602
    register Entry *e;
 
603
    Entries phoney;
 
604
    Entry entry;
 
605
 
 
606
    entry.usable = False;
 
607
    entry.tag = NULL;
 
608
    entry.value = NULL;
 
609
    phoney.used = 0;
 
610
    phoney.room = 1;
 
611
    phoney.entry = &entry;
 
612
    GetEntries(&phoney, b, 1);
 
613
    if (phoney.used < 1)
 
614
        return NULL;
 
615
    for (i = 0; i < db->used; i++) {
 
616
        e = &db->entry[i];
 
617
        if (!e->usable)
 
618
            continue;
 
619
        if (strcmp(e->tag, entry.tag))
 
620
            continue;
 
621
        e->usable = False;
 
622
        if (strcmp(e->value, entry.value))
 
623
            return e;
 
624
        return NULL;
 
625
    }
 
626
    return NULL;
 
627
}
 
628
 
 
629
static void 
 
630
EditFile(Entries *new, FILE *in, FILE *out)
 
631
{
 
632
    Buffer b;
 
633
    char buff[BUFSIZ];
 
634
    register Entry *e;
 
635
    register char *c;
 
636
    int i;
 
637
 
 
638
    InitBuffer(&b);
 
639
    while (in) {
 
640
        b.used = 0;
 
641
        while (1) {
 
642
            buff[0] ='\0';
 
643
            if (!fgets(buff, BUFSIZ, in))
 
644
                goto cleanup;
 
645
            AppendToBuffer(&b, buff, strlen(buff));
 
646
            c = &b.buff[b.used - 1];
 
647
            if ((*(c--) == '\n') && (b.used == 1 || *c != '\\'))
 
648
                break;
 
649
        }
 
650
        if ((e = FindEntry(new, &b)))
 
651
            fprintf(out, "%s:\t%s\n", e->tag, e->value);
 
652
        else
 
653
            fwrite(b.buff, 1, b.used, out);
 
654
    }
 
655
cleanup:
 
656
    for (i = 0; i < new->used; i++) {
 
657
        e = &new->entry[i];
 
658
        if (e->usable)
 
659
            fprintf(out, "%s:\t%s\n", e->tag, e->value);
 
660
    }
 
661
}
 
662
 
 
663
static void 
 
664
Syntax (void)
 
665
{
 
666
    fprintf (stderr, 
 
667
             "usage:  %s [-options ...] [filename]\n\n",
 
668
             ProgramName);
 
669
    fprintf (stderr, 
 
670
             "where options include:\n");
 
671
    fprintf (stderr, 
 
672
             " -display host:dpy   display to use\n");
 
673
    fprintf (stderr, 
 
674
             " -all                do all resources [default]\n");
 
675
    fprintf (stderr, 
 
676
             " -global             do screen-independent resources\n");
 
677
    fprintf (stderr, 
 
678
             " -screen             do screen-specific resources for one screen\n");
 
679
    fprintf (stderr, 
 
680
             " -screens            do screen-specific resources for all screens\n");
 
681
    fprintf (stderr,
 
682
             " -n                  show but don't do changes\n");
 
683
    fprintf (stderr, 
 
684
             " -cpp filename       preprocessor to use [%s]\n",
 
685
             CPP);
 
686
    fprintf (stderr, 
 
687
             " -nocpp              do not use a preprocessor\n");
 
688
    fprintf (stderr, 
 
689
             " -query              query resources\n");
 
690
    fprintf (stderr,
 
691
             " -load               load resources from file [default]\n");
 
692
    fprintf (stderr,
 
693
             " -override           add in resources from file\n");
 
694
    fprintf (stderr, 
 
695
             " -merge              merge resources from file & sort\n");
 
696
    fprintf (stderr, 
 
697
             " -edit filename      edit resources into file\n");
 
698
    fprintf (stderr, 
 
699
             " -backup string      backup suffix for -edit [%s]\n",
 
700
             BACKUP_SUFFIX);
 
701
    fprintf (stderr, 
 
702
             " -symbols            show preprocessor symbols\n");
 
703
    fprintf (stderr, 
 
704
             " -remove             remove resources\n");
 
705
    fprintf (stderr, 
 
706
             " -retain             avoid server reset (avoid using this)\n");
 
707
    fprintf (stderr,
 
708
             " -quiet              don't warn about duplicates\n");
 
709
    fprintf (stderr, 
 
710
             " -Dname[=value], -Uname, -Idirectory    %s\n",
 
711
             "passed to preprocessor");
 
712
    fprintf (stderr, 
 
713
             "\n");
 
714
    fprintf (stderr,
 
715
             "A - or no input filename represents stdin.\n");  
 
716
    exit (1);
 
717
}
 
718
 
 
719
/*
 
720
 * The following is a hack until XrmParseCommand is ready.  It determines
 
721
 * whether or not the given string is an abbreviation of the arg.
 
722
 */
 
723
 
 
724
static Bool 
 
725
isabbreviation(char *arg, char *s, int minslen)
 
726
{
 
727
    int arglen;
 
728
    int slen;
 
729
 
 
730
    /* exact match */
 
731
    if (!strcmp (arg, s)) return (True);
 
732
 
 
733
    arglen = strlen (arg);
 
734
    slen = strlen (s);
 
735
 
 
736
    /* too long or too short */
 
737
    if (slen >= arglen || slen < minslen) return (False);
 
738
 
 
739
    /* abbreviation */
 
740
    if (strncmp (arg, s, slen) == 0) return (True);
 
741
 
 
742
    /* bad */
 
743
    return (False);
 
744
}
 
745
 
 
746
static void
 
747
addstring(String *arg, const char *s)
 
748
{
 
749
    if(arg->used + strlen(s) + 1 >= arg->room) {
 
750
        if(arg->val)
 
751
            arg->val = (char *)realloc(arg->val, arg->room + CHUNK_SIZE);
 
752
        else
 
753
            arg->val = (char *)malloc(arg->room + CHUNK_SIZE);      
 
754
        if(arg->val == NULL)
 
755
            fatal("%s: Not enough memory\n", ProgramName);
 
756
        arg->room += CHUNK_SIZE;
 
757
    }
 
758
    if(arg->used)
 
759
        strcat(arg->val, s);
 
760
    else
 
761
        strcpy(arg->val, s);
 
762
    arg->used += strlen(s);
 
763
}   
 
764
 
 
765
 
 
766
int
 
767
main(int argc, char *argv[])
 
768
{
 
769
    int i;
 
770
    char *displayname = NULL;
 
771
    int whichResources = RALL;
 
772
    int retainProp = 0;
 
773
    FILE *fp = NULL;
 
774
    Bool need_newline;
 
775
 
 
776
    ProgramName = argv[0];
 
777
 
 
778
    defines.room = defines.used = includes.room = includes.used = 0;
 
779
 
 
780
    /* initialize the includes String struct */
 
781
    addstring(&includes, "");
 
782
 
 
783
    /* needs to be replaced with XrmParseCommand */
 
784
 
 
785
    for (i = 1; i < argc; i++) {
 
786
        char *arg = argv[i];
 
787
 
 
788
        if (arg[0] == '-') {
 
789
            if (arg[1] == '\0') {
 
790
                filename = NULL;
 
791
                continue;
 
792
            } else if (isabbreviation ("-help", arg, 2)) {
 
793
                Syntax ();
 
794
                /* doesn't return */
 
795
            } else if (isabbreviation ("-display", arg, 2)) {
 
796
                if (++i >= argc) Syntax ();
 
797
                displayname = argv[i];
 
798
                continue;
 
799
            } else if (isabbreviation ("-geometry", arg, 3)) {
 
800
                if (++i >= argc) Syntax ();
 
801
                /* ignore geometry */
 
802
                continue;
 
803
            } else if (isabbreviation ("-cpp", arg, 2)) {
 
804
                if (++i >= argc) Syntax ();
 
805
                cpp_program = argv[i];
 
806
                continue;
 
807
            } else if (!strcmp ("-n", arg)) {
 
808
                dont_execute = True;
 
809
                continue;
 
810
            } else if (isabbreviation ("-nocpp", arg, 3)) {
 
811
                cpp_program = NULL;
 
812
                continue;
 
813
            } else if (isabbreviation ("-query", arg, 2)) {
 
814
                oper = OPQUERY;
 
815
                continue;
 
816
            } else if (isabbreviation ("-load", arg, 2)) {
 
817
                oper = OPLOAD;
 
818
                continue;
 
819
            } else if (isabbreviation ("-merge", arg, 2)) {
 
820
                oper = OPMERGE;
 
821
                continue;
 
822
            } else if (isabbreviation ("-override", arg, 2)) {
 
823
                oper = OPOVERRIDE;
 
824
                continue;
 
825
            } else if (isabbreviation ("-symbols", arg, 3)) {
 
826
                oper = OPSYMBOLS;
 
827
                continue;
 
828
            } else if (isabbreviation ("-remove", arg, 4)) {
 
829
                oper = OPREMOVE;
 
830
                continue;
 
831
            } else if (isabbreviation ("-edit", arg, 2)) {
 
832
                if (++i >= argc) Syntax ();
 
833
                oper = OPEDIT;
 
834
                editFile = argv[i];
 
835
                continue;
 
836
            } else if (isabbreviation ("-backup", arg, 2)) {
 
837
                if (++i >= argc) Syntax ();
 
838
                backup_suffix = argv[i];
 
839
                continue;
 
840
            } else if (isabbreviation ("-all", arg, 2)) {
 
841
                whichResources = RALL;
 
842
                continue;
 
843
            } else if (isabbreviation ("-global", arg, 3)) {
 
844
                whichResources = RGLOBAL;
 
845
                continue;
 
846
            } else if (isabbreviation ("-screen", arg, 3)) {
 
847
                whichResources = RSCREEN;
 
848
                continue;
 
849
            } else if (!strcmp ("-screens", arg)) {
 
850
                whichResources = RSCREENS;
 
851
                continue;
 
852
            } else if (isabbreviation ("-retain", arg, 4)) {
 
853
                retainProp = 1;
 
854
                continue;
 
855
            } else if (isabbreviation ("-quiet", arg, 2)) {
 
856
                quiet = True;
 
857
                continue;
 
858
            } else if (arg[1] == 'I') {
 
859
                addstring(&includes, " ");
 
860
                addstring(&includes, arg);
 
861
                continue;
 
862
            } else if (arg[1] == 'U' || arg[1] == 'D') {
 
863
                if (num_cmd_defines < MAX_CMD_DEFINES) {
 
864
                    cmd_defines[num_cmd_defines++] = arg;
 
865
                } else {
 
866
                    fatal("%s: Too many -U/-D arguments\n", ProgramName);
 
867
                }
 
868
                continue;
 
869
            }
 
870
            Syntax ();
 
871
        } else if (arg[0] == '=') 
 
872
            continue;
 
873
        else
 
874
            filename = arg;
 
875
    }                                                   /* end for */
 
876
 
 
877
#ifndef WIN32
 
878
    while ((i = open("/dev/null", O_RDONLY)) < 3)
 
879
        ; /* make sure later freopen won't clobber things */
 
880
    (void) close(i);
 
881
#endif
 
882
    /* Open display  */
 
883
    if (!(dpy = XOpenDisplay (displayname)))
 
884
        fatal("%s: Can't open display '%s'\n", ProgramName,
 
885
                 XDisplayName (displayname));
 
886
 
 
887
    if (whichResources == RALL && ScreenCount(dpy) == 1)
 
888
        whichResources = RGLOBAL;
 
889
 
 
890
#ifdef PATHETICCPP
 
891
    if (cpp_program &&
 
892
        (oper == OPLOAD || oper == OPMERGE || oper == OPOVERRIDE)) {
 
893
        need_real_defines = True;
 
894
#ifdef WIN32
 
895
        strcpy(tmpname2, "xrdbD_XXXXXX");
 
896
        strcpy(tmpname3, "\\temp\\xrdbD_XXXXXX");
 
897
#else
 
898
#ifdef __UNIXOS2__
 
899
        { char *tmpdir=getenv("TMP");
 
900
          if (!tmpdir) tmpdir="/";
 
901
          sprintf(tmpname2, "%s/xrdbD_XXXXXX",tmpdir);
 
902
        }
 
903
#else
 
904
        strcpy(tmpname2, "/tmp/xrdbD_XXXXXX");
 
905
#endif
 
906
#endif
 
907
        (void) mktemp(tmpname2);
 
908
    }
 
909
#endif
 
910
 
 
911
    if (!filename &&
 
912
#ifdef PATHETICCPP
 
913
        need_real_defines
 
914
#else
 
915
        (oper == OPLOAD || oper == OPMERGE || oper == OPOVERRIDE) &&
 
916
        (whichResources == RALL || whichResources == RSCREENS)
 
917
#endif
 
918
        ) {
 
919
        char inputbuf[1024];
 
920
#ifdef WIN32
 
921
        strcpy(tmpname, "\\temp\\xrdb_XXXXXX");
 
922
#else
 
923
#ifdef __UNIXOS2__
 
924
        { char *tmpdir=getenv("TMP");
 
925
          if (!tmpdir) tmpdir="/";
 
926
          sprintf(tmpname, "%s/xrdb_XXXXXX",tmpdir);
 
927
        }
 
928
#else
 
929
        strcpy(tmpname, "/tmp/xrdb_XXXXXX");
 
930
#endif
 
931
#endif
 
932
#ifndef HAS_MKSTEMP
 
933
        (void) mktemp(tmpname);
 
934
        filename = tmpname;
 
935
        fp = fopen(filename, "w");
 
936
#else
 
937
        {
 
938
        int fd = mkstemp(tmpname);
 
939
        filename = tmpname;
 
940
        fp = fdopen(fd, "w");
 
941
        }
 
942
#endif /* MKSTEMP */
 
943
        if (!fp)
 
944
            fatal("%s: Failed to open temp file: %s\n", ProgramName,
 
945
                  filename);
 
946
        while (fgets(inputbuf, sizeof(inputbuf), stdin) != NULL) 
 
947
            fputs(inputbuf, fp);
 
948
        fclose(fp);
 
949
    }
 
950
        
 
951
    DoDisplayDefines(dpy, &defines, displayname);
 
952
    defines_base = defines.used;
 
953
    need_newline = (oper == OPQUERY || oper == OPSYMBOLS ||
 
954
                    (dont_execute && oper != OPREMOVE));
 
955
    InitBuffer(&buffer);
 
956
    if (whichResources == RGLOBAL)
 
957
        Process(DefaultScreen(dpy), False, True);
 
958
    else if (whichResources == RSCREEN)
 
959
        Process(DefaultScreen(dpy), True, True);
 
960
    else if (whichResources == RSCREENS ||
 
961
             (oper != OPLOAD && oper != OPMERGE && oper != OPOVERRIDE)) {
 
962
        if (whichResources == RALL && oper != OPSYMBOLS) {
 
963
            if (need_newline)
 
964
                printf("! screen-independent resources\n");
 
965
            Process(0, False, True);
 
966
            if (need_newline)
 
967
                printf("\n");
 
968
        }
 
969
        for (i = 0; i < ScreenCount(dpy); i++) {
 
970
            if (need_newline) {
 
971
                if (oper == OPSYMBOLS)
 
972
                    printf("# screen %d symbols\n", i);
 
973
                else {
 
974
                    printf("! screen %d resources\n", i);
 
975
                    printf("#if SCREEN_NUM == %d\n", i);
 
976
                }
 
977
            }
 
978
            Process(i, True, True);
 
979
            if (need_newline) {
 
980
                if (oper != OPSYMBOLS)
 
981
                    printf("#endif\n");
 
982
                if (i+1 != ScreenCount(dpy))
 
983
                    printf("\n");
 
984
            }
 
985
        }
 
986
    }
 
987
    else {
 
988
        Entries *dbs;
 
989
 
 
990
        dbs = (Entries *)malloc(ScreenCount(dpy) * sizeof(Entries));
 
991
        for (i = 0; i < ScreenCount(dpy); i++) {
 
992
            Process(i, True, False);
 
993
            dbs[i] = newDB;
 
994
        }
 
995
        InitEntries(&newDB);
 
996
        if (oper == OPMERGE || oper == OPOVERRIDE)
 
997
            GetEntriesString(&newDB, XResourceManagerString(dpy));
 
998
        ShuffleEntries(&newDB, dbs, ScreenCount(dpy));
 
999
        if (need_newline)
 
1000
            printf("! screen-independent resources\n");
 
1001
        ReProcess(0, False);
 
1002
        if (need_newline)
 
1003
            printf("\n");
 
1004
        for (i = 0; i < ScreenCount(dpy); i++) {
 
1005
            newDB = dbs[i];
 
1006
            if (need_newline) {
 
1007
                printf("! screen %d resources\n", i);
 
1008
                printf("#if SCREEN_NUM == %d\n", i);
 
1009
            }
 
1010
            ReProcess(i, True);
 
1011
            if (need_newline) {
 
1012
                printf("#endif\n");
 
1013
                if (i+1 != ScreenCount(dpy))
 
1014
                    printf("\n");
 
1015
            }
 
1016
        }
 
1017
    }
 
1018
 
 
1019
    if (fp)
 
1020
        unlink(filename);
 
1021
    if (retainProp)
 
1022
        XSetCloseDownMode(dpy, RetainPermanent);
 
1023
    XCloseDisplay(dpy);
 
1024
    exit (0);
 
1025
}
 
1026
 
 
1027
 
 
1028
static void 
 
1029
FormatEntries(Buffer *buffer, Entries *entries)
 
1030
{
 
1031
    register int i;
 
1032
 
 
1033
    buffer->used = 0;
 
1034
    if (!entries->used)
 
1035
        return;
 
1036
    if (oper == OPMERGE)
 
1037
        qsort(entries->entry, entries->used, sizeof(Entry),
 
1038
              CompareEntries);
 
1039
    for (i = 0; i < entries->used; i++) {
 
1040
        if (entries->entry[i].usable)
 
1041
            AppendEntryToBuffer(buffer, &entries->entry[i]);
 
1042
    }
 
1043
}
 
1044
 
 
1045
static void
 
1046
StoreProperty(Display *dpy, Window root, Atom res_prop)
 
1047
{
 
1048
    int len = buffer.used;
 
1049
    int mode = PropModeReplace;
 
1050
    unsigned char *buf = (unsigned char *)buffer.buff;
 
1051
    int max = (XMaxRequestSize(dpy) << 2) - 28;
 
1052
 
 
1053
    if (len > max) {
 
1054
        XGrabServer(dpy);
 
1055
        do {
 
1056
            XChangeProperty(dpy, root, res_prop, XA_STRING, 8, mode, buf, max);
 
1057
            buf += max;
 
1058
            len -= max;
 
1059
            mode = PropModeAppend;
 
1060
        } while (len > max);
 
1061
    }
 
1062
    XChangeProperty(dpy, root, res_prop, XA_STRING, 8, mode, buf, len);
 
1063
    if (mode != PropModeReplace)
 
1064
        XUngrabServer(dpy);
 
1065
}
 
1066
 
 
1067
static void
 
1068
Process(int scrno, Bool doScreen, Bool execute)
 
1069
{
 
1070
    char *xdefs;
 
1071
    Window root;
 
1072
    Atom res_prop;
 
1073
    FILE *input, *output;
 
1074
    char *cmd;
 
1075
 
 
1076
    defines.val[defines_base] = '\0';
 
1077
    defines.used = defines_base;
 
1078
    buffer.used = 0;
 
1079
    InitEntries(&newDB);
 
1080
    DoScreenDefines(dpy, scrno, &defines);
 
1081
    DoCmdDefines(&defines);
 
1082
    if (doScreen) {
 
1083
        xdefs = XScreenResourceString (ScreenOfDisplay(dpy, scrno));
 
1084
        root = RootWindow(dpy, scrno);
 
1085
        res_prop = XInternAtom(dpy, SCREEN_RESOURCES, False);
 
1086
    } else {
 
1087
        xdefs = XResourceManagerString (dpy);
 
1088
        root = RootWindow(dpy, 0);
 
1089
        res_prop = XA_RESOURCE_MANAGER;
 
1090
    }
 
1091
    if (oper == OPSYMBOLS) {
 
1092
        printf ("%s\n", defines.val);
 
1093
    } else if (oper == OPQUERY) {
 
1094
        if (xdefs)
 
1095
            printf ("%s", xdefs);       /* fputs broken in SunOS 4.0 */
 
1096
    } else if (oper == OPREMOVE) {
 
1097
        if (xdefs)
 
1098
            XDeleteProperty(dpy, root, res_prop);
 
1099
    } else if (oper == OPEDIT) {
 
1100
        char template[100], old[100];
 
1101
 
 
1102
        input = fopen(editFile, "r");
 
1103
        snprintf(template, sizeof(template), "%sXXXXXX", editFile);
 
1104
#ifndef HAS_MKSTEMP
 
1105
        (void) mktemp(template);
 
1106
        output = fopen(template, "w");
 
1107
#else
 
1108
        { 
 
1109
        int fd = mkstemp(template);
 
1110
        output = fdopen(fd, "w");
 
1111
        }
 
1112
#endif
 
1113
        if (!output)
 
1114
            fatal("%s: can't open temporary file '%s'\n", ProgramName, template);
 
1115
        GetEntriesString(&newDB, xdefs);
 
1116
        EditFile(&newDB, input, output);
 
1117
        if (input)
 
1118
            fclose(input);
 
1119
        fclose(output);
 
1120
        snprintf(old, sizeof(old), "%s%s", editFile, backup_suffix);
 
1121
        if (dont_execute) {             /* then write to standard out */
 
1122
            char buf[BUFSIZ];
 
1123
            int n;
 
1124
 
 
1125
            output = fopen (template, "r");
 
1126
            if (output) {
 
1127
                while ((n = fread (buf, 1, sizeof buf, output)) > 0) {
 
1128
                    fwrite (buf, 1, n, stdout);
 
1129
                }
 
1130
                fclose (output);
 
1131
            }
 
1132
            unlink (template);
 
1133
        } else {
 
1134
            rename (editFile, old);
 
1135
            if (rename (template, editFile))
 
1136
                fatal("%s: can't rename file '%s' to '%s'\n", ProgramName,
 
1137
                      template, editFile);
 
1138
        }
 
1139
    } else {
 
1140
        if (oper == OPMERGE || oper == OPOVERRIDE)
 
1141
            GetEntriesString(&newDB, xdefs);
 
1142
#ifdef PATHETICCPP
 
1143
        if (need_real_defines) {
 
1144
#ifdef WIN32
 
1145
            if (!(input = fopen(tmpname2, "w")))
 
1146
                fatal("%s: can't open file '%s'\n", ProgramName, tmpname2);
 
1147
            fputs(defines.val, input);
 
1148
            fprintf(input, "\n#include \"%s\"\n", filename);
 
1149
            fclose(input);
 
1150
            (void) mktemp(tmpname3);
 
1151
            if((cmd = (char *)
 
1152
                malloc(strlen(cpp_program) + strlen(includes.val) +
 
1153
                       1 + strlen(tmpname2) + 3 + strlen(tmpname3) + 1)) ==
 
1154
               NULL)
 
1155
                fatal("%s: Out of memory\n", ProgramName);
 
1156
            sprintf(cmd, "%s%s %s > %s", cpp_program, includes.val,
 
1157
                    tmpname2, tmpname3);
 
1158
            if (system(cmd) < 0)
 
1159
                fatal("%s: cannot run '%s'\n", ProgramName, cmd);
 
1160
            free(cmd);
 
1161
            if (!(input = fopen(tmpname3, "r")))
 
1162
                fatal("%s: can't open file '%s'\n", ProgramName, tmpname3);
 
1163
#else
 
1164
            if (!freopen(tmpname2, "w+", stdin))
 
1165
                fatal("%s: can't open file '%s'\n", ProgramName, tmpname2);
 
1166
            fputs(defines.val, stdin);
 
1167
            fprintf(stdin, "\n#include \"%s\"\n", filename);
 
1168
            fflush(stdin);
 
1169
            fseek(stdin, 0, 0);
 
1170
            if((cmd = (char *)
 
1171
                malloc(strlen(cpp_program) + strlen(includes.val) + 1)) ==
 
1172
               NULL)
 
1173
                fatal("%s: Out of memory\n", ProgramName);
 
1174
            sprintf(cmd, "%s%s", cpp_program, includes.val);
 
1175
            if (!(input = popen(cmd, "r")))
 
1176
                fatal("%s: cannot run '%s'\n", ProgramName, cmd);
 
1177
            free(cmd);
 
1178
#endif
 
1179
        } else {
 
1180
#endif
 
1181
        if (filename) {
 
1182
            if (!freopen (filename, "r", stdin))
 
1183
                fatal("%s: can't open file '%s'\n", ProgramName, filename);
 
1184
        }
 
1185
        if (cpp_program) {
 
1186
#ifdef WIN32
 
1187
            (void) mktemp(tmpname3);
 
1188
            if((cmd = (char *)
 
1189
                malloc(strlen(cpp_program) + strlen(includes.val) +
 
1190
                       1 + strlen(defines.val) + 1 +
 
1191
                       strlen(filename ? filename : "") + 3 +
 
1192
                       strlen(tmpname3) + 1)) ==
 
1193
               NULL)
 
1194
                fatal("%s: Out of memory\n", ProgramName);
 
1195
            sprintf(cmd, "%s%s %s %s > %s", cpp_program,
 
1196
                    includes.val, defines.val,
 
1197
                    filename ? filename : "", tmpname3);
 
1198
            if (system(cmd) < 0)
 
1199
                fatal("%s: cannot run '%s'\n", ProgramName, cmd);
 
1200
            free(cmd);
 
1201
            if (!(input = fopen(tmpname3, "r")))
 
1202
                fatal("%s: can't open file '%s'\n", ProgramName, tmpname3);
 
1203
#else
 
1204
            if((cmd = (char *)
 
1205
                malloc(strlen(cpp_program) + strlen(includes.val) + 1 +
 
1206
                       strlen(defines.val) + 1)) ==
 
1207
               NULL)
 
1208
                fatal("%s: Out of memory\n", ProgramName);
 
1209
            sprintf(cmd, "%s%s %s", cpp_program, includes.val, defines.val);
 
1210
            if (!(input = popen(cmd, "r")))
 
1211
                fatal("%s: cannot run '%s'\n", ProgramName, cmd);
 
1212
            free(cmd);
 
1213
#endif
 
1214
        } else {
 
1215
            input = stdin;
 
1216
        }
 
1217
#ifdef PATHETICCPP
 
1218
        }
 
1219
#endif
 
1220
        ReadFile(&buffer, input);
 
1221
        if (cpp_program) {
 
1222
#ifdef WIN32
 
1223
            fclose(input);
 
1224
#else
 
1225
            pclose(input);
 
1226
#endif
 
1227
        }
 
1228
#ifdef PATHETICCPP
 
1229
        if (need_real_defines) {
 
1230
            unlink(tmpname2);
 
1231
#ifdef WIN32
 
1232
            if (tmpname3[strlen(tmpname3) - 1] != 'X')
 
1233
                unlink(tmpname3);
 
1234
#endif
 
1235
        }
 
1236
#endif
 
1237
        GetEntries(&newDB, &buffer, 0);
 
1238
        if (execute) {
 
1239
            FormatEntries(&buffer, &newDB);
 
1240
            if (dont_execute) {
 
1241
                if (buffer.used > 0) {
 
1242
                    fwrite (buffer.buff, 1, buffer.used, stdout);
 
1243
                    if (buffer.buff[buffer.used - 1] != '\n') putchar ('\n');
 
1244
                }
 
1245
            } else if (buffer.used > 1 || !doScreen)
 
1246
                StoreProperty (dpy, root, res_prop);
 
1247
            else
 
1248
                XDeleteProperty (dpy, root, res_prop);
 
1249
        }
 
1250
    }
 
1251
    if (execute)
 
1252
        FreeEntries(&newDB);
 
1253
    if (doScreen && xdefs)
 
1254
        XFree(xdefs);
 
1255
}
 
1256
 
 
1257
static void
 
1258
ShuffleEntries(Entries *db, Entries *dbs, int num)
 
1259
{
 
1260
    int *hits;
 
1261
    register int i, j, k;
 
1262
    Entries cur, cmp;
 
1263
    char *curtag, *curvalue;
 
1264
 
 
1265
    hits = (int *)malloc(num * sizeof(int));
 
1266
    cur = dbs[0];
 
1267
    for (i = 0; i < cur.used; i++) {
 
1268
        curtag = cur.entry[i].tag;
 
1269
        curvalue = cur.entry[i].value;
 
1270
        for (j = 1; j < num; j++) {
 
1271
            cmp = dbs[j];
 
1272
            for (k = 0; k < cmp.used; k++) {
 
1273
                if (cmp.entry[k].usable &&
 
1274
                    !strcmp(curtag, cmp.entry[k].tag) &&
 
1275
                    !strcmp(curvalue, cmp.entry[k].value))
 
1276
                {
 
1277
                    hits[j] = k;
 
1278
                    break;
 
1279
                }
 
1280
            }
 
1281
            if (k == cmp.used)
 
1282
                break;
 
1283
        }
 
1284
        if (j == num) {
 
1285
            AddEntry(db, &cur.entry[i]);
 
1286
            hits[0] = i;
 
1287
            for (j = 0; j < num; j++)
 
1288
                dbs[j].entry[hits[j]].usable = False;
 
1289
        }
 
1290
    }
 
1291
    free((char *)hits);
 
1292
}
 
1293
 
 
1294
static void
 
1295
ReProcess(int scrno, Bool doScreen)
 
1296
{
 
1297
    Window root;
 
1298
    Atom res_prop;
 
1299
 
 
1300
    FormatEntries(&buffer, &newDB);
 
1301
    if (doScreen) {
 
1302
        root = RootWindow(dpy, scrno);
 
1303
        res_prop = XInternAtom(dpy, SCREEN_RESOURCES, False);
 
1304
    } else {
 
1305
        root = RootWindow(dpy, 0);
 
1306
        res_prop = XA_RESOURCE_MANAGER;
 
1307
    }
 
1308
    if (dont_execute) {
 
1309
        if (buffer.used > 0) {
 
1310
            fwrite (buffer.buff, 1, buffer.used, stdout);
 
1311
            if (buffer.buff[buffer.used - 1] != '\n') putchar ('\n');
 
1312
        }
 
1313
    } else {
 
1314
        if (buffer.used > 1 || !doScreen)
 
1315
            StoreProperty (dpy, root, res_prop);
 
1316
        else
 
1317
            XDeleteProperty (dpy, root, res_prop);
 
1318
    }
 
1319
    FreeEntries(&newDB);
 
1320
}
 
1321
 
 
1322
static void
 
1323
fatal(char *msg, ...)
 
1324
{
 
1325
    va_list args;
 
1326
 
 
1327
    if (errno != 0)
 
1328
        perror(ProgramName);
 
1329
    va_start(args, msg);
 
1330
    vfprintf(stderr, msg, args);
 
1331
    va_end(args);
 
1332
    exit(1);
 
1333
}