From decwrl!ucbvax!tut.cis.ohio-state.edu!husc6!rutgers!aramis.rutgers.edu!dartagnan.rutgers.edu!mcgrew Sat May 20 21:42:22 PDT 1989 Article 9 of comp.sources.sun: Path: decwrl!ucbvax!tut.cis.ohio-state.edu!husc6!rutgers!aramis.rutgers.edu!dartagnan.rutgers.edu!mcgrew From: mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) Newsgroups: comp.sources.sun Subject: v01i008: palette, a colormix tool, Part 01/02 Message-ID: Date: 18 May 89 20:59:18 GMT Organization: Rutgers Univ., New Brunswick, N.J. Lines: 1915 Approved: mcgrew@aramis.rutgers.edu Submitted-by: Wayne Mesard 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@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@BBN.COM. * X * * X **************************************************************************/ X X#include X#include X#include X#include X#include X#include 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("", 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("", 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 [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("", 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("", 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("", 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("", 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("", 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("", 0); X } X } X if (ccount > 0) X Message("", ccount); X if (ccount > 0 || ccount == -2) X UpdateColorMaps(U_NEW_COLOR); X (void) fclose(fp); X } X else X Message("", 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("", 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("", 0); X else if (rh.ras_maptype != RMT_EQUAL_RGB) X Message(" cur_size) X Message("", 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("", 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("", 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("", 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("", 0); X else { X if (!WalkWinTree(rootfd, shallow_walkP)) X Message("", 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("", 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("", 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 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@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