550N/A/*
1233N/A* Copyright (c) 1990, 2011, Oracle and/or its affiliates. All rights reserved.
550N/A*
550N/A* Permission is hereby granted, free of charge, to any person obtaining a
919N/A* copy of this software and associated documentation files (the "Software"),
919N/A* to deal in the Software without restriction, including without limitation
919N/A* the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A* and/or sell copies of the Software, and to permit persons to whom the
919N/A* Software is furnished to do so, subject to the following conditions:
550N/A*
919N/A* The above copyright notice and this permission notice (including the next
919N/A* paragraph) shall be included in all copies or substantial portions of the
919N/A* Software.
550N/A*
919N/A* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A* DEALINGS IN THE SOFTWARE.
550N/A*
550N/A*/
550N/A
550N/A
550N/A#include <stdio.h>
550N/A#include <X11/Xlib.h>
550N/A#include <X11/Xatom.h>
550N/A#include "cmcutil.h"
550N/A#include "cmc.h"
550N/A
550N/A
550N/A/*
550N/A** Common utility routines shared by the Workspace Colors programs
550N/A** cmcsave, cmcshow, cmcinit.
550N/A*/
550N/A
550N/A/*ARGSUSED*/
1233N/Astatic int
1233N/Adisp_err_handler (Display *dpy)
550N/A
550N/A{
550N/A fatal_error("cannot open display \"%s\"", display_name);
550N/A}
550N/A
550N/A/*
550N/A** Open display and handle any errors.
550N/A*/
550N/A
550N/ADisplay *
550N/Aopen_display (dpyname)
550N/Achar *dpyname;
550N/A
550N/A{
550N/A Display *dpy;
550N/A
550N/A /*
550N/A ** Catch errors opening display so user doesn't
550N/A ** get confusing 'XIOError: Broken Pipe' message.
550N/A */
550N/A XSetIOErrorHandler(disp_err_handler);
550N/A
550N/A display_name = XDisplayName(dpyname);
550N/A if (!(dpy = XOpenDisplay(dpyname)))
550N/A return NULL;
550N/A
550N/A XSync(dpy, 0);
550N/A XSetIOErrorHandler(NULL);
550N/A
550N/A return dpy;
550N/A}
550N/A
550N/A
550N/A/*
550N/A** Return true if default visual of screen is dynamic.
550N/A*/
550N/A
550N/Aint
550N/Adynamic_indexed_default_visual (screen)
550N/AScreen *screen;
550N/A
550N/A{
550N/A int class = DefaultVisualOfScreen(screen)->class;
550N/A
550N/A return (class == GrayScale ||
550N/A class == PseudoColor);
550N/A}
550N/A
550N/A/*
550N/A** If file name is not already absolute, make absolute
550N/A** relative to home directory.
550N/A*/
550N/A
1233N/Astatic const char *
1233N/Afn_absolutize (const char *relname)
550N/A
550N/A{
550N/A static char filename[256];
1233N/A const char *homedir;
550N/A
550N/A if (*relname == '/')
550N/A return relname;
550N/A
550N/A if (!(homedir = (char *) getenv("HOME")))
550N/A homedir = "/";
550N/A sprintf(filename, "%s/%s", homedir, relname);
550N/A return filename;
550N/A}
550N/A
550N/A
1233N/Aconst char *
1233N/Acomp_colors_filename (const char *basename)
550N/A
550N/A{
550N/A if (!basename)
550N/A basename = COMPACTED_COLORS_FILE;
550N/A return fn_absolutize(basename);
550N/A
550N/A}
550N/A
550N/Aint
1233N/Acmc_write (
1233N/A FILE *f,
1233N/A int scr_num,
1233N/A int ncolors,
1233N/A XColor *colors)
550N/A
550N/A{
550N/A (void)fwrite(&scr_num, sizeof(int), 1, f);
550N/A (void)fwrite(&ncolors, sizeof(int), 1, f);
550N/A (void)fwrite(colors, sizeof(XColor), ncolors, f);
550N/A
550N/A return 1;
550N/A}
550N/A
550N/A
550N/A/*
550N/A** 0 is returned on EOF; 1 otherwise
550N/A*/
550N/A
550N/Aint
1233N/Acmc_read (
1233N/A FILE *f,
1233N/A int *scr_num,
1233N/A int *ncolors,
1233N/A XColor **colors)
550N/A
550N/A{
550N/A if (!fread(scr_num, sizeof(int), 1, f))
550N/A return 0;
550N/A
550N/A if (!fread(ncolors, sizeof(int), 1, f)) {
550N/A fprintf(stderr, "error: premature end-of-file\n");
550N/A fatal_error("cannot read number of saved colors");
550N/A }
550N/A
550N/A if (!(*colors = (XColor *) malloc(*ncolors * sizeof(XColor))))
550N/A fatal_error("not enough memory");
550N/A
550N/A if (!fread(*colors, sizeof(XColor), *ncolors, f)) {
550N/A fprintf(stderr, "error: premature end-of-file\n");
550N/A fatal_error("cannot read saved colors");
550N/A }
550N/A
550N/A return 1;
550N/A}
550N/A
550N/A
550N/Avoid
1233N/Acmc_header_write (
1233N/A FILE *f)
550N/A
550N/A{
550N/A int value;
550N/A
550N/A /* write magic number and version */
550N/A value = CMC_MAGIC;
550N/A (void)fwrite(&value, sizeof(int), 1, f);
550N/A value = CMC_VERSION;
550N/A (void)fwrite(&value, sizeof(int), 1, f);
550N/A}
550N/A
550N/A
550N/Avoid
1233N/Acmc_header_test (
1233N/A FILE *f)
550N/A
550N/A{
550N/A int value;
550N/A
550N/A /* check magic number */
550N/A if (!fread(&value, sizeof(int), 1, f) ||
550N/A value != CMC_MAGIC)
550N/A fatal_error("Unrecognized colors file. Expected magic number = %x, \
550N/AActual = %x", CMC_MAGIC, value);
550N/A
550N/A /* check version number */
550N/A if (!fread(&value, sizeof(int), 1, f) ||
550N/A value != CMC_VERSION)
550N/A fatal_error("Unrecognized colors file. Expected version number = %x, \
550N/AActual = %x", CMC_VERSION, value);
550N/A}
550N/A
550N/A
550N/Avoid
1233N/Aprop_update (
1233N/A Display *dpy,
1233N/A Window w,
1233N/A const char *name,
1233N/A Atom type,
1233N/A int format,
1233N/A int data,
1233N/A int nelem)
550N/A
550N/A{
550N/A /* intern the property name */
550N/A Atom atom = XInternAtom(dpy, name, 0);
550N/A
550N/A /* create or replace the property */
550N/A XChangeProperty(dpy, w, atom, type, format, PropModeReplace,
550N/A (unsigned char *)&data, nelem);
550N/A}
550N/A
550N/A
550N/A/*
550N/A** Sets the close-down mode of the cmc client to 'RetainPermanent'
550N/A** so all client resources will be preserved after the client
550N/A** exits. Puts a property on the default root window containing
550N/A** an XID of the client so that the resources can later be killed.
550N/A*/
550N/A
550N/Avoid
1233N/Aresource_preserve (
1233N/A Display *dpy)
550N/A
550N/A{
550N/A Window w = DefaultRootWindow(dpy);
550N/A
550N/A /* create dummy resource */
550N/A Pixmap pm = XCreatePixmap(dpy, w, 1, 1, 1);
550N/A
550N/A /* create/replace the property */
550N/A prop_update(dpy, w, RETAIN_PROP_NAME, XA_PIXMAP, 32, (int)pm, 1);
550N/A
550N/A /* retain all client resources until explicitly killed */
550N/A XSetCloseDownMode(dpy, RetainPermanent);
550N/A}
550N/A
550N/A
550N/A/*
550N/A** Flushes any resources previously retained by a cmc client,
550N/A** if any exist.
550N/A*/
550N/A
550N/Avoid
1233N/Aresource_discard (
1233N/A Display *dpy)
550N/A
550N/A{
550N/A Pixmap *pm;
550N/A Atom actual_type; /* NOTUSED */
550N/A int format;
1233N/A unsigned long nitems;
1233N/A unsigned long bytes_after;
550N/A
550N/A /* intern the property name */
550N/A Atom atom = XInternAtom(dpy, RETAIN_PROP_NAME, 0);
550N/A
550N/A /* look for existing resource allocation */
550N/A if (XGetWindowProperty(dpy, DefaultRootWindow(dpy), atom, 0, 1,
550N/A 1/*delete*/, AnyPropertyType, &actual_type, &format, &nitems,
1233N/A &bytes_after, (unsigned char **) &pm) == Success
1233N/A && nitems == 1) {
550N/A
550N/A if (actual_type == XA_PIXMAP && format == 32 &&
550N/A nitems == 1 && bytes_after == 0) {
550N/A /* blast it away */
1233N/A XKillClient(dpy, *pm);
550N/A XFree(pm);
550N/A } else if (actual_type != None) {
550N/A extern char *program;
550N/A fprintf(stderr, "%s: warning: invalid format encountered for property %s\n",
550N/A RETAIN_PROP_NAME, program);
1233N/A }
550N/A }
550N/A}
550N/A
550N/A
550N/A
550N/A