/* * Copyright (c) 1990, 2015, Oracle and/or its affiliates. All rights reserved. * * 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 (including the next * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. * */ #include #include #include #include "cmcutil.h" #include "cmc.h" /* ** Common utility routines shared by the Workspace Colors programs ** cmcsave, cmcshow, cmcinit. */ /*ARGSUSED*/ static int disp_err_handler (Display *dpy) { fatal_error("cannot open display \"%s\"", display_name); } /* ** Open display and handle any errors. */ Display * open_display (const char *dpyname) { Display *dpy; /* ** Catch errors opening display so user doesn't ** get confusing 'XIOError: Broken Pipe' message. */ XSetIOErrorHandler(disp_err_handler); display_name = XDisplayName(dpyname); if (!(dpy = XOpenDisplay(dpyname))) return NULL; XSync(dpy, 0); XSetIOErrorHandler(NULL); return dpy; } /* ** Return true if default visual of screen is dynamic. */ int dynamic_indexed_default_visual (Screen *screen) { int class = DefaultVisualOfScreen(screen)->class; return (class == GrayScale || class == PseudoColor); } /* ** If file name is not already absolute, make absolute ** relative to home directory. */ static const char * fn_absolutize (const char *relname) { static char filename[256]; const char *homedir; if (*relname == '/') return relname; if (!(homedir = (char *) getenv("HOME"))) homedir = "/"; sprintf(filename, "%s/%s", homedir, relname); return filename; } const char * comp_colors_filename (const char *basename) { if (!basename) basename = COMPACTED_COLORS_FILE; return fn_absolutize(basename); } int cmc_write ( FILE *f, int scr_num, int ncolors, XColor *colors) { (void)fwrite(&scr_num, sizeof(int), 1, f); (void)fwrite(&ncolors, sizeof(int), 1, f); (void)fwrite(colors, sizeof(XColor), ncolors, f); return 1; } /* ** 0 is returned on EOF; 1 otherwise */ int cmc_read ( FILE *f, int *scr_num, int *ncolors, XColor **colors) { if (!fread(scr_num, sizeof(int), 1, f)) return 0; if (!fread(ncolors, sizeof(int), 1, f)) { fprintf(stderr, "error: premature end-of-file\n"); fatal_error("cannot read number of saved colors"); } if (!(*colors = (XColor *) malloc(*ncolors * sizeof(XColor)))) fatal_error("not enough memory"); if (!fread(*colors, sizeof(XColor), *ncolors, f)) { fprintf(stderr, "error: premature end-of-file\n"); fatal_error("cannot read saved colors"); } return 1; } void cmc_header_write ( FILE *f) { int value; /* write magic number and version */ value = CMC_MAGIC; (void)fwrite(&value, sizeof(int), 1, f); value = CMC_VERSION; (void)fwrite(&value, sizeof(int), 1, f); } void cmc_header_test ( FILE *f) { int value; /* check magic number */ if (!fread(&value, sizeof(int), 1, f) || value != CMC_MAGIC) fatal_error("Unrecognized colors file. Expected magic number = %x, \ Actual = %x", CMC_MAGIC, value); /* check version number */ if (!fread(&value, sizeof(int), 1, f) || value != CMC_VERSION) fatal_error("Unrecognized colors file. Expected version number = %x, \ Actual = %x", CMC_VERSION, value); } void prop_update ( Display *dpy, Window w, const char *name, Atom type, int format, int data, int nelem) { /* intern the property name */ Atom atom = XInternAtom(dpy, name, 0); /* create or replace the property */ XChangeProperty(dpy, w, atom, type, format, PropModeReplace, (unsigned char *)&data, nelem); } /* ** Sets the close-down mode of the cmc client to 'RetainPermanent' ** so all client resources will be preserved after the client ** exits. Puts a property on the default root window containing ** an XID of the client so that the resources can later be killed. */ void resource_preserve ( Display *dpy) { Window w = DefaultRootWindow(dpy); /* create dummy resource */ Pixmap pm = XCreatePixmap(dpy, w, 1, 1, 1); /* create/replace the property */ prop_update(dpy, w, RETAIN_PROP_NAME, XA_PIXMAP, 32, (int)pm, 1); /* retain all client resources until explicitly killed */ XSetCloseDownMode(dpy, RetainPermanent); } /* ** Flushes any resources previously retained by a cmc client, ** if any exist. */ void resource_discard ( Display *dpy) { Pixmap *pm; Atom actual_type; /* NOTUSED */ int format; unsigned long nitems; unsigned long bytes_after; /* intern the property name */ Atom atom = XInternAtom(dpy, RETAIN_PROP_NAME, 0); /* look for existing resource allocation */ if (XGetWindowProperty(dpy, DefaultRootWindow(dpy), atom, 0, 1, 1/*delete*/, AnyPropertyType, &actual_type, &format, &nitems, &bytes_after, (unsigned char **) &pm) == Success && nitems == 1) { if (actual_type == XA_PIXMAP && format == 32 && nitems == 1 && bytes_after == 0) { /* blast it away */ XKillClient(dpy, *pm); XFree(pm); } else if (actual_type != None) { extern char *program; fprintf(stderr, "%s: warning: invalid format encountered for property %s\n", RETAIN_PROP_NAME, program); } } }