diff options
author | dawes <dawes> | 1994-04-27 07:07:10 +0000 |
---|---|---|
committer | dawes <dawes> | 1994-04-27 07:07:10 +0000 |
commit | 0eb2a9ffbce458a68d60d1a1854c115cd68feaaf (patch) | |
tree | 0d20c0850671e155b34993ba0a7bf44f02551892 /programs/xrdb |
Initial revision
Diffstat (limited to 'programs/xrdb')
-rw-r--r-- | programs/xrdb/Imakefile | 9 | ||||
-rw-r--r-- | programs/xrdb/xrdb.c | 1273 | ||||
-rw-r--r-- | programs/xrdb/xrdb.man | 303 |
3 files changed, 1585 insertions, 0 deletions
diff --git a/programs/xrdb/Imakefile b/programs/xrdb/Imakefile new file mode 100644 index 000000000..7eae50f84 --- /dev/null +++ b/programs/xrdb/Imakefile @@ -0,0 +1,9 @@ +XCOMM $XConsortium: Imakefile,v 1.8 92/09/14 18:53:12 rws Exp $ +#if PatheticCpp + CPPDEFS = -DPATHETICCPP +#endif + DEFINES = -DCPP="\"$(CPP)\"" $(CPPDEFS) + DEPLIBS = $(DEPXMULIB) $(DEPXLIB) +LOCAL_LIBRARIES = $(XMULIB) $(XLIB) + +SimpleProgramTarget(xrdb) diff --git a/programs/xrdb/xrdb.c b/programs/xrdb/xrdb.c new file mode 100644 index 000000000..e32fcdd85 --- /dev/null +++ b/programs/xrdb/xrdb.c @@ -0,0 +1,1273 @@ +/* + * xrdb - X resource manager database utility + * + * $XConsortium: xrdb.c,v 11.75 94/03/27 14:42:02 rws Exp $ + */ + +/* + * COPYRIGHT 1987, 1991 + * DIGITAL EQUIPMENT CORPORATION + * MAYNARD, MASSACHUSETTS + * MASSACHUSETTS INSTITUTE OF TECHNOLOGY + * CAMBRIDGE, MASSACHUSETTS + * ALL RIGHTS RESERVED. + * + * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND + * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. + * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR + * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. + * + * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, + * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT + * SET FORTH ABOVE. + * + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Digital Equipment Corporation not be + * used in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. + */ + +/* + * this program is used to load, or dump the resource manager database + * in the server. + * + * Original Author: Jim Gettys, August 28, 1987 + * Extensively Modified: Phil Karlton, January 5, 1987 + * Modified a Bunch More: Bob Scheifler, February, 1991 + */ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/Xos.h> +#include <stdio.h> +#include <ctype.h> + +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif + + +#if NeedVarargsPrototypes +# include <stdarg.h> +#endif + +#define SCREEN_RESOURCES "SCREEN_RESOURCES" + +#ifndef CPP +#define CPP "/usr/lib/cpp" +#endif /* CPP */ + +#define INIT_BUFFER_SIZE 10000 +#define INIT_ENTRY_SIZE 500 + +#define RALL 0 +#define RGLOBAL 1 +#define RSCREEN 2 +#define RSCREENS 3 + +#define OPSYMBOLS 0 +#define OPQUERY 1 +#define OPREMOVE 2 +#define OPEDIT 3 +#define OPLOAD 4 +#define OPMERGE 5 +#define OPOVERRIDE 6 + +#define RESOURCE_PROPERTY_NAME "RESOURCE_MANAGER" +#define BACKUP_SUFFIX ".bak" /* for editting */ + +typedef struct _Entry { + char *tag, *value; + int lineno; + Bool usable; +} Entry; +typedef struct _Buffer { + char *buff; + int room, used; +} Buffer; +typedef struct _Entries { + Entry *entry; + int room, used; +} Entries; + +char *ProgramName; +Bool quiet = False; +char tmpname[32]; +char *filename = NULL; +#ifdef PATHETICCPP +Bool need_real_defines = False; +char tmpname2[32]; +#ifdef WIN32 +char tmpname3[32]; +#endif +#endif +int oper = OPLOAD; +char *editFile = NULL; +char *cpp_program = CPP; +char *backup_suffix = BACKUP_SUFFIX; +Bool dont_execute = False; +char defines[4096]; +int defines_base; +char *cmd_defines[512]; +int num_cmd_defines = 0; +char includes[4096]; +Display *dpy; +Buffer buffer; +Entries newDB; + +#if !defined(sgi) && !defined(WIN32) +extern FILE *popen(); +#endif + +#if NeedVarargsPrototypes +extern fatal(char *, ...); +#endif + +#if defined(USG) && !defined(CRAY) && !defined(MOTOROLA) +int rename (from, to) + char *from, *to; +{ + (void) unlink (to); + if (link (from, to) == 0) { + unlink (from); + return 0; + } else { + return -1; + } +} +#endif + +void InitBuffer(b) + Buffer *b; +{ + b->room = INIT_BUFFER_SIZE; + b->used = 0; + b->buff = (char *)malloc(INIT_BUFFER_SIZE*sizeof(char)); +} + +void FreeBuffer(b) + Buffer *b; +{ + free(b->buff); +} + +void AppendToBuffer(b, str, len) + register Buffer *b; + char *str; + register int len; +{ + while (b->used + len > b->room) { + b->buff = (char *)realloc(b->buff, 2*b->room*(sizeof(char))); + b->room *= 2; + } + strncpy(b->buff + b->used, str, len); + b->used += len; +} + +void InitEntries(e) + Entries *e; +{ + e->room = INIT_ENTRY_SIZE; + e->used = 0; + e->entry = (Entry *)malloc(INIT_ENTRY_SIZE*sizeof(Entry)); +} + +void FreeEntries(e) + Entries *e; +{ + register int i; + + for (i = 0; i < e->used; i++) { + if (e->entry[i].usable) { + free(e->entry[i].tag); + free(e->entry[i].value); + } + } + free((char *)e->entry); +} + +void AddEntry(e, entry) + register Entries *e; + Entry *entry; +{ + register int n; + + for (n = 0; n < e->used; n++) { + if (!strcmp(e->entry[n].tag, entry->tag)) { + /* overwrite old entry */ + if (e->entry[n].lineno && !quiet) { + fprintf (stderr, + "%s: \"%s\" on line %d overrides entry on line %d\n", + ProgramName, entry->tag, entry->lineno, + e->entry[n].lineno); + } + free(e->entry[n].tag); + free(e->entry[n].value); + entry->usable = True; + e->entry[n] = *entry; + return; /* ok to leave, now there's only one of each tag in db */ + } + } + + if (e->used == e->room) { + e->entry = (Entry *)realloc((char *)e->entry, + 2*e->room*(sizeof(Entry))); + e->room *= 2; + } + entry->usable = True; + e->entry[e->used++] = *entry; +} + + +int CompareEntries(e1, e2) + Entry *e1, *e2; +{ + return strcmp(e1->tag, e2->tag); +} + +void AppendEntryToBuffer(buffer, entry) + register Buffer *buffer; + Entry *entry; +{ + AppendToBuffer(buffer, entry->tag, strlen(entry->tag)); + AppendToBuffer(buffer, ":\t", 2); + AppendToBuffer(buffer, entry->value, strlen(entry->value)); + AppendToBuffer(buffer, "\n", 1); +} + +/* + * Return the position of the first unescaped occurrence of dest in string. + * If lines is non-null, return the number of newlines skipped over. + */ +char *FindFirst(string, dest, lines) + register char *string; + register char dest; + register int *lines; /* RETURN */ +{ + if (lines) + *lines = 0; + for (;;) { + if (*string == '\0') + return NULL; + if (*string == '\\') { + if (*++string == '\0') + return NULL; + } else if (*string == dest) + return string; + if (*string == '\n' && lines) + (*lines)++; + string++; + } +} + +void GetEntries(entries, buff, bequiet) + register Entries *entries; + Buffer *buff; + int bequiet; +{ + register char *line, *colon, *temp, *str; + Entry entry; + register int length; + int lineno = 0; + int lines_skipped; + + str = buff->buff; + if (!str) return; + for ( ; str < buff->buff + buff->used; + str = line + 1, lineno += lines_skipped) { + line = FindFirst(str, '\n', &lines_skipped); + lineno++; + if (!line) + line = buff->buff + buff->used; + if (*str == '!') + continue; + if (*str == '\n') + continue; + if (!bequiet && *str == '#') { + int dummy; + if (sscanf (str, "# %d", &dummy) == 1 || + sscanf (str, "# line %d", &dummy) == 1) + lineno = dummy - 1; + continue; + } + for (temp = str; + *temp && *temp != '\n' && isascii(*temp) && isspace(*temp); + temp++) ; + if (!*temp || *temp == '\n') continue; + + colon = FindFirst(str, ':', NULL); + if (!colon || colon > line) { + if (!bequiet && !quiet) + fprintf (stderr, + "%s: colon missing on line %d, ignoring line\n", + ProgramName, lineno); + continue; + } + + /* strip leading and trailing blanks from name and store result */ + while (*str == ' ' || *str == '\t') + str++; + length = colon - str; + while (length && (str[length-1] == ' ' || str[length-1] == '\t')) + length--; + temp = (char *)malloc(length + 1); + strncpy(temp, str, length); + temp[length] = '\0'; + entry.tag = temp; + + /* strip leading and trailing blanks from value and store result */ + colon++; + while (*colon == ' ' || *colon == '\t') + colon++; + length = line - colon; + temp = (char *)malloc(length + 1); + strncpy(temp, colon, length); + temp[length] = '\0'; + entry.value = temp; + entry.lineno = bequiet ? 0 : lineno; + + AddEntry(entries, &entry); + } +} + +GetEntriesString(entries, str) + register Entries *entries; + char *str; +{ + Buffer buff; + + if (str && *str) { + buff.buff = str; + buff.used = strlen(str); + GetEntries(entries, &buff, 1); + } +} + +void ReadFile(buffer, input) + register Buffer *buffer; + FILE *input; +{ + char buf[BUFSIZ + 1]; + register int bytes; + + buffer->used = 0; + while (!feof(input) && (bytes = fread(buf, 1, BUFSIZ, input)) > 0) { +#ifdef WIN32 + char *p; + buf[bytes] = '\0'; + for (p = buf; p = strchr(p, '\r'); ) { + if (p[-1] == '\\' && p[1] == '\n') { + bytes -= 3; + strcpy(p - 1, p + 2); + } + } +#endif + AppendToBuffer(buffer, buf, bytes); + } + AppendToBuffer(buffer, "", 1); +} + +AddDef(buff, title, value) + char *buff, *title, *value; +{ +#ifdef PATHETICCPP + if (need_real_defines) { + strcat(buff, "\n#define "); + strcat(buff, title); + if (value && (value[0] != '\0')) { + strcat(buff, " "); + strcat(buff, value); + } + return; + } +#endif + if (buff[0]) { + if (oper == OPSYMBOLS) + strcat(buff, "\n-D"); + else + strcat(buff, " -D"); + } else + strcat(buff, "-D"); + strcat(buff, title); + if (value && (value[0] != '\0')) { + strcat(buff, "="); + strcat(buff, value); + } +} + +AddDefQ(buff, title, value) + char *buff, *title, *value; +{ +#ifdef PATHETICCPP + if (need_real_defines) + AddDef(buff, title, value); + else +#endif + if (value && (value[0] != '\0')) { + AddDef(buff, title, "\""); + strcat(buff, value); + strcat(buff, "\""); + } else + AddDef(buff, title, NULL); +} + +AddNum(buff, title, value) + char *buff, *title; + int value; +{ + char num[20]; + sprintf(num, "%d", value); + AddDef(buff, title, num); +} + +AddSimpleDef(buff, title) + char *buff, *title; +{ + AddDef(buff, title, (char *)NULL); +} + +AddDefTok(buff, prefix, title) + char *buff, *prefix, *title; +{ + char *s; + char name[512]; + char c; + + strcpy(name, prefix); + strcat(name, title); + for (s = name; c = *s; s++) { + if (!isalpha(c) && !isdigit(c) && c != '_') + *s = '_'; + } + AddSimpleDef(buff, name); +} + +AddUndef(buff, title) + char *buff, *title; +{ +#ifdef PATHETICCPP + if (need_real_defines) { + strcat(buff, "\n#undef "); + strcat(buff, title); + return; + } +#endif + if (buff[0]) { + if (oper == OPSYMBOLS) + strcat(buff, "\n-U"); + else + strcat(buff, " -U"); + } else + strcat(buff, "-U"); + strcat(buff, title); +} + +DoCmdDefines(buff) + char *buff; +{ + int i; + char *arg, *val; + + for (i = 0; i < num_cmd_defines; i++) { + arg = cmd_defines[i]; + if (arg[1] == 'D') { + val = strchr(arg, '='); + if (val) { + *val = '\0'; + AddDefQ(buff, arg + 2, val + 1); + *val = '='; + } else + AddSimpleDef(buff, arg + 2); + } else + AddUndef(buff, arg + 2); + } +} + +int Resolution(pixels, mm) + int pixels, mm; +{ + return ((pixels * 100000 / mm) + 50) / 100; +} + + +void +DoDisplayDefines(display, defs, host) + Display *display; + register char *defs; + char *host; +{ +#define MAXHOSTNAME 255 + char client[MAXHOSTNAME], server[MAXHOSTNAME], *colon; + char **extnames; + int n; + + XmuGetHostname(client, MAXHOSTNAME); + strcpy(server, XDisplayName(host)); + colon = strchr(server, ':'); + n = 0; + if (colon) { + *colon++ = '\0'; + if (*colon == ':') + colon++; + sscanf(colon, "%d", &n); + } + if (!*server || !strcmp(server, "unix") || !strcmp(server, "localhost")) + strcpy(server, client); + AddDef(defs, "HOST", server); /* R3 compatibility */ + AddDef(defs, "SERVERHOST", server); + AddDefTok(defs, "SRVR_", server); + AddNum(defs, "DISPLAY_NUM", n); + AddDef(defs, "CLIENTHOST", client); + AddDefTok(defs, "CLNT_", client); + AddNum(defs, "VERSION", ProtocolVersion(display)); + AddNum(defs, "REVISION", ProtocolRevision(display)); + AddDefQ(defs, "VENDOR", ServerVendor(display)); + AddDefTok(defs, "VNDR_", ServerVendor(display)); + AddNum(defs, "RELEASE", VendorRelease(display)); + AddNum(defs, "NUM_SCREENS", ScreenCount(display)); + extnames = XListExtensions(display, &n); + while (--n >= 0) + AddDefTok(defs, "EXT_", extnames[n]); +} + +char *ClassNames[] = { + "StaticGray", + "GrayScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor" +}; + +void +DoScreenDefines(display, scrno, defs) + Display *display; + int scrno; + register char *defs; +{ + Screen *screen; + Visual *visual; + XVisualInfo vinfo, *vinfos; + int nv, i, j; + char name[50]; + + screen = ScreenOfDisplay(display, scrno); + visual = DefaultVisualOfScreen(screen); + vinfo.screen = scrno; + vinfos = XGetVisualInfo(display, VisualScreenMask, &vinfo, &nv); + AddNum(defs, "SCREEN_NUM", scrno); + AddNum(defs, "WIDTH", screen->width); + AddNum(defs, "HEIGHT", screen->height); + AddNum(defs, "X_RESOLUTION", Resolution(screen->width,screen->mwidth)); + AddNum(defs, "Y_RESOLUTION", Resolution(screen->height,screen->mheight)); + AddNum(defs, "PLANES", DisplayPlanes(display, scrno)); + AddNum(defs, "BITS_PER_RGB", visual->bits_per_rgb); + AddDef(defs, "CLASS", ClassNames[visual->class]); + sprintf(name, "CLASS_%s", ClassNames[visual->class]); + AddNum(defs, name, (int)visual->visualid); + switch(visual->class) { + case StaticColor: + case PseudoColor: + case TrueColor: + case DirectColor: + AddSimpleDef(defs, "COLOR"); + break; + } + for (i = 0; i < nv; i++) { + for (j = i; --j >= 0; ) { + if (vinfos[j].class == vinfos[i].class && + vinfos[j].depth == vinfos[i].depth) + break; + } + if (j < 0) { + sprintf(name, "CLASS_%s_%d", + ClassNames[vinfos[i].class], vinfos[i].depth); + AddNum(defs, name, (int)vinfos[i].visualid); + } + } + XFree((char *)vinfos); +} + +Entry *FindEntry(db, b) + register Entries *db; + Buffer *b; +{ + int i; + register Entry *e; + Entries phoney; + Entry entry; + + entry.usable = False; + entry.tag = NULL; + entry.value = NULL; + phoney.used = 0; + phoney.room = 1; + phoney.entry = &entry; + GetEntries(&phoney, b, 1); + if (phoney.used < 1) + return NULL; + for (i = 0; i < db->used; i++) { + e = &db->entry[i]; + if (!e->usable) + continue; + if (strcmp(e->tag, entry.tag)) + continue; + e->usable = False; + if (strcmp(e->value, entry.value)) + return e; + return NULL; + } + return NULL; +} + +void EditFile(new, in, out) + register Entries *new; + FILE *in, *out; +{ + Buffer b; + char buff[BUFSIZ]; + register Entry *e; + register char *c; + int i; + + InitBuffer(&b); + while (in) { + b.used = 0; + while (1) { + buff[0] ='\0'; + if (!fgets(buff, BUFSIZ, in)) + goto cleanup; + AppendToBuffer(&b, buff, strlen(buff)); + c = &b.buff[b.used - 1]; + if ((*(c--) == '\n') && (b.used == 1 || *c != '\\')) + break; + } + if (e = FindEntry(new, &b)) + fprintf(out, "%s:\t%s\n", e->tag, e->value); + else + fwrite(b.buff, 1, b.used, out); + } +cleanup: + for (i = 0; i < new->used; i++) { + e = &new->entry[i]; + if (e->usable) + fprintf(out, "%s:\t%s\n", e->tag, e->value); + } +} + +void Syntax () +{ + fprintf (stderr, + "usage: %s [-options ...] [filename]\n\n", + ProgramName); + fprintf (stderr, + "where options include:\n"); + fprintf (stderr, + " -display host:dpy display to use\n"); + fprintf (stderr, + " -all do all resources [default]\n"); + fprintf (stderr, + " -global do screen-independent resources\n"); + fprintf (stderr, + " -screen do screen-specific resources for one screen\n"); + fprintf (stderr, + " -screens do screen-specific resources for all screens\n"); + fprintf (stderr, + " -n show but don't do changes\n"); + fprintf (stderr, + " -cpp filename preprocessor to use [%s]\n", + CPP); + fprintf (stderr, + " -nocpp do not use a preprocessor\n"); + fprintf (stderr, + " -query query resources\n"); + fprintf (stderr, + " -load load resources from file [default]\n"); + fprintf (stderr, + " -override add in resources from file\n"); + fprintf (stderr, + " -merge merge resources from file & sort\n"); + fprintf (stderr, + " -edit filename edit resources into file\n"); + fprintf (stderr, + " -backup string backup suffix for -edit [%s]\n", + BACKUP_SUFFIX); + fprintf (stderr, + " -symbols show preprocessor symbols\n"); + fprintf (stderr, + " -remove remove resources\n"); + fprintf (stderr, + " -retain avoid server reset (avoid using this)\n"); + fprintf (stderr, + " -quiet don't warn about duplicates\n"); + fprintf (stderr, + " -Dname[=value], -Uname, -Idirectory %s\n", + "passed to preprocessor"); + fprintf (stderr, + "\n"); + fprintf (stderr, + "A - or no input filename represents stdin.\n"); + exit (1); +} + +/* + * The following is a hack until XrmParseCommand is ready. It determines + * whether or not the given string is an abbreviation of the arg. + */ + +Bool isabbreviation (arg, s, minslen) + char *arg; + char *s; + int minslen; +{ + int arglen; + int slen; + + /* exact match */ + if (!strcmp (arg, s)) return (True); + + arglen = strlen (arg); + slen = strlen (s); + + /* too long or too short */ + if (slen >= arglen || slen < minslen) return (False); + + /* abbreviation */ + if (strncmp (arg, s, slen) == 0) return (True); + + /* bad */ + return (False); +} + +main (argc, argv) + int argc; + char **argv; +{ + int i; + char *displayname = NULL; + int whichResources = RALL; + int retainProp = 0; + FILE *fp = NULL; + Bool need_newline; + + ProgramName = argv[0]; + + defines[0] = '\0'; + includes[0] = '\0'; + + /* needs to be replaced with XrmParseCommand */ + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + + if (arg[0] == '-') { + if (arg[1] == '\0') { + filename = NULL; + continue; + } else if (isabbreviation ("-help", arg, 2)) { + Syntax (); + /* doesn't return */ + } else if (isabbreviation ("-display", arg, 2)) { + if (++i >= argc) Syntax (); + displayname = argv[i]; + continue; + } else if (isabbreviation ("-geometry", arg, 3)) { + if (++i >= argc) Syntax (); + /* ignore geometry */ + continue; + } else if (isabbreviation ("-cpp", arg, 2)) { + if (++i >= argc) Syntax (); + cpp_program = argv[i]; + continue; + } else if (!strcmp ("-n", arg)) { + dont_execute = True; + continue; + } else if (isabbreviation ("-nocpp", arg, 3)) { + cpp_program = NULL; + continue; + } else if (isabbreviation ("-query", arg, 2)) { + oper = OPQUERY; + continue; + } else if (isabbreviation ("-load", arg, 2)) { + oper = OPLOAD; + continue; + } else if (isabbreviation ("-merge", arg, 2)) { + oper = OPMERGE; + continue; + } else if (isabbreviation ("-override", arg, 2)) { + oper = OPOVERRIDE; + continue; + } else if (isabbreviation ("-symbols", arg, 3)) { + oper = OPSYMBOLS; + continue; + } else if (isabbreviation ("-remove", arg, 4)) { + oper = OPREMOVE; + continue; + } else if (isabbreviation ("-edit", arg, 2)) { + if (++i >= argc) Syntax (); + oper = OPEDIT; + editFile = argv[i]; + continue; + } else if (isabbreviation ("-backup", arg, 2)) { + if (++i >= argc) Syntax (); + backup_suffix = argv[i]; + continue; + } else if (isabbreviation ("-all", arg, 2)) { + whichResources = RALL; + continue; + } else if (isabbreviation ("-global", arg, 3)) { + whichResources = RGLOBAL; + continue; + } else if (isabbreviation ("-screen", arg, 3)) { + whichResources = RSCREEN; + continue; + } else if (!strcmp ("-screens", arg)) { + whichResources = RSCREENS; + continue; + } else if (isabbreviation ("-retain", arg, 4)) { + retainProp = 1; + continue; + } else if (isabbreviation ("-quiet", arg, 2)) { + quiet = True; + continue; + } else if (arg[1] == 'I') { + strcat(includes, " "); + strcat(includes, arg); + continue; + } else if (arg[1] == 'U' || arg[1] == 'D') { + cmd_defines[num_cmd_defines++] = arg; + continue; + } + Syntax (); + } else if (arg[0] == '=') + continue; + else + filename = arg; + } /* end for */ + +#ifndef WIN32 + while ((i = open("/dev/null", 0)) < 3) + ; /* make sure later freopen won't clobber things */ + (void) close(i); +#endif + /* Open display */ + if (!(dpy = XOpenDisplay (displayname))) + fatal("%s: Can't open display '%s'\n", ProgramName, + XDisplayName (displayname)); + + if (whichResources == RALL && ScreenCount(dpy) == 1) + whichResources = RGLOBAL; + +#ifdef PATHETICCPP + if (cpp_program && + (oper == OPLOAD || oper == OPMERGE || oper == OPOVERRIDE)) { + need_real_defines = True; +#ifdef WIN32 + strcpy(tmpname2, "xrdbD_XXXXXX"); + strcpy(tmpname3, "\\temp\\xrdbD_XXXXXX"); +#else + strcpy(tmpname2, "/tmp/xrdbD_XXXXXX"); +#endif + (void) mktemp(tmpname2); + } +#endif + + if (!filename && +#ifdef PATHETICCPP + need_real_defines +#else + (oper == OPLOAD || oper == OPMERGE || oper == OPOVERRIDE) && + (whichResources == RALL || whichResources == RSCREENS) +#endif + ) { +#ifdef WIN32 + strcpy(tmpname, "\\temp\\xrdb_XXXXXX"); +#else + strcpy(tmpname, "/tmp/xrdb_XXXXXX"); +#endif + (void) mktemp(tmpname); + filename = tmpname; + fp = fopen(filename, "w"); + if (!fp) + fatal("%s: Failed to open temp file: %s\n", ProgramName, + filename); + while ((i = getc(stdin)) != EOF) + putc(i, fp); + fclose(fp); + } + + DoDisplayDefines(dpy, defines, displayname); + defines_base = strlen(defines); + need_newline = (oper == OPQUERY || oper == OPSYMBOLS || + (dont_execute && oper != OPREMOVE)); + InitBuffer(&buffer); + if (whichResources == RGLOBAL) + Process(DefaultScreen(dpy), False, True); + else if (whichResources == RSCREEN) + Process(DefaultScreen(dpy), True, True); + else if (whichResources == RSCREENS || + (oper != OPLOAD && oper != OPMERGE && oper != OPOVERRIDE)) { + if (whichResources == RALL && oper != OPSYMBOLS) { + if (need_newline) + printf("! screen-independent resources\n"); + Process(0, False, True); + if (need_newline) + printf("\n"); + } + for (i = 0; i < ScreenCount(dpy); i++) { + if (need_newline) { + if (oper == OPSYMBOLS) + printf("# screen %d symbols\n", i); + else { + printf("! screen %d resources\n", i); + printf("#if SCREEN_NUM == %d\n", i); + } + } + Process(i, True, True); + if (need_newline) { + if (oper != OPSYMBOLS) + printf("#endif\n"); + if (i+1 != ScreenCount(dpy)) + printf("\n"); + } + } + } + else { + Entries *dbs; + + dbs = (Entries *)malloc(ScreenCount(dpy) * sizeof(Entries)); + for (i = 0; i < ScreenCount(dpy); i++) { + Process(i, True, False); + dbs[i] = newDB; + } + InitEntries(&newDB); + if (oper == OPMERGE || oper == OPOVERRIDE) + GetEntriesString(&newDB, XResourceManagerString(dpy)); + ShuffleEntries(&newDB, dbs, ScreenCount(dpy)); + if (need_newline) + printf("! screen-independent resources\n"); + ReProcess(0, False); + if (need_newline) + printf("\n"); + for (i = 0; i < ScreenCount(dpy); i++) { + newDB = dbs[i]; + if (need_newline) { + printf("! screen %d resources\n", i); + printf("#if SCREEN_NUM == %d\n", i); + } + ReProcess(i, True); + if (need_newline) { + printf("#endif\n"); + if (i+1 != ScreenCount(dpy)) + printf("\n"); + } + } + } + + if (fp) + unlink(filename); + if (retainProp) + XSetCloseDownMode(dpy, RetainPermanent); + XCloseDisplay(dpy); + exit (0); +} + +void FormatEntries(buffer, entries) + register Buffer *buffer; + register Entries *entries; +{ + register int i; + + buffer->used = 0; + if (!entries->used) + return; + if (oper == OPMERGE) + qsort(entries->entry, entries->used, sizeof(Entry), CompareEntries); + for (i = 0; i < entries->used; i++) { + if (entries->entry[i].usable) + AppendEntryToBuffer(buffer, &entries->entry[i]); + } +} + +StoreProperty(dpy, root, res_prop) + Display *dpy; + Window root; + Atom res_prop; +{ + int len = buffer.used; + int mode = PropModeReplace; + unsigned char *buf = (unsigned char *)buffer.buff; + int max = (XMaxRequestSize(dpy) << 2) - 28; + + if (len > max) { + XGrabServer(dpy); + do { + XChangeProperty(dpy, root, res_prop, XA_STRING, 8, mode, buf, max); + buf += max; + len -= max; + mode = PropModeAppend; + } while (len > max); + } + XChangeProperty(dpy, root, res_prop, XA_STRING, 8, mode, buf, len); + if (mode != PropModeReplace) + XUngrabServer(dpy); +} + +Process(scrno, doScreen, execute) + int scrno; + Bool doScreen; + Bool execute; +{ + char *xdefs; + Window root; + Atom res_prop; + FILE *input, *output; + char cmd[BUFSIZ]; + + defines[defines_base] = '\0'; + buffer.used = 0; + InitEntries(&newDB); + DoScreenDefines(dpy, scrno, defines); + DoCmdDefines(defines); + if (doScreen) { + xdefs = XScreenResourceString (ScreenOfDisplay(dpy, scrno)); + root = RootWindow(dpy, scrno); + res_prop = XInternAtom(dpy, SCREEN_RESOURCES, False); + } else { + xdefs = XResourceManagerString (dpy); + root = RootWindow(dpy, 0); + res_prop = XA_RESOURCE_MANAGER; + } + if (oper == OPSYMBOLS) { + printf ("%s\n", defines); + } else if (oper == OPQUERY) { + if (xdefs) + printf ("%s", xdefs); /* fputs broken in SunOS 4.0 */ + } else if (oper == OPREMOVE) { + if (xdefs) + XDeleteProperty(dpy, root, res_prop); + } else if (oper == OPEDIT) { + char template[100], old[100]; + + input = fopen(editFile, "r"); + strcpy(template, editFile); + strcat(template, "XXXXXX"); + (void) mktemp(template); + output = fopen(template, "w"); + if (!output) + fatal("%s: can't open temporary file '%s'\n", ProgramName, template); + GetEntriesString(&newDB, xdefs); + EditFile(&newDB, input, output); + if (input) + fclose(input); + fclose(output); + strcpy(old, editFile); + strcat(old, backup_suffix); + if (dont_execute) { /* then write to standard out */ + char buf[BUFSIZ]; + int n; + + output = fopen (template, "r"); + if (output) { + while ((n = fread (buf, 1, sizeof buf, output)) > 0) { + fwrite (buf, 1, n, stdout); + } + fclose (output); + } + unlink (template); + } else { + rename (editFile, old); + if (rename (template, editFile)) + fatal("%s: can't rename file '%s' to '%s'\n", ProgramName, + template, editFile); + } + } else { + if (oper == OPMERGE || oper == OPOVERRIDE) + GetEntriesString(&newDB, xdefs); +#ifdef PATHETICCPP + if (need_real_defines) { +#ifdef WIN32 + if (!(input = fopen(tmpname2, "w"))) + fatal("%s: can't open file '%s'\n", ProgramName, tmpname2); + fputs(defines, input); + fprintf(input, "\n#include \"%s\"\n", filename); + fclose(input); + (void) mktemp(tmpname3); + sprintf(cmd, "%s%s %s > %s", cpp_program, includes, + tmpname2, tmpname3); + if (system(cmd) < 0) + fatal("%s: cannot run '%s'\n", ProgramName, cmd); + if (!(input = fopen(tmpname3, "r"))) + fatal("%s: can't open file '%s'\n", ProgramName, tmpname3); +#else + if (!freopen(tmpname2, "w+", stdin)) + fatal("%s: can't open file '%s'\n", ProgramName, tmpname2); + fputs(defines, stdin); + fprintf(stdin, "\n#include \"%s\"\n", filename); + fflush(stdin); + fseek(stdin, 0, 0); + sprintf(cmd, "%s%s", cpp_program, includes); + if (!(input = popen(cmd, "r"))) + fatal("%s: cannot run '%s'\n", ProgramName, cmd); +#endif + } else { +#endif + if (filename) { + if (!freopen (filename, "r", stdin)) + fatal("%s: can't open file '%s'\n", ProgramName, filename); + } + if (cpp_program) { +#ifdef WIN32 + (void) mktemp(tmpname3); + sprintf(cmd, "%s%s %s %s > %s", cpp_program, includes, defines, + filename ? filename : "", tmpname3); + if (system(cmd) < 0) + fatal("%s: cannot run '%s'\n", ProgramName, cmd); + if (!(input = fopen(tmpname3, "r"))) + fatal("%s: can't open file '%s'\n", ProgramName, tmpname3); +#else + sprintf(cmd, "%s%s %s", cpp_program, includes, defines); + if (!(input = popen(cmd, "r"))) + fatal("%s: cannot run '%s'\n", ProgramName, cmd); +#endif + } else { + input = stdin; + } +#ifdef PATHETICCPP + } +#endif + ReadFile(&buffer, input); + if (cpp_program) { +#ifdef WIN32 + fclose(input); +#else + pclose(input); +#endif + } +#ifdef PATHETICCPP + if (need_real_defines) { + unlink(tmpname2); +#ifdef WIN32 + if (tmpname3[strlen(tmpname3) - 1] != 'X') + unlink(tmpname3); +#endif + } +#endif + GetEntries(&newDB, &buffer, 0); + if (execute) { + FormatEntries(&buffer, &newDB); + if (dont_execute) { + if (buffer.used > 0) { + fwrite (buffer.buff, 1, buffer.used, stdout); + if (buffer.buff[buffer.used - 1] != '\n') putchar ('\n'); + } + } else if (buffer.used > 1 || !doScreen) + StoreProperty (dpy, root, res_prop); + else + XDeleteProperty (dpy, root, res_prop); + } + } + if (execute) + FreeEntries(&newDB); + if (doScreen && xdefs) + XFree(xdefs); +} + +ShuffleEntries(db, dbs, num) + Entries *db; + Entries *dbs; + int num; +{ + int *hits; + register int i, j, k; + Entries cur, cmp; + char *curtag, *curvalue; + + hits = (int *)malloc(num * sizeof(int)); + cur = dbs[0]; + for (i = 0; i < cur.used; i++) { + curtag = cur.entry[i].tag; + curvalue = cur.entry[i].value; + for (j = 1; j < num; j++) { + cmp = dbs[j]; + for (k = 0; k < cmp.used; k++) { + if (cmp.entry[k].usable && + !strcmp(curtag, cmp.entry[k].tag) && + !strcmp(curvalue, cmp.entry[k].value)) + { + hits[j] = k; + break; + } + } + if (k == cmp.used) + break; + } + if (j == num) { + AddEntry(db, &cur.entry[i]); + hits[0] = i; + for (j = 0; j < num; j++) + dbs[j].entry[hits[j]].usable = False; + } + } + free((char *)hits); +} + +ReProcess(scrno, doScreen) + int scrno; + Bool doScreen; +{ + Window root; + Atom res_prop; + register int i; + + FormatEntries(&buffer, &newDB); + if (doScreen) { + root = RootWindow(dpy, scrno); + res_prop = XInternAtom(dpy, SCREEN_RESOURCES, False); + } else { + root = RootWindow(dpy, 0); + res_prop = XA_RESOURCE_MANAGER; + } + if (dont_execute) { + if (buffer.used > 0) { + fwrite (buffer.buff, 1, buffer.used, stdout); + if (buffer.buff[buffer.used - 1] != '\n') putchar ('\n'); + } + } else { + if (buffer.used > 1 || !doScreen) + StoreProperty (dpy, root, res_prop); + else + XDeleteProperty (dpy, root, res_prop); + } + FreeEntries(&newDB); +} + +#if NeedVarargsPrototypes +fatal(char *msg, ...) +#else +fatal(msg, x1, x2, x3, x4, x5, x6) + char *msg; + int x1, x2, x3, x4, x5, x6; +#endif +{ + extern int errno; +#if NeedVarargsPrototypes + va_list args; +#endif + + if (errno) + perror(ProgramName); +#if NeedVarargsPrototypes + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); +#else + (void) fprintf(stderr, msg, x1, x2, x3, x4, x5, x6); +#endif + exit(1); +} diff --git a/programs/xrdb/xrdb.man b/programs/xrdb/xrdb.man new file mode 100644 index 000000000..0d23347d4 --- /dev/null +++ b/programs/xrdb/xrdb.man @@ -0,0 +1,303 @@ +.\" $XConsortium: xrdb.man,v 11.38 94/04/18 18:07:04 rws Exp $ +.\" Copyright 1991, Digital Equipment Corporation. +.\" Copyright (c) 1991, 1994 X Consortium +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining +.\" a copy of this software and associated documentation files (the +.\" "Software"), to deal in the Software without restriction, including +.\" without limitation the rights to use, copy, modify, merge, publish, +.\" distribute, sublicense, and/or sell copies of the Software, and to +.\" permit persons to whom the Software is furnished to do so, subject to +.\" the following conditions: +.\" +.\" The above copyright notice and this permission notice shall be included +.\" in all copies or substantial portions of the Software. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +.\" IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +.\" OTHER DEALINGS IN THE SOFTWARE. +.\" +.\" Except as contained in this notice, the name of the X Consortium shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from the X Consortium. +.TH XRDB 1 "Release 6" "X Version 11" +.SH NAME +xrdb - X server resource database utility +.SH SYNOPSIS +.B xrdb +[-option ...] [\fIfilename\fP] +.SH DESCRIPTION +.I Xrdb +is used to get or set the contents of the RESOURCE_MANAGER property +on the root window of screen 0, or the SCREEN_RESOURCES property on +the root window of any or all screens, or everything combined. +You would normally run this program from your X startup file. +.LP +Most X clients use the RESOURCE_MANAGER and SCREEN_RESOURCES properties to +get user preferences about +color, fonts, and so on for applications. Having this information in +the server (where it is available to all clients) instead of on disk, +solves the problem in previous versions of X that required you to +maintain \fIdefaults\fP files on every machine that you might use. +It also allows for dynamic changing of defaults without editing files. +.LP +The RESOURCE_MANAGER property is used for resources that apply to all +screens of the display. The SCREEN_RESOURCES property on each screen +specifies additional (or overriding) resources to be used for that screen. +(When there is only one screen, SCREEN_RESOURCES is normally not used, +all resources are just placed in the RESOURCE_MANAGER property.) +.LP +The file specified by +.I filename +(or the contents from standard input if - or no filename is given) +is optionally passed through the C preprocessor with the +following symbols defined, based on the capabilities of the server +being used: +.TP 8 +.B SERVERHOST=\fIhostname\fP +the hostname portion of the display to which you are connected. +.TP 8 +.B SRVR_\fIname\fB +the SERVERHOST hostname string turned into a legal identifier. +For example, "my-dpy.lcs.mit.edu" becomes SRVR_my_dpy_lcs_mit_edu. +.TP 8 +.B HOST=\fIhostname\fP +the same as +.BR SERVERHOST . +.TP 8 +.B DISPLAY_NUM=\fInum\fP +the number of the display on the server host. +.TP 8 +.B CLIENTHOST=\fIhostname\fP +the name of the host on which +.I xrdb +is running. +.TP 8 +.B CLNT_\fIname\fB +the CLIENTHOST hostname string turned into a legal identifier. +For example, "expo.lcs.mit.edu" becomes CLNT_expo_lcs_mit_edu. +.TP 8 +.B RELEASE=\fInum\fP +the vendor release number for the server. The interpretation of this +number will vary depending on VENDOR. +.TP 8 +.B REVISION=\fInum\fP +the X protocol minor version supported by this server (currently 0). +.TP 8 +.B VERSION=\fInum\fP +the X protocol major version supported by this server (should always be 11). +.TP 8 +.B VENDOR="\fIvendor\fP" +a string literal specifying the vendor of the server. +.TP 8 +.B VNDR_\fIname\fP +the VENDOR name string turned into a legal identifier. +For example, "MIT X Consortium" becomes VNDR_MIT_X_Consortium. +.TP 8 +.B EXT_\fIname\fP +A symbol is defined for each protocol extension supported by the server. +Each extension string name is turned into a legal identifier. +For example, "X3D-PEX" becomes EXT_X3D_PEX. +.TP 8 +.B NUM_SCREENS=\fInum\fP +the total number of screens. +.TP 8 +.B SCREEN_NUM=\fInum\fP +the number of the current screen (from zero). +.TP 8 +.B BITS_PER_RGB=\fInum\fP +the number of significant bits in an RGB color specification. This is the +log base 2 of the number of distinct shades of each primary that the hardware +can generate. Note that it usually is not related to PLANES. +.TP 8 +.B CLASS=\fIvisualclass\fP +one of StaticGray, GrayScale, StaticColor, PseudoColor, TrueColor, +DirectColor. This is the visual class of the root window. +.TP 8 +.B CLASS_\fIvisualclass\fP=\fIvisualid\fP +the visual class of the root window in a form you can \fI#ifdef\fP on. +The value is the numeric id of the visual. +.TP 8 +.B COLOR +defined only if CLASS is one of StaticColor, PseudoColor, TrueColor, or +DirectColor. +.TP 8 +.B CLASS_\fIvisualclass\fP_\fIdepth\fP=\fInum\fP +A symbol is defined for each visual supported for the screen. +The symbol includes the class of the visual and its depth; +the value is the numeric id of the visual. +(If more than one visual has the same class and depth, the numeric id +of the first one reported by the server is used.) +.TP 8 +.B HEIGHT=\fInum\fP +the height of the root window in pixels. +.TP 8 +.B WIDTH=\fInum\fP +the width of the root window in pixels. +.TP 8 +.B PLANES=\fInum\fP +the number of bit planes (the depth) of the root window. +.TP 8 +.B X_RESOLUTION=\fInum\fP +the x resolution of the screen in pixels per meter. +.TP 8 +.B Y_RESOLUTION=\fInum\fP +the y resolution of the screen in pixels per meter. +.LP +SRVR_\fIname\fP, CLNT_\fIname\fP, VNDR_\fIname\fP, and EXT_\fIname\fP +identifiers are formed by changing all characters other than letters +and digits into underscores (_). +.LP +Lines that begin with an exclamation mark (!) are ignored and may +be used as comments. +.LP +Note that since +.I xrdb +can read from standard input, it can be used to +the change the contents of properties directly from +a terminal or from a shell script. +.SH "OPTIONS" +.PP +.I xrdb +program accepts the following options: +.TP 8 +.B \-help +This option (or any unsupported option) will cause a brief description of +the allowable options and parameters to be printed. +.TP 8 +.B \-display \fIdisplay\fP +This option specifies the X server to be used; see \fIX(1)\fP. +It also specifies the screen to use for the \fI-screen\fP option, +and it specifies the screen from which preprocessor symbols are +derived for the \fI-global\fP option. +.TP 8 +.B \-all +This option indicates that operation should be performed on the +screen-independent resource property (RESOURCE_MANAGER), as well as +the screen-specific property (SCREEN_RESOURCES) on every screen of the +display. For example, when used in conjunction with \fI-query\fP, +the contents of all properties are output. For \fI-load\fP, \fI-override\fP +and \fI-merge\fP, +the input file is processed once for each screen. The resources which occur +in common in the output for every screen are collected, and these are applied +as the screen-independent resources. The remaining resources are applied +for each individual per-screen property. This the default mode of operation. +.TP 8 +.B \-global +This option indicates that the operation should only be performed on +the screen-independent RESOURCE_MANAGER property. +.TP 8 +.B \-screen +This option indicates that the operation should only be performed on +the SCREEN_RESOURCES property of the default screen of the display. +.TP 8 +.B \-screens +This option indicates that the operation should be performed on +the SCREEN_RESOURCES property of each screen of the display. +For \fI-load\fP, \fI-override\fP and \fI-merge\fP, the input file is +processed for each screen. +.TP 8 +.B \-n +This option indicates that changes to the specified properties (when used with +\fI-load\fP, \fI-override\fP or \fI-merge\fP) +or to the resource file (when used with \fI-edit\fP) should be shown on the +standard output, but should not be performed. +.TP 8 +.B \-quiet +This option indicates that warning about duplicate entries should not be +displayed. +.TP 8 +.B -cpp \fIfilename\fP +This option specifies the pathname of the C preprocessor program to be used. +Although +.I xrdb +was designed to use CPP, any program that acts as a filter +and accepts the -D, -I, and -U options may be used. +.TP 8 +.B -nocpp +This option indicates that +.I xrdb +should not run the input file through a preprocessor before loading it +into properties. +.TP 8 +.B \-symbols +This option indicates that the symbols that are defined for the preprocessor +should be printed onto the standard output. +.TP 8 +.B \-query +This option indicates that the current contents of the specified +properties should be printed onto the standard output. Note that since +preprocessor commands in the input resource file are part of the input +file, not part of the property, they won't appear in the output from this +option. The +.B \-edit +option can be used to merge the contents of properties back into the input +resource file without damaging preprocessor commands. +.TP 8 +.B \-load +This option indicates that the input should be loaded as the new value +of the specified properties, replacing whatever was there (i.e. +the old contents are removed). This is the default action. +.TP 8 +.B \-override +This option indicates that the input should be added to, instead of +replacing, the current contents of the specified properties. +New entries override previous entries. +.TP 8 +.B \-merge +This option indicates that the input should be merged and lexicographically +sorted with, instead of replacing, the current contents of the specified +properties. +.TP 8 +.B \-remove +This option indicates that the specified properties should be removed +from the server. +.TP 8 +.B \-retain +This option indicates that the server should be instructed not to reset if +\fIxrdb\fP is the first client. This never be necessary under normal +conditions, since \fIxdm\fP and \fIxinit\fP always act as the first client. +.TP 8 +.B \-edit \fIfilename\fP +This option indicates that the contents of the specified properties +should be edited into the given file, replacing any values already listed +there. This allows you to put changes that you have made to your defaults +back into your resource file, preserving any comments or preprocessor lines. +.TP 8 +.B \-backup \fIstring\fP +This option specifies a suffix to be appended to the filename used with +.B \-edit +to generate a backup file. +.TP 8 +.B \-D\fIname[=value]\fP +This option is passed through to the preprocessor and is used to define +symbols for use with conditionals such as +.I# ifdef. +.TP 8 +.B \-U\fIname\fP +This option is passed through to the preprocessor and is used to remove +any definitions of this symbol. +.TP 8 +.B \-I\fIdirectory\fP +This option is passed through to the preprocessor and is used to specify +a directory to search for files that are referenced with +.I #include. +.SH FILES +Generalizes \fI~/.Xdefaults\fP files. +.SH "SEE ALSO" +X(1), Xlib Resource Manager documentation, Xt resource documentation +.SH ENVIRONMENT +.TP 8 +.B DISPLAY +to figure out which display to use. +.SH BUGS +.PP +The default for no arguments should be to query, not to overwrite, so that +it is consistent with other programs. +.SH AUTHORS +Bob Scheifler, Phil Karlton, rewritten from the original by Jim Gettys |