v01i008: palette, a colormix tool, Part 01/02
Charles Mcgrew
mcgrew at dartagnan.rutgers.edu
Fri May 19 06:59:18 AEST 1989
Submitted-by: Wayne Mesard <mesard at bbn.com>
Posting-number: Volume 1, Issue 8
Archive-name: palette/part01
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# README
# README.mod
# MANIFEST
# mono.icon
# palette.c
# palette.l
# patchlevel.h
# wsm_types.h
# This archive created: Thu May 18 14:03:18 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(1094 characters)'
if test -f 'README'
then
echo shar: will not over-write existing file "'README'"
else
sed 's/^ X//' << \SHAR_EOF > 'README'
XTo build palette, type
X
X make
X
XTo install it, change the MANDIR, MANEXT and BINDIR in the Makefile as
Xappropriate, and type
X
X make install
X
XSee the man page for details.
X
XPalette was developed on a color Sun 3/160 under SunOS 3.4.
XAny bug reports, comments or suggestions would be appreciated
X
Xpalette - a colormap editor
XCopyright (c) 1988 Wayne Mesard
X
XThis is free software. It may be reproduced, retransmitted,
Xredistributed and otherwise propogated at will, provided that
Xno monetary profit is realized and that this notice remains
Xintact and in place.
X
XChanges made from v1.0p0 to v1.1:
X
X o Fixed the hideous missing 2nd arg to open(2).
X o Arrow keys now handled the "right" wrong way [sic].
X o Added Delete Map ability.
X o New file format: RGB Lists.
X o Added ability to load from files (in any of the 4 supported formats).
X o Various minor fixes to control names, minor performance improvements, etc.
X o Added more runtime error messages.
X
XWayne Mesard
XBolt Beranek and Newman mesard at bbn.com
X70 Fawcett St. 617-873-1878
XCambridge, MA 02138
X
X
SHAR_EOF
if test 1094 -ne "`wc -c < 'README'`"
then
echo shar: error transmitting "'README'" '(should have been 1094 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README.mod'" '(265 characters)'
if test -f 'README.mod'
then
echo shar: will not over-write existing file "'README.mod'"
else
sed 's/^ X//' << \SHAR_EOF > 'README.mod'
X This is a thing that will allow you to futz with your color levels.
XThe author says it works under 3.4, and it also works under 4.0.
X
X I could not get the color icon (which is not used in the actual
Xcode anyway) to work, but the b&w icon works fine.
X
XCharles
X
SHAR_EOF
if test 265 -ne "`wc -c < 'README.mod'`"
then
echo shar: error transmitting "'README.mod'" '(should have been 265 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'MANIFEST'" '(620 characters)'
if test -f 'MANIFEST'
then
echo shar: will not over-write existing file "'MANIFEST'"
else
sed 's/^ X//' << \SHAR_EOF > 'MANIFEST'
X File Name Archive # Description
X----------------------------------------------------------
X README 1
X README.mod 1 Moderators comments
X MANIFEST 1 This shipping list
X Makefile 2
X canvas.c 2
X color.icon 2
X desktop.c 2
X hash.c 2
X hash.h 2
X left_arrow.pr 2
X mono.icon 1
X palette.c 1
X palette.l 1
X patchlevel.h 1
X right_arrow.pr 2
X wsm_types.h 1
X
SHAR_EOF
if test 620 -ne "`wc -c < 'MANIFEST'`"
then
echo shar: error transmitting "'MANIFEST'" '(should have been 620 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'mono.icon'" '(1934 characters)'
if test -f 'mono.icon'
then
echo shar: will not over-write existing file "'mono.icon'"
else
sed 's/^ X//' << \SHAR_EOF > 'mono.icon'
X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
X */
X 0x7FFF,0xFFFF,0xFFFF,0xFFFE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
X 0xE000,0x0000,0x0000,0x0007,0xC000,0x0000,0x0000,0x0003,
X 0xC000,0x0000,0x0000,0x0003,0xC000,0x007F,0xFFE0,0x0003,
X 0xC000,0x0380,0x001E,0x0003,0xC000,0x0C00,0x0001,0x8003,
X 0xC000,0x0802,0x0000,0xC003,0xC000,0x31E7,0x0000,0x6003,
X 0xC000,0xC3FF,0x8000,0x1003,0xC001,0x03FF,0x8000,0x0803,
X 0xC006,0x03FF,0xC000,0x0403,0xC008,0x01FF,0xC000,0x0603,
X 0xC010,0xA1FF,0x8000,0x0303,0xC011,0xB1FF,0x8000,0x0103,
X 0xC022,0xE9FF,0x8000,0x0103,0xC047,0x7CFC,0x0000,0x0103,
X 0xC04D,0xDC00,0x0000,0x0103,0xC08B,0xB400,0x0000,0x0103,
X 0xC086,0xEC00,0x0000,0x0303,0xC107,0x7E00,0x0000,0x0603,
X 0xC105,0xBC00,0x0000,0x0403,0xC103,0xE800,0x0000,0x1803,
X 0xC210,0x3000,0x0001,0xE003,0xC22A,0x0000,0xFC03,0x0003,
X 0xC255,0x0001,0x0206,0x0003,0xC2AA,0x8002,0x010C,0x0003,
X 0xC255,0x0004,0x0088,0x0003,0xC2AA,0x8004,0x0098,0x0003,
X 0xC255,0x0004,0x0090,0x0003,0xC2AA,0x8004,0x0090,0x0003,
X 0xC255,0x0004,0x0090,0x0003,0xC22A,0x8004,0x0090,0x0003,
X 0xC254,0x0002,0x0110,0x0003,0xC200,0x1801,0x0210,0x0003,
X 0xC201,0xC000,0xFC08,0x0003,0xC206,0x2400,0x000C,0x0003,
X 0xC211,0x9000,0x0006,0x0003,0xC210,0x8400,0x0003,0x0003,
X 0xC10A,0x1000,0x0000,0xC003,0xC112,0xAC00,0x0000,0x2003,
X 0xC118,0xC800,0x0000,0x1803,0xC087,0xA0A0,0x0000,0x0403,
X 0xC080,0x2018,0x0000,0x0203,0xC0CB,0xC232,0x0000,0x0203,
X 0xC021,0x032C,0x0000,0x0203,0xC030,0x0484,0x0000,0x0203,
X 0xC010,0x05A1,0x0000,0x0203,0xC008,0x0208,0x0000,0x0203,
X 0xC00C,0x04A2,0x0000,0x0203,0xC004,0x0158,0x0000,0x0203,
X 0xC003,0x00A4,0x0000,0x0403,0xC000,0xC010,0x0000,0x0803,
X 0xC000,0x7048,0x0000,0x1003,0xC000,0x0800,0x0000,0x2003,
X 0xC000,0x0700,0x0001,0xC003,0xC000,0x00FC,0x000E,0x0003,
X 0xC000,0x0003,0xFFF0,0x0003,0xC000,0x0000,0x0000,0x0003,
X 0xC000,0x0000,0x0000,0x0003,0xE000,0x0000,0x0000,0x0007,
X 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x7FFF,0xFFFF,0xFFFF,0xFFFE
X
SHAR_EOF
if test 1934 -ne "`wc -c < 'mono.icon'`"
then
echo shar: error transmitting "'mono.icon'" '(should have been 1934 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'palette.c'" '(38447 characters)'
if test -f 'palette.c'
then
echo shar: will not over-write existing file "'palette.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'palette.c'
X/*
X * palette.c - This file contains the program's main processing routines
X * including all window creation, event handlers and
X * the routines for manipulating colors and color maps.
X *
X * Exported routines:
X * main (duh)
X * MakeCMS
X */
X
X/**************************************************************************
X * palette - a colormap editor
X * Copyright (c) 1988 Wayne Mesard *
X * *
X * This is free software. It may be reproduced, retransmitted, *
X * redistributed and otherwise propogated at will, provided that *
X * no monetary profit is realized and that this notice remains *
X * intact and in place. *
X * *
X * Please direct bug reports, code enhancements and comments *
X * to mesard at BBN.COM. *
X * *
X **************************************************************************/
X
X#include <suntool/sunview.h>
X#include <suntool/panel.h>
X#include <suntool/canvas.h>
X#include <strings.h>
X#include <ctype.h>
X#include <stdio.h>
X
X#include "patchlevel.h"
X#include "wsm_types.h"
X#include "hash.h"
X
X#define MAX_COLORS 256
X#define MAX_BRIGHTNESS 255
X
X#define MAX_COLORS_STR_LEN 9
X
X#define PALETTE_H 160
X#define BUTT_SIZE 11
X#define NUM_MY_WINDOWS 4
X
Xenum updatecolor_msg {U_NEW_STATE, U_NEW_COLOR, U_NEW_CMS};
X
X
Xstatic short mono_image[] = {
X# include "mono.icon"
X};
Xmpr_static(mono_pr, 64, 64, 1, mono_image);
XDEFINE_ICON_FROM_IMAGE(mono_icon, mono_image);
X
Xstatic short color_image[] = {
X# include "color.icon"
X};
Xmpr_static(color_pr, 64, 64, 8, color_image);
Xstatic Icon color_icon;
X
X
Xstatic short left_arrow_array[] = {
X# include "left_arrow.pr"
X};
Xmpr_static(left_arrow, 16, 16, 1, left_arrow_array);
X
Xstatic short right_arrow_array[] = {
X# include "right_arrow.pr"
X};
Xmpr_static(right_arrow, 16, 16, 1, right_arrow_array);
X
X
Xstatic use_colormap = false;
Xstatic boolean shallow_walkP = false;
Xstatic Pixwin *my_pixies[NUM_MY_WINDOWS];
X
Xstatic Panel_item sliders[3];
Xstatic Panel_item avg_markers[3];
Xstatic Panel_item new_map_size;
Xstatic Panel_item step_size_item;
Xstatic Panel_item proportional_item;
Xstatic Panel_item reset_on_reread;
Xstatic Panel_item file_type;
Xstatic Panel_item file_name;
X
Xstatic int cur_entry = 0;
Xstatic int cur_range_end = 0;
Xstatic int cur_size;
Xstatic char *cur_name;
Xstatic Panel_item cur_cms_item;
Xstatic struct cms_map cur_map;
X
Xstatic unsigned char clipboard_red[MAX_COLORS];
Xstatic unsigned char clipboard_green[MAX_COLORS];
Xstatic unsigned char clipboard_blue[MAX_COLORS];
Xstatic struct cms_map clipboard =
X {clipboard_red, clipboard_green, clipboard_blue};
Xstatic short clipboard_entries = 0;
X
Xstatic Frame frame;
Xstatic int my_frame_fd;
Xstatic Panel control_panel, table_panel;
Xstatic Panel_item cur_color_item;
Xstatic Panel_item msg_item;
Xstatic char frame_cms_name[CMS_NAMESIZE];
Xstatic char subwins_cms_name[CMS_NAMESIZE];
X
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X extern int Get_Root();
X void InitWindow(), Message();
X void SelectCMS();
X boolean WalkWinTree();
X int rootfd, i;
X
X for (i = argc; i>1;)
X if (argv[--i][0] == '-')
X if (argv[i][1] == 'f')
X shallow_walkP = true;
X else if (argv[i][1] == 's')
X use_colormap = true;
X /* else This must be an arg for the frame. */
X
X H_MakeNull();
X InitWindow(argc, argv);
X
X if ((rootfd=Get_Root(frame))==-1) {
X fprintf(stderr, "%s: Error opening screen's root window\n", argv[0]);
X exit(1);
X /*NOTREACHED*/
X }
X
X if (!WalkWinTree(rootfd, shallow_walkP))
X Message("<Error: CMS table full. Not all windows processed.>", 0);
X (void) close(rootfd);
X (void) WalkWinTree(my_frame_fd, true); /* Since it's not in the tree yet. */
X cur_name = NULL;
X SelectCMS(frame_cms_name);
X window_main_loop(frame);
X}
X
X
X
X/*
X * InitWindow - Set up all the windows and panel items.
X */
X
Xstatic void InitWindow(argc, argv)
Xint argc;
Xchar **argv;
X{
X extern Pixwin *MakePalette();
X void slider_notify();
X void ArrowEvent();
X void Copy(), Paste();
X Panel_setting KeyedEntry(), NumericText();
X void ClickOnCMS();
X void KeyEvent();
X void UseColorMap(), WalkDepth();
X void ResizeCanvas(), CanvasEvent();
X void CreateNewMap(), Reread_Maps(), Save(), Load(), Quit();
X
X static char RGBName[][6] = {"Red ", "Green", "Blue "};
X Canvas canvas;
X char buf[16];
X int i, row = -1;
X unsigned char **ptr;
X
X
X color_icon = icon_create(ICON_IMAGE, &color_pr, 0);
X
X frame = window_create(NULL, FRAME,
X FRAME_NO_CONFIRM, TRUE,
X FRAME_ICON, &mono_icon,
X FRAME_LABEL, "Palette",
X FRAME_ARGS, argc, argv,
X WIN_CONSUME_KBD_EVENT, WIN_NO_EVENTS,
X 0);
X
X control_panel = window_create(frame, PANEL,
X PANEL_ITEM_X_GAP, 5,
X WIN_EVENT_PROC, KeyEvent,
X 0);
X
X for (i= -1; ++i<3;) {
X (void) sprintf(buf, "%s:", RGBName[i]);
X switch (i) {
X case 0:
X ptr = &(cur_map.cm_red);
X break;
X case 1:
X ptr = &(cur_map.cm_green);
X break;
X case 2:
X ptr = &(cur_map.cm_blue);
X break;
X }
X
X sliders[i] = panel_create_item(control_panel, PANEL_SLIDER,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_LABEL_STRING, buf,
X PANEL_CLIENT_DATA, ptr,
X PANEL_MIN_VALUE, 0,
X PANEL_MAX_VALUE, MAX_COLORS-1,
X PANEL_SHOW_RANGE, FALSE,
X PANEL_SLIDER_WIDTH, MAX_COLORS,
X PANEL_NOTIFY_PROC, slider_notify,
X PANEL_NOTIFY_LEVEL, PANEL_ALL,
X 0);
X
X avg_markers[i] = panel_create_item(control_panel, PANEL_MESSAGE,
X PANEL_LABEL_STRING, "*",
X PANEL_LABEL_BOLD, TRUE,
X 0);
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE, &left_arrow,
X PANEL_NOTIFY_PROC, ArrowEvent,
X PANEL_CLIENT_DATA, sliders[i],
X 0);
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE, &right_arrow,
X PANEL_NOTIFY_PROC, ArrowEvent,
X PANEL_CLIENT_DATA, sliders[i],
X 0);
X
X
X }
X panel_set(control_panel, PANEL_ITEM_X_GAP, 15, 0);
X
X cur_color_item = panel_create_item(control_panel, PANEL_TEXT,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_LABEL_BOLD, TRUE,
X PANEL_LABEL_STRING, "Current Color:",
X PANEL_VALUE_STORED_LENGTH, MAX_COLORS_STR_LEN,
X PANEL_VALUE_DISPLAY_LENGTH, MAX_COLORS_STR_LEN,
X PANEL_NOTIFY_LEVEL, PANEL_ALL,
X PANEL_NOTIFY_PROC, KeyedEntry,
X 0);
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_NOTIFY_PROC, Copy,
X PANEL_LABEL_IMAGE,
X panel_button_image(control_panel,
X "Copy", BUTT_SIZE, 0),
X 0);
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_NOTIFY_PROC, Paste,
X PANEL_LABEL_IMAGE,
X panel_button_image(control_panel,
X "Paste", BUTT_SIZE, 0),
X 0);
X
X msg_item = panel_create_item(control_panel, PANEL_MESSAGE,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_LABEL_STRING, " ",
X 0);
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_NOTIFY_PROC, CreateNewMap,
X PANEL_LABEL_IMAGE,
X panel_button_image(control_panel,
X "New Map", BUTT_SIZE, 0),
X 0);
X
X new_map_size = panel_create_item(control_panel, PANEL_CYCLE,
X PANEL_ITEM_X, ATTR_COL(15),
X PANEL_ITEM_Y, ATTR_ROW(row),
X PANEL_LABEL_BOLD, TRUE,
X PANEL_LABEL_STRING, "New Map Size:",
X PANEL_CHOICE_STRINGS,
X " 2"," 4"," 8"," 16"," 32",
X " 64","128","256", 0,
X PANEL_VALUE, 7,
X 0);
X
X proportional_item = panel_create_item(control_panel, PANEL_CYCLE,
X PANEL_ITEM_X, ATTR_COL(15),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_LABEL_STRING, "Uniform Steps:",
X PANEL_LABEL_BOLD, TRUE,
X PANEL_CHOICE_STRINGS, "Yes", "No", 0,
X PANEL_VALUE, 0,
X 0);
X
X /* A bug in SunOS 3.4 causes the following item to be 2 pixels above
X * the row using screen.r.14. I have no idea why. Other fonts don't
X * seem to be effected, and other sizes of screen are shifted by
X * different distances. Anyway, the "+2" below should be adjusted or
X * removed as your system configuration dictates.
X */
X step_size_item = panel_create_item(control_panel, PANEL_TEXT,
X PANEL_LABEL_BOLD, TRUE,
X PANEL_LABEL_STRING, "Step Size:",
X PANEL_ITEM_Y, ATTR_ROW(row)+2,
X PANEL_VALUE_STORED_LENGTH, 3,
X PANEL_VALUE_DISPLAY_LENGTH, 3,
X PANEL_VALUE, "10",
X PANEL_NOTIFY_LEVEL, PANEL_ALL,
X PANEL_NOTIFY_PROC, NumericText,
X 0);
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_NOTIFY_PROC, Reread_Maps,
X PANEL_LABEL_IMAGE,
X panel_button_image(control_panel,
X "Reread Maps", BUTT_SIZE, 0),
X 0);
X
X (void) panel_create_item(control_panel, PANEL_CYCLE,
X PANEL_ITEM_X, ATTR_COL(15),
X PANEL_ITEM_Y, ATTR_ROW(row),
X PANEL_NOTIFY_PROC, WalkDepth,
X PANEL_LABEL_BOLD, TRUE,
X PANEL_LABEL_STRING, "Read From:",
X PANEL_CHOICE_STRINGS,
X "All windows", "Top level frames", 0,
X PANEL_VALUE, shallow_walkP,
X 0);
X
X reset_on_reread = panel_create_item(control_panel, PANEL_CYCLE,
X PANEL_ITEM_X, ATTR_COL(15),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_LABEL_BOLD, TRUE,
X PANEL_LABEL_STRING, "On Reread:",
X PANEL_CHOICE_STRINGS,
X "Reset table first", "Don't reset table", 0,
X 0);
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_NOTIFY_PROC, Save,
X PANEL_LABEL_IMAGE,
X panel_button_image(control_panel,
X "Save", BUTT_SIZE, 0),
X 0);
X
X file_type = panel_create_item(control_panel, PANEL_CYCLE,
X PANEL_ITEM_X, ATTR_COL(15),
X PANEL_LABEL_BOLD, TRUE,
X PANEL_LABEL_STRING, "Save Type:",
X PANEL_CHOICE_STRINGS,
X "RGB arrays", "RGB list", "Clear raster file",
X "Palette raster file", 0,
X 0);
X
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_NOTIFY_PROC, Load,
X PANEL_LABEL_IMAGE,
X panel_button_image(control_panel,
X "Load", BUTT_SIZE, 0),
X 0);
X
X
X file_name = panel_create_item(control_panel, PANEL_TEXT,
X PANEL_ITEM_X, ATTR_COL(15),
X PANEL_ITEM_Y, ATTR_ROW(row),
X PANEL_LABEL_BOLD, TRUE,
X PANEL_LABEL_STRING, "File Name:",
X PANEL_VALUE_STORED_LENGTH, 128,
X PANEL_VALUE_DISPLAY_LENGTH, 24,
X PANEL_VALUE, "palette.rgb",
X 0);
X
X (void) panel_create_item(control_panel, PANEL_BUTTON,
X PANEL_ITEM_X, ATTR_COL(0),
X PANEL_ITEM_Y, ATTR_ROW(++row),
X PANEL_NOTIFY_PROC, Quit,
X PANEL_LABEL_IMAGE,
X panel_button_image(control_panel,
X "Quit", BUTT_SIZE, 0),
X 0);
X
X (void) panel_create_item(control_panel, PANEL_CYCLE,
X PANEL_ITEM_X, ATTR_COL(15),
X PANEL_NOTIFY_PROC, UseColorMap,
X PANEL_LABEL_BOLD, TRUE,
X PANEL_LABEL_STRING, "Palette's Colormap:",
X PANEL_CHOICE_STRINGS, "Its own", "Selected", 0,
X PANEL_VALUE, use_colormap,
X 0);
X
X window_fit(control_panel);
X window_fit_width(frame);
X table_panel = window_create(frame, PANEL,
X PANEL_ITEM_X_GAP, 60,
X PANEL_EVENT_PROC, ClickOnCMS,
X WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
X WIN_ROWS, 3,
X WIN_IGNORE_KBD_EVENT, WIN_ASCII_EVENTS,
X WIN_CONSUME_PICK_EVENT, MS_LEFT,
X WIN_INPUT_DESIGNEE,
X i = (int) window_get(control_panel,
X WIN_DEVICE_NUMBER),
X 0);
X
X canvas = window_create(frame, CANVAS,
X CANVAS_RESIZE_PROC, ResizeCanvas,
X CANVAS_FIXED_IMAGE, FALSE,
X CANVAS_AUTO_CLEAR, FALSE,
X WIN_CONSUME_PICK_EVENTS,
X WIN_UP_EVENTS, LOC_DRAG,
X MS_LEFT, MS_MIDDLE, 0,
X WIN_INPUT_DESIGNEE, i,
X WIN_EVENT_PROC, CanvasEvent,
X WIN_BELOW, table_panel,
X WIN_HEIGHT, PALETTE_H,
X 0);
X
X my_pixies[0] = MakePalette(canvas);
X my_pixies[1] = (Pixwin *) window_get(frame, WIN_PIXWIN);
X my_pixies[2] = (Pixwin *) window_get(control_panel, WIN_PIXWIN);
X my_pixies[3] = (Pixwin *) window_get(table_panel, WIN_PIXWIN);
X
X pw_getcmsname(my_pixies[1], frame_cms_name);
X pw_getcmsname(my_pixies[2], subwins_cms_name);
X
X my_frame_fd = (int) window_get(frame, WIN_FD);
X window_fit_height(frame);
X}
X
X
X
X/*
X * Message - Put a string in the message line (with an optional numeric
X * argument.
X */
X
Xstatic void Message(s, i)
Xchar *s;
Xint i;
X{
X char buf[80];
X
X (void) sprintf(buf, s, i);
X panel_set(msg_item, PANEL_LABEL_STRING, buf, 0);
X}
X
X
X
X/*
X * SelectEntry - Do the work when the user selects a new color or range
X * of colors. index need not be less than range_end. The
X * sliders and the Current Color indicator are updated.
X * And the current color(s) are highlighted in the palette.
X * (Single colors are not highlighted if the colormap is of
X * size 2.)
X *
X * If index or range_end are illegal values, the routine
X * silently exits.
X */
X
Xstatic void SelectEntry(index, range_end)
Xint index, range_end;
X{
X extern void HighlightSwatch(), BoxSwatches(), DrawPalette();
X unsigned char **ptr;
X char buf[MAX_COLORS_STR_LEN+1];
X int i, j, val, prev;
X boolean avgP, avg_existsP = false;
X
X if (index > range_end) {
X if (range_end == -1)
X range_end = index;
X else {
X i = index;
X index = range_end;
X range_end = i;
X }
X }
X if (index < 0 || range_end >= cur_size)
X return;
X cur_entry = index;
X cur_range_end = range_end;
X
X DrawPalette(cur_size);
X
X if (cur_entry == cur_range_end) {
X (void) sprintf(buf, "%d", cur_entry);
X if (cur_size > 2)
X HighlightSwatch(cur_entry, cur_size-1);
X }
X else {
X BoxSwatches(cur_entry, cur_range_end);
X (void) sprintf(buf, "%d..%d", cur_entry, cur_range_end);
X }
X panel_set_value(cur_color_item, buf);
X
X for (i= -1; ++i<3;) {
X avgP = FALSE;
X ptr = (unsigned char **) panel_get(sliders[i], PANEL_CLIENT_DATA);
X for (val = 0, j = cur_entry, prev = ((*ptr)[cur_entry]);
X j <= cur_range_end; j++) {
X avgP = (avgP | (prev != ((*ptr)[j])));
X val += (prev = (*ptr)[j]);
X }
X panel_set(sliders[i], PANEL_VALUE, val/(cur_range_end-cur_entry+1), 0);
X panel_set(avg_markers[i], PANEL_SHOW_ITEM, avgP, 0);
X avg_existsP = (avg_existsP | avgP);
X }
X Message((avg_existsP ? "* Starred items represent averages." : ""), 0);
X}
X
X
X
X/*
X * slider_notify - When the user clicks on a slider, update the colormap,
X * the colormap array, and hide the slider's asterisk
X * item (in case it's on).
X */
X
Xstatic void slider_notify(slider, value, event)
XPanel_item slider;
Xint value;
XEvent *event;
X{
X void UpdateColorMaps();
X unsigned char **ptr;
X int i;
X
X ptr = (unsigned char **) panel_get(slider, PANEL_CLIENT_DATA);
X for (i=cur_entry; i <= cur_range_end; ++i)
X (*ptr)[i] = (unsigned char) value;
X
X UpdateColorMaps(U_NEW_COLOR);
X panel_set((Panel_item)panel_get(slider, PANEL_NEXT_ITEM),
X PANEL_SHOW_ITEM, FALSE, 0);
X}
X
X
X/*
X * ArrowEvent - When the user clicks on an arrow, update its slider,
X * increment the current color(s) (possibly by a linearly
X * increasing amount), update the array and the colormap,
X * and possibly turn off the color's asterisk (if all the
X * colors in the range have become equal).
X */
X
Xstatic void ArrowEvent(button, event)
XPanel_item button;
XEvent *event;
X{
X extern int atoi();
X int i, prev, new_val, total = 0;
X boolean avgP = FALSE;
X boolean proportional = (boolean) panel_get_value(proportional_item);
X int step_size = atoi(panel_get_value(step_size_item));
X Panel_item my_slider = panel_get(button, PANEL_CLIENT_DATA);
X unsigned char **ptr;
X
X if ((Pixrect *)panel_get(button, PANEL_LABEL_IMAGE) == &left_arrow)
X step_size = -step_size;
X
X ptr = (unsigned char **) panel_get(my_slider, PANEL_CLIENT_DATA);
X for (i = cur_entry, prev = -1; i <= cur_range_end; i++) {
X new_val = (*ptr)[i] + (step_size * (proportional ? i-cur_entry+1 : 1));
X if (new_val > MAX_BRIGHTNESS)
X new_val = MAX_BRIGHTNESS;
X else if (new_val < 0)
X new_val = 0;
X avgP = (avgP | (prev == -1 ? FALSE : (prev != new_val)));
X total += ((*ptr)[i] = prev = new_val);
X }
X UpdateColorMaps(U_NEW_COLOR);
X panel_set(my_slider, PANEL_VALUE, total/(cur_range_end-cur_entry+1), 0);
X panel_set((Panel_item)panel_get(my_slider, PANEL_NEXT_ITEM),
X PANEL_SHOW_ITEM, avgP, 0);
X}
X
X
X
X/*
X * Copy - Copy the current range onto the clipboard.
X */
X
Xstatic void Copy()
X{
X void UpdateColorMaps();
X int nbytes;
X
X clipboard_entries = 1+(cur_range_end-cur_entry);
X nbytes = sizeof(unsigned char)*clipboard_entries;
X bcopy((char *) cur_map.cm_red + cur_entry,
X (char *) clipboard.cm_red, nbytes);
X bcopy((char *) cur_map.cm_green + cur_entry,
X (char *) clipboard.cm_green, nbytes);
X bcopy((char *) cur_map.cm_blue + cur_entry,
X (char *) clipboard.cm_blue, nbytes);
X}
X
X
X/*
X * Paste - Paste the clipboard contents onto the current CMS starting at
X * the current entry.
X */
X
Xstatic void Paste()
X{
X void UpdateColorMaps();
X
X int nbytes = sizeof(unsigned char) *
X (clipboard_entries + cur_entry > cur_size ?
X cur_size - cur_entry : clipboard_entries);
X
X bcopy((char *) clipboard.cm_red, (char *) cur_map.cm_red + cur_entry,
X nbytes);
X bcopy((char *) clipboard.cm_green, (char *) cur_map.cm_green + cur_entry,
X nbytes);
X bcopy((char *) clipboard.cm_blue, (char *) cur_map.cm_blue + cur_entry,
X nbytes);
X UpdateColorMaps(U_NEW_COLOR);
X SelectEntry(cur_entry, cur_range_end);
X if (clipboard_entries > (nbytes / sizeof(unsigned char)))
X Message("<Only the first %d clipboard items fit.>",
X (nbytes / sizeof(unsigned char)));
X}
X
X
X
X/*
X * KeyEvent - Take the appropriate action when the user types a key.
X * Note that ascii input from all three windows are directed
X * to the control_panel.
X * All that crap with esp_seq is necessary because you
X * can't get KEY_RIGHT() events for the arrow keys. (At
X * least not on my Sun3/160.) So this routine looks for a
X * consecutive <Esc>[n, where "n" is D or C.
X */
X
Xstatic void KeyEvent(win, event, arg)
XWindow win;
XEvent *event;
Xcaddr_t arg;
X{
X void SelectEntry();
X void Quit();
X
X static short esq_seq = 0;
X
X if (esq_seq == 2)
X switch (event_id(event)) {
X case 'D':
X event_set_id(event, '<');
X break;
X case 'C':
X event_set_id(event, '>');
X break;
X }
X
X switch(event_id(event)) {
X case '\033':
X esq_seq = 1;
X break;
X case '[':
X if (esq_seq == 1)
X esq_seq = 2;
X break;
X case '<':
X SelectEntry(cur_entry-1, -1);
X esq_seq = 0;
X break;
X case '>':
X SelectEntry(cur_entry+1, -1);
X esq_seq = 0;
X break;
X case '\003':
X Quit();
X default:
X esq_seq = 0;
X window_default_event_proc(win, event, arg);
X break;
X
X }
X}
X
X
X/*
X * KeyedEntry - Preprocess keyboard input to the Current Color item.
X * Only allow digits and periods to be entered. When
X * Return is pressed, parse the text for the starting and
X * ending values of the new range. If no starting or ending
X * range is found, assume zero and the highest value in the
X * current colormap, respectively.
X */
X
Xstatic Panel_setting
XKeyedEntry(item, event)
XPanel_item item;
XEvent *event;
X{
X extern int atoi();
X void SelectEntry();
X int t1, t2;
X boolean error_flag = false;
X char *s, *ptr;
X
X if (event_id(event)=='\r' || event_id(event)=='\n') {
X if (ptr = rindex(s = panel_get_value(item), '.')) {
X if (*++ptr == '\0')
X t1 = cur_size-1;
X else
X t1 = atoi(ptr);
X if (t1 >= cur_size || (t2 = atoi(s)) > cur_size)
X error_flag = true;
X else
X SelectEntry(t2, t1);
X }
X else if ((t1 = atoi(panel_get_value(item))) < cur_size)
X SelectEntry(atoi(panel_get_value(item)), -1);
X else
X error_flag = true;
X
X if (error_flag)
X Message("<Valid colors for this cms are 0..%d>", cur_size-1);
X }
X else if (iscntrl(event_id(event)) || isdigit(event_id(event)) ||
X event_id(event) == '.')
X return(panel_text_notify(item, event));
X
X return(PANEL_NONE);
X}
X
X
X/*
X * NumericText - Notify procedure for a text item that only wants
X * digits in itself.
X */
X
Xstatic Panel_setting
XNumericText(item, event)
XPanel_item item;
XEvent *event;
X{
X return ((isdigit(event_id(event)) || iscntrl(event_id(event))) ?
X panel_text_notify(item, event) : PANEL_NONE);
X}
X
X
X
X
X/*
X * UpdateColorMaps - Sets the colormap of the four local windows
X * acccording to the value of use_colormap. The
X * amount of action required is determined by the
X * type parameter and the current state of the
X * use_colormap variable.
X *
X * U_NEW_COLOR - simply updates the window manager's record
X * of the current CMS to match Palette's.
X * U_NEW_CMS - tells the window manager to assign a new
X * colormap to Palette's canvas window, or to
X * all its windows if use_colormap is true.
X * U_NEW_STATE - Sets the colormaps of the other (non-canvas)
X * windows when the "Palette's Colormap" feature
X * gets toggled. Forces the wm to redraw the
X * windows too.
X */
X
Xstatic void UpdateColorMaps(type)
Xenum updatecolor_msg type;
X{
X int i, win_limit;
X char *name;
X
X name = cur_name;
X win_limit = ((type == U_NEW_STATE || use_colormap) ? NUM_MY_WINDOWS : 1);
X for (i = (type==U_NEW_STATE? 0 : -1); ++i < win_limit;) {
X if (i == 1 && !use_colormap)
X name = frame_cms_name;
X if (i == 2 && !use_colormap)
X name = subwins_cms_name;
X
X if (type != U_NEW_COLOR)
X pw_setcmsname(my_pixies[i], name);
X
X if (i==0 || use_colormap)
X pw_putcolormap(my_pixies[i], 0, cur_size,
X cur_map.cm_red, cur_map.cm_green, cur_map.cm_blue);
X }
X if (type == U_NEW_STATE || (type == U_NEW_CMS && use_colormap)) {
X wmgr_refreshwindow(my_frame_fd);
X if (cur_size > 4 && cur_size < MAX_COLORS && use_colormap)
X window_set(frame, FRAME_ICON, color_icon, 0);
X else
X window_set(frame, FRAME_ICON, &mono_icon, 0);
X }
X}
X
X
X/*
X * UseColorMap - Change state of the Palette's Colormap feature, and
X * update the windows as appropriate.
X *
X * See BorrowFramesCMS for explanation of the conditional
X * statments.
X */
X
Xstatic void UseColorMap(item, value, event)
XPanel_item item;
Xint value;
XEvent *event;
X{
X void UpdateColorMaps(), BorrowFramesCMS(), SelectCMS();
X char *glob_name = cur_name;
X
X if (value == false)
X BorrowFramesCMS();
X
X use_colormap = value;
X UpdateColorMaps(U_NEW_STATE);
X
X if (value == false)
X SelectCMS(glob_name);
X}
X
X
X
X/*
X * WalkDepth
X */
X
Xstatic void WalkDepth(item, value, event)
XPanel_item item;
Xint value;
XEvent *event;
X{
X shallow_walkP = (boolean) value;
X}
X
X
X
X/*
X * CreateNewMap - Enter a new map in the colormap table.
X */
X
Xstatic void CreateNewMap()
X{
X extern char *malloc();
X extern int getpid();
X boolean MakeCMS();
X static int gensym = 0;
X static struct colormapseg data; /* static so cur_name can point to it. */
X int i;
X
X (void) sprintf(data.cms_name, "Palette%d-%d", getpid(), ++gensym);
X data.cms_size = 1<<((int)panel_get_value(new_map_size)+1);
X
X cur_map.cm_red = (unsigned char *) malloc((unsigned) data.cms_size);
X cur_map.cm_green = (unsigned char *) malloc((unsigned) data.cms_size);
X cur_map.cm_blue = (unsigned char *) malloc((unsigned) data.cms_size);
X for (i = -1; ++i < data.cms_size;)
X cur_map.cm_red[i] = cur_map.cm_green[i] = cur_map.cm_blue[i] =
X i*(255/(data.cms_size-1.0));
X
X if (MakeCMS(&data, &cur_map)) {
X panel_paint(table_panel, PANEL_NO_CLEAR);
X SelectCMS(data.cms_name);
X }
X else
X Message("<Error: CMS table full. Try \"Reread Maps\".>", 0);
X}
X
X
X
X
X/*
X * Save - Save the current colormap in the specified file, in one of the
X * three specified formats.
X */
X
Xstatic void Save()
X{
X FILE *fp;
X int i;
X char *name;
X char buf[180];
X boolean error = false;
X /* RGB array */
X int c;
X unsigned char **ptr;
X
X /* Rasterfile */
X extern int SavePalette();
X colormap_t colormap;
X Pixrect *null_pr;
X
X if (fp = fopen(name = panel_get_value(file_name), "r")) {
X (void) fclose(fp);
X (void) sprintf(buf, "The file \"%s\" exists. Press the left mouse\
X button to overwrite. To cancel press the right mouse button.", name);
X if (wmgr_confirm(my_frame_fd, buf) == 0) {
X Message("Save operation cancelled.", 0);
X return;
X }
X }
X fp = fopen(panel_get_value(file_name), "w");
X if (fp==NULL) {
X error = true;
X Message("<Error: Couldn't open specified file.>", 0);
X }
X else {
X switch((int)panel_get_value(file_type)) {
X case 0: /* RGB arrays */
X for (i = -1; ++i<3;) {
X switch (i) {
X case 0:
X name = "red";
X ptr = &(cur_map.cm_red);
X break;
X case 1:
X name = "green";
X ptr = &(cur_map.cm_green);
X break;
X case 2:
X name = "blue";
X ptr = &(cur_map.cm_blue);
X break;
X }
X
X (void) fprintf(fp, "unsigned char %s[%d] = %*c", name, cur_size,
X (2*(i==0)+(i==2)+(cur_size>11)+(cur_size<100)), '{');
X for(c = -1; ++c < cur_size;) {
X if ((c%16) == 11)
X (void) fprintf(fp, "\n/*%3d*/ ", c );
X (void) fprintf(fp, "%3d%c", (*ptr)[c],
X (c==cur_size-1 ? '}' : ','));
X }
X (void) fprintf(fp, ";\n\n");
X }
X break;
X case 1: /* Number list */
X for (i = -1; ++i < cur_size; )
X (void) fprintf(fp, "%3d %3d %3d\n", *(cur_map.cm_red+i),
X *(cur_map.cm_green+i), *(cur_map.cm_blue+i));
X break;
X case 2: /* Null rasterfile w/ colormap */
X colormap.type = RMT_EQUAL_RGB;
X colormap.length = cur_size;
X colormap.map[0] = cur_map.cm_red;
X colormap.map[1] = cur_map.cm_green;
X colormap.map[2] = cur_map.cm_blue;
X
X null_pr = mem_create(0, 0, 8);
X
X if (pr_dump(null_pr, fp, &colormap, RT_STANDARD, 0))
X error = true;
X pr_destroy(null_pr);
X break;
X case 3: /* Picture of the palette */
X colormap.type = RMT_EQUAL_RGB;
X colormap.length = cur_size;
X colormap.map[0] = cur_map.cm_red;
X colormap.map[1] = cur_map.cm_green;
X colormap.map[2] = cur_map.cm_blue;
X
X DrawPalette(cur_size);
X
X if (SavePalette(fp, &colormap))
X error = true;
X
X HighlightSwatch(cur_entry, cur_size-1);
X break;
X }
X (void) fclose(fp);
X if (error)
X Message("<Error occured while writing to file.>", 0);
X else
X Message("File written.", 0);
X }
X}
X
X/*
X * Load
X */
X
X/*
X * Load calls three auxiliary routines. Each takes an open FILE *
X * and returns a count of how many colors it read in, or:
X * 0 to indicate that the file is not of the required type.
X * -1 to indicate that it's the right type but an error occurred
X * before any loading took place.
X * -2 the colormap was partially loaded when an error occurred
X * (this is bogus).
X * The subroutine displays an error message whenever -1 or -2 is returned.
X */
X
Xstatic void Load()
X{
X void UpdateColorMaps();
X int Load_NumList(), Load_Rasterfile(), Load_C_Array();
X
X FILE *fp;
X int ccount;
X
X if (cur_size == 2)
X Message("<Error: Can't load into a 2 color map.>", 0);
X if (fp = fopen(panel_get_value(file_name), "r")) {
X if ((ccount = Load_NumList(fp)) == 0) {
X rewind(fp);
X if ((ccount = Load_Rasterfile(fp)) == 0) {
X rewind(fp);
X if ((ccount = Load_C_Array(fp)) == 0)
X Message("<Error: Couldn't find any colors in file.>", 0);
X }
X }
X if (ccount > 0)
X Message("<Loaded %d color map from file.>", ccount);
X if (ccount > 0 || ccount == -2)
X UpdateColorMaps(U_NEW_COLOR);
X (void) fclose(fp);
X }
X else
X Message("<Error: Couldn't open specified file>", 0);
X}
X
X
Xstatic int Load_NumList(fp)
XFILE *fp;
X{
X int tem1, tem2, tem3;
X int i;
X
X for(i = -1;
X fscanf(fp, "%d %d %d", &tem1, &tem2, &tem3) == 3 &&
X ++i < cur_size; ) {
X *(cur_map.cm_red + i) = tem1;
X *(cur_map.cm_green + i) = tem2;
X *(cur_map.cm_blue + i) = tem3;
X }
X if (i == cur_size) {
X Message("<Error: Only the first %d colors fit.>", i);
X return(-2);
X }
X else
X return(i == -1 ? 0 : i+1);
X}
X
X
Xstatic int Load_Rasterfile(fp)
XFILE *fp;
X{
X struct rasterfile rh;
X colormap_t colormap;
X enum {NOT_A_RASTERFILE, DID_GOOD, ERROR} status = ERROR;
X boolean isa_rasterfile = true;
X
X if (pr_load_header(fp, &rh) == PIX_ERR)
X status = NOT_A_RASTERFILE;
X else if (rh.ras_maplength == 0 || rh.ras_maptype == RMT_NONE)
X Message("<Error: File's colormap is empty.>", 0);
X else if (rh.ras_maptype != RMT_EQUAL_RGB)
X Message("<Error: File's colormap not of type RMT_EQUAL_RGB", 0);
X else if ((colormap.length = rh.ras_maplength / 3) > cur_size)
X Message("<Error: Can't fit %d colors into current map>",
X colormap.length);
X else {
X colormap.type = RMT_EQUAL_RGB;
X colormap.map[0] = cur_map.cm_red;
X colormap.map[1] = cur_map.cm_green;
X colormap.map[2] = cur_map.cm_blue;
X /* Note colormap.length set above */
X if (pr_load_colormap(fp, &rh, &colormap) == PIX_ERR)
X Message("<Major bummer: Error while reading the colormap.>", 0);
X else
X status = DID_GOOD;
X }
X
X return((status==DID_GOOD ? colormap.length :
X (status==NOT_A_RASTERFILE ? 0 : -1)));
X}
X
Xstatic int Load_C_Array(fp)
XFILE *fp;
X{
X char buf[BUFSIZ];
X char *targ, *ptr;
X int rgb, ccolor = 0;
X boolean in_comment = false;
X unsigned char *cur_array;
X
X do {
X do {
X if (ptr = fgets(buf, BUFSIZ, fp))
X for (targ = "char red[", ptr = buf; *targ && *ptr; )
X if (*ptr++ == *targ)
X ++targ;
X } while (ptr && (*targ != '\0'));
X } while (ptr && !index(ptr, '='));
X
X if (ptr) { /* Hey, we found our target! */
X for (rgb = -1; ++rgb < 3; ) {
X ccolor = 0;
X cur_array = (rgb == 0 ? cur_map.cm_red :
X (rgb == 1 ? cur_map.cm_green :
X cur_map.cm_blue));
X while (*ptr != '{')
X if (*ptr == '\0') {
X ptr = fgets(buf, BUFSIZ, fp);
X if (ptr == NULL) {
X Message("<Error: EOF in color array.>", 0);
X return(rgb == 0 ? -1 : -2);
X }
X }
X else
X ++ptr;
X
X if (*ptr) { /* Found the open brace. */
X while (1) {
X /* Get a new line when you finish one */
X if (*ptr == '\0') {
X ptr = fgets(buf, BUFSIZ, fp);
X if (ptr == NULL) {
X Message("<Error: EOF in color array.>", 0);
X return(-2);
X }
X }
X if (*ptr == '}')
X break;
X
X /* Look for comments */
X if (*ptr == '/' && *(ptr+1) == '*')
X in_comment = true;
X if (*ptr == '*' && *(ptr+1) == '/')
X in_comment = false;
X
X /* This is a number, read it */
X if (!in_comment && isdigit(*ptr)) {
X *(cur_array + ccolor++) = atoi(ptr);
X while (isdigit(*++ptr))
X ;
X }
X else
X ++ptr;
X }
X }
X }
X }
X return(ccolor);
X}
X
X
X
X/*
X * Quit
X */
X
Xstatic void Quit()
X{
X exit(0);
X}
X
X
X/*
X * Reread_Maps - Do a brute force reread of the colormaps. Delete
X * everything in the hash table and the table_panel. Then
X * walk down the tree the same as at startup (except this
X * time, our windows are in the tree).
X */
X
Xstatic void Reread_Maps(item, event)
XPanel_item item;
XEvent *event;
X{
X int Get_Root();
X boolean WalkWinTree();
X void SelectCMS();
X char *item_name;
X int rootfd;
X
X if (panel_get_value(reset_on_reread)==0) {
X panel_each_item(table_panel, item)
X item_name = (char *) panel_get(item, PANEL_LABEL_STRING);
X *(rindex(item_name, '[')-1) = '\0';
X H_Delete(item_name);
X panel_destroy_item(item);
X panel_end_each
X }
X if ((rootfd=Get_Root(control_panel))==-1)
X Message("<Error: Couldn't open root window device.>", 0);
X else {
X if (!WalkWinTree(rootfd, shallow_walkP))
X Message("<Error: CMS table full. Not all windows processed.>", 0);
X (void) close(rootfd);
X if (H_Member(cur_name, NIL(struct cms_map), NIL(Panel_item *)))
X item_name = cur_name;
X else
X item_name = frame_cms_name;
X
X cur_name = NULL;
X SelectCMS(item_name);
X panel_paint(table_panel, PANEL_CLEAR);
X }
X}
X
X
X/*
X * MakeCMS - Create a new entry as specified by the two params and
X * return true if it doesn't already exist. Otherwise, do
X * nothing and return false.
X */
X
Xboolean MakeCMS(cmsdata, themap)
Xstruct colormapseg *cmsdata;
Xstruct cms_map *themap;
X{
X char buf[CMS_NAMESIZE+6];
X char *ptr;
X Panel_item item;
X
X (void) sprintf(buf, "%s [%d]", cmsdata->cms_name, cmsdata->cms_size);
X
X for (ptr=buf+strlen(buf); ptr < buf+CMS_NAMESIZE+6-5; ++ptr)
X *ptr = ' ';
X *ptr = '\0';
X
X item = panel_create_item(table_panel, PANEL_MESSAGE,
X PANEL_LABEL_STRING, buf,
X 0);
X if (H_Insert(cmsdata->cms_name, cmsdata->cms_size, item, themap)==false) {
X panel_destroy_item(item);
X return(false);
X }
X else
X return(true);
X}
X
X
X/*
X * ClickOnCMS - Find out which colormap name was clicked on and make it
X * the current color.
X * If it was shift-clicked, delete it from the table.
X */
X
Xstatic void ClickOnCMS(item, event)
XPanel_item item;
XEvent *event;
X{
X void SelectCMS();
X static char buf[CMS_NAMESIZE+6]; /* static so cur_name can point to it. */
X
X if (event_id(event) == MS_LEFT && event_is_down(event)) {
X (void) strcpy(buf, panel_get(item, PANEL_LABEL_STRING));
X *(rindex(buf, '[')-1) = '\0';
X if (event_shift_is_down(event)) {
X if (!strcmp(buf, frame_cms_name))
X Message("<Error: Can't delete Palette's colormap>", 0);
X else {
X Message("", 0);
X if (item == cur_cms_item)
X SelectCMS(frame_cms_name);
X H_Delete(buf);
X panel_destroy_item(item);
X panel_paint(table_panel, PANEL_CLEAR);
X }
X }
X else
X SelectCMS(buf);
X }
X}
X
X
X/*
X * ResizeCanvas - Call the canvas.c package routine when the canvas size
X * changes. Then redraw the palette. Also if necessary,
X * call the routine which defends against a window system
X * bug. See BorrowFramesCMS() for details.
X */
X
Xstatic void ResizeCanvas()
X{
X extern void SetPaletteSize();
X void BorrowFramesCMS();
X boolean glob_use = use_colormap;
X char *glob_name = cur_name;
X
X SetPaletteSize();
X use_colormap = false; /* So Palette's other win's don't redraw, too */
X if (cur_size > 2)
X BorrowFramesCMS();
X SelectCMS(glob_name);
X use_colormap = glob_use;
X}
X
X
X
X/*
X * CanvasEvent - Do the right thing with the variety of left- and
X * right-clicks, and drags.
X */
X
Xstatic void CanvasEvent(win, event, arg)
XWindow win;
XEvent *event;
Xcaddr_t arg;
X{
X extern void DrawPalette(), BoxSwatches();
X extern int WhichSwatch();
X void SelectEntry();
X int selection;
X
X if (event_id(event) == LOC_DRAG || event_is_button(event)) {
X selection = WhichSwatch(event_x(event), event_y(event));
X if (selection < 0) /* Clicking outside the rect erases the selection */
X DrawPalette(cur_size);
X else if (selection != cur_range_end && selection != cur_entry &&
X ((event_id(event) == MS_MIDDLE && event_is_down(event)) ||
X (event_id(event) == MS_LEFT && event_is_up(event)) ||
X event_id(event) == LOC_DRAG))
X SelectEntry(cur_entry, selection);
X else if (event_id(event) == MS_LEFT && event_is_down(event)) {
X SelectEntry(selection, -1);
X }
X }
X}
X
X
X/*
X * SelectCMS - Get the specs for a colormap, and make it the current one.
X * Note, that there should never be an error, since if a map
X * isn't in the table, the user should have no way to get it
X * to here.
X */
X
Xstatic void SelectCMS(name)
Xchar *name;
X{
X extern void DrawPalette();
X void UpdateColorMaps();
X
X int size;
X
X if (cur_name)
X panel_set(cur_cms_item, PANEL_LABEL_BOLD, FALSE, 0);
X if (size = H_Member(name, &cur_map, &cur_cms_item)) {
X cur_size = size;
X cur_name = name;
X panel_set(cur_cms_item, PANEL_LABEL_BOLD, TRUE, 0);
X UpdateColorMaps(U_NEW_CMS);
X SelectEntry(cur_entry >= cur_size ? 0 : cur_entry,
X cur_range_end >= cur_size ? -1 : cur_range_end);
X }
X else
X Message("<Weird error: Colormap not in hash table.>", 0);
X}
X
X
X
X
X/*
X * BorrowFramesCMS - SunOS 3.4 apparently gets troubled by deep
X * pixrects and by changes made to a retained pixwin
X * behind its back. Specifically, when a canvas gets
X * resized, the backing pixrect (pw_prretained) gets
X * set to a depth of 1 even for 8 bit deep pixwins.
X * If a color window gets set back to its original
X * color, the scrollbar color gets messed up. Also,
X * when changing a window's icon from an 8-bit to a
X * one bit, two WINGETCMS ioctl errors are generated.
X *
X * This routine protects against that by allowing
X * callers to borrow the frame's original colormap
X * before doing any the above operations. It's a
X * nasty kludge, and a lousy description of the
X * problem. But, hey, get outta my face.
X */
X
Xstatic void BorrowFramesCMS()
X{
X void SelectCMS();
X
X int glob_entry = cur_entry;
X int glob_range_end = cur_range_end;
X
X SelectCMS(frame_cms_name);
X cur_entry = glob_entry; /* In case it was reset to 0 in SelectCMS() */
X cur_range_end = glob_range_end;
X}
X
SHAR_EOF
if test 38447 -ne "`wc -c < 'palette.c'`"
then
echo shar: error transmitting "'palette.c'" '(should have been 38447 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'palette.l'" '(8048 characters)'
if test -f 'palette.l'
then
echo shar: will not over-write existing file "'palette.l'"
else
sed 's/^ X//' << \SHAR_EOF > 'palette.l'
X.TH palette 1L "8 April 1989" " " " "
X
X.SH NAME
Xpalette \- edit colormaps
X.\"
X.SH SYNOPSIS
X.B palette
X[
X.B \-f
X]
X[
X.B \-s
X]
X[
X.I <SunView window options>
X]
X.\"
X.SH DESCRIPTION
X.\" .I name
X.\" ...
X.\" .IR reference (1)
X.\"
X.I Palette
Xis a colormap editing tool. It can modify the colormaps being used by
Xother Suntools windows, or create new colormaps. Colormaps may be saved
Xto or loaded from C source files, a numeric list or raster files.
X
XAs a development tool,
X.I palette
Xcan be used to modify a running application's colormap arrays, thus
Xeliminating the need to make incremental changes to the code, with
Xtime-consuming recompilations between each modification. As a graphics
Xtool,
X.I palette
Xcan be used in conjunction with commercial applications or bitmap
Xeditors such as
X.IR touchup (l)
Xwhich have little or no colormap modification abilities.
X
XThe tool consists of three windows: a color palette, a colormap table,
Xand a control panel.
X
XThe palette contains a color swatch for each entry in the current
Xcolormap. Left-clicking on a swatch makes it the current color.
XSimilarly, a series of entries may be selected by left-dragging through
Xthem, or by left- and middle-clicking to specify the bounds of the
Xregion.
X
XThe colormap table lists all the colormaps that
X.I palette
Xcurrently knows about. The current colormap is displayed in bold.
XLeft-clicking on one makes it the current colormap. Shift-left-clicking
Xdeletes the map from the table.
X
XThe control panel contains the instruments for manipulating the current
Xcolormap. The panel breaks down into roughly four areas of
Xfunctionality, as described below.
X
X.B "Modifying The Current Color(s)"
X.RS
XAt the top are three slider controls for specifying the red, green and
Xblue components of the current color(s). If more than one color entry
Xis selected\(emand the values of a component differ across the
Xentries\(emthen the slider will indicate the average value for the
Xcomponent.
X
XTo the right of each slider are two arrow buttons. These allow the user
Xto step the corresponding red, green or blue component up or down. The
Xsize of the step is indicated by the user-modifiable
X.B Step Size
Xitem. When a range of colors is selected, setting the
X.B Uniform Steps
Xitem to
X.I No
Xwill cause the arrow buttons to have a linearly increasing effect on
Xeach entry. For example, if entries 3 through 5 are selected and the
Xstep size is 10, then clicking the right arrow would increase entry
Xthree by 10, entry four by 20 and entry five by 30. This feature allows
Xthe user to quickly and easily create complex color schemes.
X
XBelow the slider controls, a
X.B Current Color
Xdisplay indicates the positional number of the current color. As
Xdescribed above, the current color may be selected by clicking on its
Xswatch in the palette window. Alternatively, a number may be typed into
Xthe
X.B Current Color
Xdisplay followed by a Return. A range may be specified by entering two
Xnumbers separated by periods.
X
XThe
X.B Copy
Xbutton copies the selected color(s) onto the "clipboard."
X.B Paste
Xplaces the contents of the clipboard onto the palette starting at the
Xcurrent entry.
X.RE
X
X.B Creating and Reading Colormaps
X.RS
XThe
X.B New Map
Xbutton creates a new colormap for editing. The size of the new map is
Xspecified by the value of the
X.B New Map Size
Xcontrol.
X
XWhen
X.I palette
Xstarts up, it checks the windows on the screen and enters their
Xcolormaps into the colormap table. If new windows are created, or
Xexisting ones go away,
X.IR palette 's
Xstate can be updated by pressing the
X.B Reread Maps
Xbutton. If the
X.B Read From
Xitem is set to
X.IR "All windows" ,
Xthen every window on the screen will be examined for colormaps. If it's
Xset to
X.IR "Top level frames" ,
Xthen only the main frames will be examined. The
X.B On Reread
Xoption specifies whether the colormap table should be reset before
Xrereading the colormaps. Note that colormaps created by the
X.B New Map
Xbutton are not associated with any window (unless it is the current
Xcolormap, in which case it is being used by the palette window). This
Xmeans that if the table is reset when
X.B On Reread
Xis set to
X.IR "Reset table first" ,
Xthese new maps will be lost.
X.RE
X
X.B Saving Colormaps
X.RS
XThe current colormap may be written to disk in four different formats,
Xas specified by the
X.B Save Type
Xcontrol. The
X.I RGB arrays
Xformat creates C code specifying the numeric values for red, green and
Xblue arrays. This output can be incorporated into a C program which can
Xthen use the SunView procedures for specifying colormaps. The
X.I RGB list
Xformat creates a text file with the three component values of each color
Xon a separate line. (This allows
X.I palette
Xto exchange files with a certain inferior colormap program bearing a
Xsimilar name.) The
X.I Clear raster file
Xformat creates a raster file containing the current colormap and a blank
Ximage. The
X.I Raster File with palette
Xformat does the same thing, except the image is a picture of the palette
Xwindow. In all four cases, the file name is specified by the
X.B File Name
Xitem.
X.RE
X
X.B Loading Colormaps
X.RS
XThe
X.B Load
Xbutton reads colormap information into the current colormap from the
Xfile specified by the
X.B File Name
Xitem. All four file formats are supported. The type of the file will
Xbe determined from its contents.
X.I Palette
Xonly promises to read RGB array files which it created. But, in fact,
Xit does quite well at reading array information which is deeply buried
Xin a C source file regardless of how bizarre the formatting is. (It
Xscans through the file looking for the string "char red[". If it can
Xfind this in your source file, then it will most likely be able to read
Xthe data.)
X.RE
X
X.B Program Control
X.RS
XIf
X.B Palette's Colormap
Xis set to
X.I Its own
Xthe control panel and the colormap table will use their own default
Xcolors (usually, the monochrome colormap). If this control is set to
X.IR Selected ,
Xthen it will use the current colormap. This is convenient when editing
Xlarge colormaps which would otherwise be swapped out by the window
Xsystem when the cursor is outside of the palette window. On the other
Xhand, if the foreground and background colors of the current map are
Xvery similar, it will make it difficult to see the controls.
X
XThe
X.B Quit
Xbutton exits
X.I palette.
X.RE
X.\"
X.SH OPTIONS
X.TP
X.B \-f
XOn startup,
X.I palette
Xnormally looks for colormaps in all windows. This options says to look
Xat top level frames only. (See
X.B Read From
Xcontrol, above.)
X.TP
X.B \-s
XNormally, the windows of the
X.I palette
Xtool use their default colormap on startup. This option causes them to
Xuse the currently selected colormap. (See
X.B Palette's Colormap
Xcontrol, above.)
X.\"
X.SH USAGE NOTES
XThe left and right arrow keys (as well as the greater-than and less-than
Xkeys) select the successive or previous color entry, respectively.
XControl-C will exit
X.IR palette .
X
XGreat pains were taken to ensure that the windows could be resized
Xwithout confusing the program. So if you want smaller or larger
Xwindows, simply resize it in the standard SunView way.
X
XUsers should remember that the background and foreground colors are
Xdefined as the first and last entries in a colormap, respectively. The
XSunView window system prevents the user from setting these to exactly
Xthe same color. If this is attempted they will appear as black and
Xwhite.
X
XWhen the current colormap contains between eight and 128 colors, and
X.B Palette's Colormap
Xis set to
X.IR Selected ,
X.IR palette 's
Xicon will appear in color.
X
XTwo popular graphics display programs,
X.IR screenload (1)
Xand
X.IR touchup (l)
Xdo their own evil deeds to colormaps. This is of interest to those
Xusing
X.I palette
Xin conjunction with either of these.
X.IR screenload (1)
Xdoesn't load the map if it only has two colors in it.
X.IR touchup (l)
Xmakes sure that
Xthe zeroth and 254th entries in its colormap stay white, and the first
Xand 255th stay black.
X.SH AUTHOR
XWayne Mesard, mesard at BBN.COM
X.SH "SEE ALSO"
Xscreenload(1), touchup(l),
X.I SunView Programmer's Guide
X
SHAR_EOF
if test 8048 -ne "`wc -c < 'palette.l'`"
then
echo shar: error transmitting "'palette.l'" '(should have been 8048 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'patchlevel.h'" '(67 characters)'
if test -f 'patchlevel.h'
then
echo shar: will not over-write existing file "'patchlevel.h'"
else
sed 's/^ X//' << \SHAR_EOF > 'patchlevel.h'
X#define VERSION_STRING "Palette Version 1.1"
X#define PATCHLEVEL 0
X
SHAR_EOF
if test 67 -ne "`wc -c < 'patchlevel.h'`"
then
echo shar: error transmitting "'patchlevel.h'" '(should have been 67 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'wsm_types.h'" '(632 characters)'
if test -f 'wsm_types.h'
then
echo shar: will not over-write existing file "'wsm_types.h'"
else
sed 's/^ X//' << \SHAR_EOF > 'wsm_types.h'
X#ifndef wsm_types_DEFINED
X#define wsm_types_DEFINED
X/**
X ** ADT: LIFO queue of int's
X **/
X
X#ifndef LIFO_Q_SIZE
X#define LIFO_Q_SIZE 20
X#endif
X
Xtypedef struct {
X int q[LIFO_Q_SIZE];
X int ptr;
X} lifo;
X
X#define Q_init(QQ) QQ.ptr = 0
X#define Q_pop(QQ) QQ.q[(--QQ.ptr)]
X#define Q_peek(QQ) QQ.q[(QQ.ptr-1)]
X#define Q_push(QQ, DATA) QQ.q[QQ.ptr]=DATA, QQ.ptr=((QQ.ptr+1)%LIFO_Q_SIZE)
X#define Q_size(QQ) QQ.ptr
X
X
X
X/**
X ** ADT: boolean
X **/
X
X#define boolean short
X#define false (short) 0
X#define true (short) !false
X
X
X/**
X ** Typed NULL constant. To avoid abuse of 0 and NULL.
X **/
X
X#define NIL(type) (type *) 0
X
X#endif wsm_types_DEFINED
X
SHAR_EOF
if test 632 -ne "`wc -c < 'wsm_types.h'`"
then
echo shar: error transmitting "'wsm_types.h'" '(should have been 632 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
More information about the Comp.sources.sun
mailing list