home *** CD-ROM | disk | FTP | other *** search
- /*
- * palette.c - This file contains the program's main processing routines
- * including all window creation, event handlers and
- * the routines for manipulating colors and color maps.
- *
- * Exported routines:
- * main (duh)
- * MakeCMS
- */
-
- /**************************************************************************
- * palette - a colormap editor
- * Copyright (c) 1988 Wayne Mesard *
- * *
- * This is free software. It may be reproduced, retransmitted, *
- * redistributed and otherwise propogated at will, provided that *
- * no monetary profit is realized and that this notice remains *
- * intact and in place. *
- * *
- * Please direct bug reports, code enhancements and comments *
- * to mesard@BBN.COM. *
- * *
- **************************************************************************/
-
- #include <suntool/sunview.h>
- #include <suntool/panel.h>
- #include <suntool/canvas.h>
- #include <strings.h>
- #include <ctype.h>
- #include <stdio.h>
-
- #include "patchlevel.h"
- #include "wsm_types.h"
- #include "hash.h"
-
- #define MAX_COLORS 256
- #define MAX_BRIGHTNESS 255
-
- #define MAX_COLORS_STR_LEN 9
-
- #define PALETTE_H 160
- #define BUTT_SIZE 11
- #define NUM_MY_WINDOWS 4
-
- enum updatecolor_msg {U_NEW_STATE, U_NEW_COLOR, U_NEW_CMS};
-
-
- static short mono_image[] = {
- # include "mono.icon"
- };
- mpr_static(mono_pr, 64, 64, 1, mono_image);
- DEFINE_ICON_FROM_IMAGE(mono_icon, mono_image);
-
- static short color_image[] = {
- # include "color.icon"
- };
- mpr_static(color_pr, 64, 64, 8, color_image);
- static Icon color_icon;
-
-
- static short left_arrow_array[] = {
- # include "left_arrow.pr"
- };
- mpr_static(left_arrow, 16, 16, 1, left_arrow_array);
-
- static short right_arrow_array[] = {
- # include "right_arrow.pr"
- };
- mpr_static(right_arrow, 16, 16, 1, right_arrow_array);
-
-
- static use_colormap = false;
- static boolean shallow_walkP = false;
- static Pixwin *my_pixies[NUM_MY_WINDOWS];
-
- static Panel_item sliders[3];
- static Panel_item avg_markers[3];
- static Panel_item new_map_size;
- static Panel_item step_size_item;
- static Panel_item proportional_item;
- static Panel_item reset_on_reread;
- static Panel_item file_type;
- static Panel_item file_name;
-
- static int cur_entry = 0;
- static int cur_range_end = 0;
- static int cur_size;
- static char *cur_name;
- static Panel_item cur_cms_item;
- static struct cms_map cur_map;
-
- static unsigned char clipboard_red[MAX_COLORS];
- static unsigned char clipboard_green[MAX_COLORS];
- static unsigned char clipboard_blue[MAX_COLORS];
- static struct cms_map clipboard =
- {clipboard_red, clipboard_green, clipboard_blue};
- static short clipboard_entries = 0;
-
- static Frame frame;
- static int my_frame_fd;
- static Panel control_panel, table_panel;
- static Panel_item cur_color_item;
- static Panel_item msg_item;
- static char frame_cms_name[CMS_NAMESIZE];
- static char subwins_cms_name[CMS_NAMESIZE];
-
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- extern int Get_Root();
- void InitWindow(), Message();
- void SelectCMS();
- boolean WalkWinTree();
- int rootfd, i;
-
- for (i = argc; i>1;)
- if (argv[--i][0] == '-')
- if (argv[i][1] == 'f')
- shallow_walkP = true;
- else if (argv[i][1] == 's')
- use_colormap = true;
- /* else This must be an arg for the frame. */
-
- H_MakeNull();
- InitWindow(argc, argv);
-
- if ((rootfd=Get_Root(frame))==-1) {
- fprintf(stderr, "%s: Error opening screen's root window\n", argv[0]);
- exit(1);
- /*NOTREACHED*/
- }
-
- if (!WalkWinTree(rootfd, shallow_walkP))
- Message("<Error: CMS table full. Not all windows processed.>", 0);
- (void) close(rootfd);
- (void) WalkWinTree(my_frame_fd, true); /* Since it's not in the tree yet. */
- cur_name = NULL;
- SelectCMS(frame_cms_name);
- window_main_loop(frame);
- }
-
-
-
- /*
- * InitWindow - Set up all the windows and panel items.
- */
-
- static void InitWindow(argc, argv)
- int argc;
- char **argv;
- {
- extern Pixwin *MakePalette();
- void slider_notify();
- void ArrowEvent();
- void Copy(), Paste();
- Panel_setting KeyedEntry(), NumericText();
- void ClickOnCMS();
- void KeyEvent();
- void UseColorMap(), WalkDepth();
- void ResizeCanvas(), CanvasEvent();
- void CreateNewMap(), Reread_Maps(), Save(), Load(), Quit();
-
- static char RGBName[][6] = {"Red ", "Green", "Blue "};
- Canvas canvas;
- char buf[16];
- int i, row = -1;
- unsigned char **ptr;
-
-
- color_icon = icon_create(ICON_IMAGE, &color_pr, 0);
-
- frame = window_create(NULL, FRAME,
- FRAME_NO_CONFIRM, TRUE,
- FRAME_ICON, &mono_icon,
- FRAME_LABEL, "Palette",
- FRAME_ARGS, argc, argv,
- WIN_CONSUME_KBD_EVENT, WIN_NO_EVENTS,
- 0);
-
- control_panel = window_create(frame, PANEL,
- PANEL_ITEM_X_GAP, 5,
- WIN_EVENT_PROC, KeyEvent,
- 0);
-
- for (i= -1; ++i<3;) {
- (void) sprintf(buf, "%s:", RGBName[i]);
- switch (i) {
- case 0:
- ptr = &(cur_map.cm_red);
- break;
- case 1:
- ptr = &(cur_map.cm_green);
- break;
- case 2:
- ptr = &(cur_map.cm_blue);
- break;
- }
-
- sliders[i] = panel_create_item(control_panel, PANEL_SLIDER,
- PANEL_ITEM_X, ATTR_COL(0),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_LABEL_STRING, buf,
- PANEL_CLIENT_DATA, ptr,
- PANEL_MIN_VALUE, 0,
- PANEL_MAX_VALUE, MAX_COLORS-1,
- PANEL_SHOW_RANGE, FALSE,
- PANEL_SLIDER_WIDTH, MAX_COLORS,
- PANEL_NOTIFY_PROC, slider_notify,
- PANEL_NOTIFY_LEVEL, PANEL_ALL,
- 0);
-
- avg_markers[i] = panel_create_item(control_panel, PANEL_MESSAGE,
- PANEL_LABEL_STRING, "*",
- PANEL_LABEL_BOLD, TRUE,
- 0);
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_LABEL_IMAGE, &left_arrow,
- PANEL_NOTIFY_PROC, ArrowEvent,
- PANEL_CLIENT_DATA, sliders[i],
- 0);
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_LABEL_IMAGE, &right_arrow,
- PANEL_NOTIFY_PROC, ArrowEvent,
- PANEL_CLIENT_DATA, sliders[i],
- 0);
-
-
- }
- panel_set(control_panel, PANEL_ITEM_X_GAP, 15, 0);
-
- cur_color_item = panel_create_item(control_panel, PANEL_TEXT,
- PANEL_ITEM_X, ATTR_COL(0),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_LABEL_BOLD, TRUE,
- PANEL_LABEL_STRING, "Current Color:",
- PANEL_VALUE_STORED_LENGTH, MAX_COLORS_STR_LEN,
- PANEL_VALUE_DISPLAY_LENGTH, MAX_COLORS_STR_LEN,
- PANEL_NOTIFY_LEVEL, PANEL_ALL,
- PANEL_NOTIFY_PROC, KeyedEntry,
- 0);
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_NOTIFY_PROC, Copy,
- PANEL_LABEL_IMAGE,
- panel_button_image(control_panel,
- "Copy", BUTT_SIZE, 0),
- 0);
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_NOTIFY_PROC, Paste,
- PANEL_LABEL_IMAGE,
- panel_button_image(control_panel,
- "Paste", BUTT_SIZE, 0),
- 0);
-
- msg_item = panel_create_item(control_panel, PANEL_MESSAGE,
- PANEL_ITEM_X, ATTR_COL(0),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_LABEL_STRING, " ",
- 0);
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_ITEM_X, ATTR_COL(0),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_NOTIFY_PROC, CreateNewMap,
- PANEL_LABEL_IMAGE,
- panel_button_image(control_panel,
- "New Map", BUTT_SIZE, 0),
- 0);
-
- new_map_size = panel_create_item(control_panel, PANEL_CYCLE,
- PANEL_ITEM_X, ATTR_COL(15),
- PANEL_ITEM_Y, ATTR_ROW(row),
- PANEL_LABEL_BOLD, TRUE,
- PANEL_LABEL_STRING, "New Map Size:",
- PANEL_CHOICE_STRINGS,
- " 2"," 4"," 8"," 16"," 32",
- " 64","128","256", 0,
- PANEL_VALUE, 7,
- 0);
-
- proportional_item = panel_create_item(control_panel, PANEL_CYCLE,
- PANEL_ITEM_X, ATTR_COL(15),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_LABEL_STRING, "Uniform Steps:",
- PANEL_LABEL_BOLD, TRUE,
- PANEL_CHOICE_STRINGS, "Yes", "No", 0,
- PANEL_VALUE, 0,
- 0);
-
- /* A bug in SunOS 3.4 causes the following item to be 2 pixels above
- * the row using screen.r.14. I have no idea why. Other fonts don't
- * seem to be effected, and other sizes of screen are shifted by
- * different distances. Anyway, the "+2" below should be adjusted or
- * removed as your system configuration dictates.
- */
- step_size_item = panel_create_item(control_panel, PANEL_TEXT,
- PANEL_LABEL_BOLD, TRUE,
- PANEL_LABEL_STRING, "Step Size:",
- PANEL_ITEM_Y, ATTR_ROW(row)+2,
- PANEL_VALUE_STORED_LENGTH, 3,
- PANEL_VALUE_DISPLAY_LENGTH, 3,
- PANEL_VALUE, "10",
- PANEL_NOTIFY_LEVEL, PANEL_ALL,
- PANEL_NOTIFY_PROC, NumericText,
- 0);
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_ITEM_X, ATTR_COL(0),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_NOTIFY_PROC, Reread_Maps,
- PANEL_LABEL_IMAGE,
- panel_button_image(control_panel,
- "Reread Maps", BUTT_SIZE, 0),
- 0);
-
- (void) panel_create_item(control_panel, PANEL_CYCLE,
- PANEL_ITEM_X, ATTR_COL(15),
- PANEL_ITEM_Y, ATTR_ROW(row),
- PANEL_NOTIFY_PROC, WalkDepth,
- PANEL_LABEL_BOLD, TRUE,
- PANEL_LABEL_STRING, "Read From:",
- PANEL_CHOICE_STRINGS,
- "All windows", "Top level frames", 0,
- PANEL_VALUE, shallow_walkP,
- 0);
-
- reset_on_reread = panel_create_item(control_panel, PANEL_CYCLE,
- PANEL_ITEM_X, ATTR_COL(15),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_LABEL_BOLD, TRUE,
- PANEL_LABEL_STRING, "On Reread:",
- PANEL_CHOICE_STRINGS,
- "Reset table first", "Don't reset table", 0,
- 0);
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_ITEM_X, ATTR_COL(0),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_NOTIFY_PROC, Save,
- PANEL_LABEL_IMAGE,
- panel_button_image(control_panel,
- "Save", BUTT_SIZE, 0),
- 0);
-
- file_type = panel_create_item(control_panel, PANEL_CYCLE,
- PANEL_ITEM_X, ATTR_COL(15),
- PANEL_LABEL_BOLD, TRUE,
- PANEL_LABEL_STRING, "Save Type:",
- PANEL_CHOICE_STRINGS,
- "RGB arrays", "RGB list", "Clear raster file",
- "Palette raster file", 0,
- 0);
-
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_ITEM_X, ATTR_COL(0),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_NOTIFY_PROC, Load,
- PANEL_LABEL_IMAGE,
- panel_button_image(control_panel,
- "Load", BUTT_SIZE, 0),
- 0);
-
-
- file_name = panel_create_item(control_panel, PANEL_TEXT,
- PANEL_ITEM_X, ATTR_COL(15),
- PANEL_ITEM_Y, ATTR_ROW(row),
- PANEL_LABEL_BOLD, TRUE,
- PANEL_LABEL_STRING, "File Name:",
- PANEL_VALUE_STORED_LENGTH, 128,
- PANEL_VALUE_DISPLAY_LENGTH, 24,
- PANEL_VALUE, "palette.rgb",
- 0);
-
- (void) panel_create_item(control_panel, PANEL_BUTTON,
- PANEL_ITEM_X, ATTR_COL(0),
- PANEL_ITEM_Y, ATTR_ROW(++row),
- PANEL_NOTIFY_PROC, Quit,
- PANEL_LABEL_IMAGE,
- panel_button_image(control_panel,
- "Quit", BUTT_SIZE, 0),
- 0);
-
- (void) panel_create_item(control_panel, PANEL_CYCLE,
- PANEL_ITEM_X, ATTR_COL(15),
- PANEL_NOTIFY_PROC, UseColorMap,
- PANEL_LABEL_BOLD, TRUE,
- PANEL_LABEL_STRING, "Palette's Colormap:",
- PANEL_CHOICE_STRINGS, "Its own", "Selected", 0,
- PANEL_VALUE, use_colormap,
- 0);
-
- window_fit(control_panel);
- window_fit_width(frame);
- table_panel = window_create(frame, PANEL,
- PANEL_ITEM_X_GAP, 60,
- PANEL_EVENT_PROC, ClickOnCMS,
- WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
- WIN_ROWS, 3,
- WIN_IGNORE_KBD_EVENT, WIN_ASCII_EVENTS,
- WIN_CONSUME_PICK_EVENT, MS_LEFT,
- WIN_INPUT_DESIGNEE,
- i = (int) window_get(control_panel,
- WIN_DEVICE_NUMBER),
- 0);
-
- canvas = window_create(frame, CANVAS,
- CANVAS_RESIZE_PROC, ResizeCanvas,
- CANVAS_FIXED_IMAGE, FALSE,
- CANVAS_AUTO_CLEAR, FALSE,
- WIN_CONSUME_PICK_EVENTS,
- WIN_UP_EVENTS, LOC_DRAG,
- MS_LEFT, MS_MIDDLE, 0,
- WIN_INPUT_DESIGNEE, i,
- WIN_EVENT_PROC, CanvasEvent,
- WIN_BELOW, table_panel,
- WIN_HEIGHT, PALETTE_H,
- 0);
-
- my_pixies[0] = MakePalette(canvas);
- my_pixies[1] = (Pixwin *) window_get(frame, WIN_PIXWIN);
- my_pixies[2] = (Pixwin *) window_get(control_panel, WIN_PIXWIN);
- my_pixies[3] = (Pixwin *) window_get(table_panel, WIN_PIXWIN);
-
- pw_getcmsname(my_pixies[1], frame_cms_name);
- pw_getcmsname(my_pixies[2], subwins_cms_name);
-
- my_frame_fd = (int) window_get(frame, WIN_FD);
- window_fit_height(frame);
- }
-
-
-
- /*
- * Message - Put a string in the message line (with an optional numeric
- * argument.
- */
-
- static void Message(s, i)
- char *s;
- int i;
- {
- char buf[80];
-
- (void) sprintf(buf, s, i);
- panel_set(msg_item, PANEL_LABEL_STRING, buf, 0);
- }
-
-
-
- /*
- * SelectEntry - Do the work when the user selects a new color or range
- * of colors. index need not be less than range_end. The
- * sliders and the Current Color indicator are updated.
- * And the current color(s) are highlighted in the palette.
- * (Single colors are not highlighted if the colormap is of
- * size 2.)
- *
- * If index or range_end are illegal values, the routine
- * silently exits.
- */
-
- static void SelectEntry(index, range_end)
- int index, range_end;
- {
- extern void HighlightSwatch(), BoxSwatches(), DrawPalette();
- unsigned char **ptr;
- char buf[MAX_COLORS_STR_LEN+1];
- int i, j, val, prev;
- boolean avgP, avg_existsP = false;
-
- if (index > range_end) {
- if (range_end == -1)
- range_end = index;
- else {
- i = index;
- index = range_end;
- range_end = i;
- }
- }
- if (index < 0 || range_end >= cur_size)
- return;
- cur_entry = index;
- cur_range_end = range_end;
-
- DrawPalette(cur_size);
-
- if (cur_entry == cur_range_end) {
- (void) sprintf(buf, "%d", cur_entry);
- if (cur_size > 2)
- HighlightSwatch(cur_entry, cur_size-1);
- }
- else {
- BoxSwatches(cur_entry, cur_range_end);
- (void) sprintf(buf, "%d..%d", cur_entry, cur_range_end);
- }
- panel_set_value(cur_color_item, buf);
-
- for (i= -1; ++i<3;) {
- avgP = FALSE;
- ptr = (unsigned char **) panel_get(sliders[i], PANEL_CLIENT_DATA);
- for (val = 0, j = cur_entry, prev = ((*ptr)[cur_entry]);
- j <= cur_range_end; j++) {
- avgP = (avgP | (prev != ((*ptr)[j])));
- val += (prev = (*ptr)[j]);
- }
- panel_set(sliders[i], PANEL_VALUE, val/(cur_range_end-cur_entry+1), 0);
- panel_set(avg_markers[i], PANEL_SHOW_ITEM, avgP, 0);
- avg_existsP = (avg_existsP | avgP);
- }
- Message((avg_existsP ? "* Starred items represent averages." : ""), 0);
- }
-
-
-
- /*
- * slider_notify - When the user clicks on a slider, update the colormap,
- * the colormap array, and hide the slider's asterisk
- * item (in case it's on).
- */
-
- static void slider_notify(slider, value, event)
- Panel_item slider;
- int value;
- Event *event;
- {
- void UpdateColorMaps();
- unsigned char **ptr;
- int i;
-
- ptr = (unsigned char **) panel_get(slider, PANEL_CLIENT_DATA);
- for (i=cur_entry; i <= cur_range_end; ++i)
- (*ptr)[i] = (unsigned char) value;
-
- UpdateColorMaps(U_NEW_COLOR);
- panel_set((Panel_item)panel_get(slider, PANEL_NEXT_ITEM),
- PANEL_SHOW_ITEM, FALSE, 0);
- }
-
-
- /*
- * ArrowEvent - When the user clicks on an arrow, update its slider,
- * increment the current color(s) (possibly by a linearly
- * increasing amount), update the array and the colormap,
- * and possibly turn off the color's asterisk (if all the
- * colors in the range have become equal).
- */
-
- static void ArrowEvent(button, event)
- Panel_item button;
- Event *event;
- {
- extern int atoi();
- int i, prev, new_val, total = 0;
- boolean avgP = FALSE;
- boolean proportional = (boolean) panel_get_value(proportional_item);
- int step_size = atoi(panel_get_value(step_size_item));
- Panel_item my_slider = panel_get(button, PANEL_CLIENT_DATA);
- unsigned char **ptr;
-
- if ((Pixrect *)panel_get(button, PANEL_LABEL_IMAGE) == &left_arrow)
- step_size = -step_size;
-
- ptr = (unsigned char **) panel_get(my_slider, PANEL_CLIENT_DATA);
- for (i = cur_entry, prev = -1; i <= cur_range_end; i++) {
- new_val = (*ptr)[i] + (step_size * (proportional ? i-cur_entry+1 : 1));
- if (new_val > MAX_BRIGHTNESS)
- new_val = MAX_BRIGHTNESS;
- else if (new_val < 0)
- new_val = 0;
- avgP = (avgP | (prev == -1 ? FALSE : (prev != new_val)));
- total += ((*ptr)[i] = prev = new_val);
- }
- UpdateColorMaps(U_NEW_COLOR);
- panel_set(my_slider, PANEL_VALUE, total/(cur_range_end-cur_entry+1), 0);
- panel_set((Panel_item)panel_get(my_slider, PANEL_NEXT_ITEM),
- PANEL_SHOW_ITEM, avgP, 0);
- }
-
-
-
- /*
- * Copy - Copy the current range onto the clipboard.
- */
-
- static void Copy()
- {
- void UpdateColorMaps();
- int nbytes;
-
- clipboard_entries = 1+(cur_range_end-cur_entry);
- nbytes = sizeof(unsigned char)*clipboard_entries;
- bcopy((char *) cur_map.cm_red + cur_entry,
- (char *) clipboard.cm_red, nbytes);
- bcopy((char *) cur_map.cm_green + cur_entry,
- (char *) clipboard.cm_green, nbytes);
- bcopy((char *) cur_map.cm_blue + cur_entry,
- (char *) clipboard.cm_blue, nbytes);
- }
-
-
- /*
- * Paste - Paste the clipboard contents onto the current CMS starting at
- * the current entry.
- */
-
- static void Paste()
- {
- void UpdateColorMaps();
-
- int nbytes = sizeof(unsigned char) *
- (clipboard_entries + cur_entry > cur_size ?
- cur_size - cur_entry : clipboard_entries);
-
- bcopy((char *) clipboard.cm_red, (char *) cur_map.cm_red + cur_entry,
- nbytes);
- bcopy((char *) clipboard.cm_green, (char *) cur_map.cm_green + cur_entry,
- nbytes);
- bcopy((char *) clipboard.cm_blue, (char *) cur_map.cm_blue + cur_entry,
- nbytes);
- UpdateColorMaps(U_NEW_COLOR);
- SelectEntry(cur_entry, cur_range_end);
- if (clipboard_entries > (nbytes / sizeof(unsigned char)))
- Message("<Only the first %d clipboard items fit.>",
- (nbytes / sizeof(unsigned char)));
- }
-
-
-
- /*
- * KeyEvent - Take the appropriate action when the user types a key.
- * Note that ascii input from all three windows are directed
- * to the control_panel.
- * All that crap with esp_seq is necessary because you
- * can't get KEY_RIGHT() events for the arrow keys. (At
- * least not on my Sun3/160.) So this routine looks for a
- * consecutive <Esc>[n, where "n" is D or C.
- */
-
- static void KeyEvent(win, event, arg)
- Window win;
- Event *event;
- caddr_t arg;
- {
- void SelectEntry();
- void Quit();
-
- static short esq_seq = 0;
-
- if (esq_seq == 2)
- switch (event_id(event)) {
- case 'D':
- event_set_id(event, '<');
- break;
- case 'C':
- event_set_id(event, '>');
- break;
- }
-
- switch(event_id(event)) {
- case '\033':
- esq_seq = 1;
- break;
- case '[':
- if (esq_seq == 1)
- esq_seq = 2;
- break;
- case '<':
- SelectEntry(cur_entry-1, -1);
- esq_seq = 0;
- break;
- case '>':
- SelectEntry(cur_entry+1, -1);
- esq_seq = 0;
- break;
- case '\003':
- Quit();
- default:
- esq_seq = 0;
- window_default_event_proc(win, event, arg);
- break;
-
- }
- }
-
-
- /*
- * KeyedEntry - Preprocess keyboard input to the Current Color item.
- * Only allow digits and periods to be entered. When
- * Return is pressed, parse the text for the starting and
- * ending values of the new range. If no starting or ending
- * range is found, assume zero and the highest value in the
- * current colormap, respectively.
- */
-
- static Panel_setting
- KeyedEntry(item, event)
- Panel_item item;
- Event *event;
- {
- extern int atoi();
- void SelectEntry();
- int t1, t2;
- boolean error_flag = false;
- char *s, *ptr;
-
- if (event_id(event)=='\r' || event_id(event)=='\n') {
- if (ptr = rindex(s = panel_get_value(item), '.')) {
- if (*++ptr == '\0')
- t1 = cur_size-1;
- else
- t1 = atoi(ptr);
- if (t1 >= cur_size || (t2 = atoi(s)) > cur_size)
- error_flag = true;
- else
- SelectEntry(t2, t1);
- }
- else if ((t1 = atoi(panel_get_value(item))) < cur_size)
- SelectEntry(atoi(panel_get_value(item)), -1);
- else
- error_flag = true;
-
- if (error_flag)
- Message("<Valid colors for this cms are 0..%d>", cur_size-1);
- }
- else if (iscntrl(event_id(event)) || isdigit(event_id(event)) ||
- event_id(event) == '.')
- return(panel_text_notify(item, event));
-
- return(PANEL_NONE);
- }
-
-
- /*
- * NumericText - Notify procedure for a text item that only wants
- * digits in itself.
- */
-
- static Panel_setting
- NumericText(item, event)
- Panel_item item;
- Event *event;
- {
- return ((isdigit(event_id(event)) || iscntrl(event_id(event))) ?
- panel_text_notify(item, event) : PANEL_NONE);
- }
-
-
-
-
- /*
- * UpdateColorMaps - Sets the colormap of the four local windows
- * acccording to the value of use_colormap. The
- * amount of action required is determined by the
- * type parameter and the current state of the
- * use_colormap variable.
- *
- * U_NEW_COLOR - simply updates the window manager's record
- * of the current CMS to match Palette's.
- * U_NEW_CMS - tells the window manager to assign a new
- * colormap to Palette's canvas window, or to
- * all its windows if use_colormap is true.
- * U_NEW_STATE - Sets the colormaps of the other (non-canvas)
- * windows when the "Palette's Colormap" feature
- * gets toggled. Forces the wm to redraw the
- * windows too.
- */
-
- static void UpdateColorMaps(type)
- enum updatecolor_msg type;
- {
- int i, win_limit;
- char *name;
-
- name = cur_name;
- win_limit = ((type == U_NEW_STATE || use_colormap) ? NUM_MY_WINDOWS : 1);
- for (i = (type==U_NEW_STATE? 0 : -1); ++i < win_limit;) {
- if (i == 1 && !use_colormap)
- name = frame_cms_name;
- if (i == 2 && !use_colormap)
- name = subwins_cms_name;
-
- if (type != U_NEW_COLOR)
- pw_setcmsname(my_pixies[i], name);
-
- if (i==0 || use_colormap)
- pw_putcolormap(my_pixies[i], 0, cur_size,
- cur_map.cm_red, cur_map.cm_green, cur_map.cm_blue);
- }
- if (type == U_NEW_STATE || (type == U_NEW_CMS && use_colormap)) {
- wmgr_refreshwindow(my_frame_fd);
- if (cur_size > 4 && cur_size < MAX_COLORS && use_colormap)
- window_set(frame, FRAME_ICON, color_icon, 0);
- else
- window_set(frame, FRAME_ICON, &mono_icon, 0);
- }
- }
-
-
- /*
- * UseColorMap - Change state of the Palette's Colormap feature, and
- * update the windows as appropriate.
- *
- * See BorrowFramesCMS for explanation of the conditional
- * statments.
- */
-
- static void UseColorMap(item, value, event)
- Panel_item item;
- int value;
- Event *event;
- {
- void UpdateColorMaps(), BorrowFramesCMS(), SelectCMS();
- char *glob_name = cur_name;
-
- if (value == false)
- BorrowFramesCMS();
-
- use_colormap = value;
- UpdateColorMaps(U_NEW_STATE);
-
- if (value == false)
- SelectCMS(glob_name);
- }
-
-
-
- /*
- * WalkDepth
- */
-
- static void WalkDepth(item, value, event)
- Panel_item item;
- int value;
- Event *event;
- {
- shallow_walkP = (boolean) value;
- }
-
-
-
- /*
- * CreateNewMap - Enter a new map in the colormap table.
- */
-
- static void CreateNewMap()
- {
- extern char *malloc();
- extern int getpid();
- boolean MakeCMS();
- static int gensym = 0;
- static struct colormapseg data; /* static so cur_name can point to it. */
- int i;
-
- (void) sprintf(data.cms_name, "Palette%d-%d", getpid(), ++gensym);
- data.cms_size = 1<<((int)panel_get_value(new_map_size)+1);
-
- cur_map.cm_red = (unsigned char *) malloc((unsigned) data.cms_size);
- cur_map.cm_green = (unsigned char *) malloc((unsigned) data.cms_size);
- cur_map.cm_blue = (unsigned char *) malloc((unsigned) data.cms_size);
- for (i = -1; ++i < data.cms_size;)
- cur_map.cm_red[i] = cur_map.cm_green[i] = cur_map.cm_blue[i] =
- i*(255/(data.cms_size-1.0));
-
- if (MakeCMS(&data, &cur_map)) {
- panel_paint(table_panel, PANEL_NO_CLEAR);
- SelectCMS(data.cms_name);
- }
- else
- Message("<Error: CMS table full. Try \"Reread Maps\".>", 0);
- }
-
-
-
-
- /*
- * Save - Save the current colormap in the specified file, in one of the
- * three specified formats.
- */
-
- static void Save()
- {
- FILE *fp;
- int i;
- char *name;
- char buf[180];
- boolean error = false;
- /* RGB array */
- int c;
- unsigned char **ptr;
-
- /* Rasterfile */
- extern int SavePalette();
- colormap_t colormap;
- Pixrect *null_pr;
-
- if (fp = fopen(name = panel_get_value(file_name), "r")) {
- (void) fclose(fp);
- (void) sprintf(buf, "The file \"%s\" exists. Press the left mouse\
- button to overwrite. To cancel press the right mouse button.", name);
- if (wmgr_confirm(my_frame_fd, buf) == 0) {
- Message("Save operation cancelled.", 0);
- return;
- }
- }
- fp = fopen(panel_get_value(file_name), "w");
- if (fp==NULL) {
- error = true;
- Message("<Error: Couldn't open specified file.>", 0);
- }
- else {
- switch((int)panel_get_value(file_type)) {
- case 0: /* RGB arrays */
- for (i = -1; ++i<3;) {
- switch (i) {
- case 0:
- name = "red";
- ptr = &(cur_map.cm_red);
- break;
- case 1:
- name = "green";
- ptr = &(cur_map.cm_green);
- break;
- case 2:
- name = "blue";
- ptr = &(cur_map.cm_blue);
- break;
- }
-
- (void) fprintf(fp, "unsigned char %s[%d] = %*c", name, cur_size,
- (2*(i==0)+(i==2)+(cur_size>11)+(cur_size<100)), '{');
- for(c = -1; ++c < cur_size;) {
- if ((c%16) == 11)
- (void) fprintf(fp, "\n/*%3d*/ ", c );
- (void) fprintf(fp, "%3d%c", (*ptr)[c],
- (c==cur_size-1 ? '}' : ','));
- }
- (void) fprintf(fp, ";\n\n");
- }
- break;
- case 1: /* Number list */
- for (i = -1; ++i < cur_size; )
- (void) fprintf(fp, "%3d %3d %3d\n", *(cur_map.cm_red+i),
- *(cur_map.cm_green+i), *(cur_map.cm_blue+i));
- break;
- case 2: /* Null rasterfile w/ colormap */
- colormap.type = RMT_EQUAL_RGB;
- colormap.length = cur_size;
- colormap.map[0] = cur_map.cm_red;
- colormap.map[1] = cur_map.cm_green;
- colormap.map[2] = cur_map.cm_blue;
-
- null_pr = mem_create(0, 0, 8);
-
- if (pr_dump(null_pr, fp, &colormap, RT_STANDARD, 0))
- error = true;
- pr_destroy(null_pr);
- break;
- case 3: /* Picture of the palette */
- colormap.type = RMT_EQUAL_RGB;
- colormap.length = cur_size;
- colormap.map[0] = cur_map.cm_red;
- colormap.map[1] = cur_map.cm_green;
- colormap.map[2] = cur_map.cm_blue;
-
- DrawPalette(cur_size);
-
- if (SavePalette(fp, &colormap))
- error = true;
-
- HighlightSwatch(cur_entry, cur_size-1);
- break;
- }
- (void) fclose(fp);
- if (error)
- Message("<Error occured while writing to file.>", 0);
- else
- Message("File written.", 0);
- }
- }
-
- /*
- * Load
- */
-
- /*
- * Load calls three auxiliary routines. Each takes an open FILE *
- * and returns a count of how many colors it read in, or:
- * 0 to indicate that the file is not of the required type.
- * -1 to indicate that it's the right type but an error occurred
- * before any loading took place.
- * -2 the colormap was partially loaded when an error occurred
- * (this is bogus).
- * The subroutine displays an error message whenever -1 or -2 is returned.
- */
-
- static void Load()
- {
- void UpdateColorMaps();
- int Load_NumList(), Load_Rasterfile(), Load_C_Array();
-
- FILE *fp;
- int ccount;
-
- if (cur_size == 2)
- Message("<Error: Can't load into a 2 color map.>", 0);
- if (fp = fopen(panel_get_value(file_name), "r")) {
- if ((ccount = Load_NumList(fp)) == 0) {
- rewind(fp);
- if ((ccount = Load_Rasterfile(fp)) == 0) {
- rewind(fp);
- if ((ccount = Load_C_Array(fp)) == 0)
- Message("<Error: Couldn't find any colors in file.>", 0);
- }
- }
- if (ccount > 0)
- Message("<Loaded %d color map from file.>", ccount);
- if (ccount > 0 || ccount == -2)
- UpdateColorMaps(U_NEW_COLOR);
- (void) fclose(fp);
- }
- else
- Message("<Error: Couldn't open specified file>", 0);
- }
-
-
- static int Load_NumList(fp)
- FILE *fp;
- {
- int tem1, tem2, tem3;
- int i;
-
- for(i = -1;
- fscanf(fp, "%d %d %d", &tem1, &tem2, &tem3) == 3 &&
- ++i < cur_size; ) {
- *(cur_map.cm_red + i) = tem1;
- *(cur_map.cm_green + i) = tem2;
- *(cur_map.cm_blue + i) = tem3;
- }
- if (i == cur_size) {
- Message("<Error: Only the first %d colors fit.>", i);
- return(-2);
- }
- else
- return(i == -1 ? 0 : i+1);
- }
-
-
- static int Load_Rasterfile(fp)
- FILE *fp;
- {
- struct rasterfile rh;
- colormap_t colormap;
- enum {NOT_A_RASTERFILE, DID_GOOD, ERROR} status = ERROR;
- boolean isa_rasterfile = true;
-
- if (pr_load_header(fp, &rh) == PIX_ERR)
- status = NOT_A_RASTERFILE;
- else if (rh.ras_maplength == 0 || rh.ras_maptype == RMT_NONE)
- Message("<Error: File's colormap is empty.>", 0);
- else if (rh.ras_maptype != RMT_EQUAL_RGB)
- Message("<Error: File's colormap not of type RMT_EQUAL_RGB", 0);
- else if ((colormap.length = rh.ras_maplength / 3) > cur_size)
- Message("<Error: Can't fit %d colors into current map>",
- colormap.length);
- else {
- colormap.type = RMT_EQUAL_RGB;
- colormap.map[0] = cur_map.cm_red;
- colormap.map[1] = cur_map.cm_green;
- colormap.map[2] = cur_map.cm_blue;
- /* Note colormap.length set above */
- if (pr_load_colormap(fp, &rh, &colormap) == PIX_ERR)
- Message("<Major bummer: Error while reading the colormap.>", 0);
- else
- status = DID_GOOD;
- }
-
- return((status==DID_GOOD ? colormap.length :
- (status==NOT_A_RASTERFILE ? 0 : -1)));
- }
-
- static int Load_C_Array(fp)
- FILE *fp;
- {
- char buf[BUFSIZ];
- char *targ, *ptr;
- int rgb, ccolor = 0;
- boolean in_comment = false;
- unsigned char *cur_array;
-
- do {
- do {
- if (ptr = fgets(buf, BUFSIZ, fp))
- for (targ = "char red[", ptr = buf; *targ && *ptr; )
- if (*ptr++ == *targ)
- ++targ;
- } while (ptr && (*targ != '\0'));
- } while (ptr && !index(ptr, '='));
-
- if (ptr) { /* Hey, we found our target! */
- for (rgb = -1; ++rgb < 3; ) {
- ccolor = 0;
- cur_array = (rgb == 0 ? cur_map.cm_red :
- (rgb == 1 ? cur_map.cm_green :
- cur_map.cm_blue));
- while (*ptr != '{')
- if (*ptr == '\0') {
- ptr = fgets(buf, BUFSIZ, fp);
- if (ptr == NULL) {
- Message("<Error: EOF in color array.>", 0);
- return(rgb == 0 ? -1 : -2);
- }
- }
- else
- ++ptr;
-
- if (*ptr) { /* Found the open brace. */
- while (1) {
- /* Get a new line when you finish one */
- if (*ptr == '\0') {
- ptr = fgets(buf, BUFSIZ, fp);
- if (ptr == NULL) {
- Message("<Error: EOF in color array.>", 0);
- return(-2);
- }
- }
- if (*ptr == '}')
- break;
-
- /* Look for comments */
- if (*ptr == '/' && *(ptr+1) == '*')
- in_comment = true;
- if (*ptr == '*' && *(ptr+1) == '/')
- in_comment = false;
-
- /* This is a number, read it */
- if (!in_comment && isdigit(*ptr)) {
- *(cur_array + ccolor++) = atoi(ptr);
- while (isdigit(*++ptr))
- ;
- }
- else
- ++ptr;
- }
- }
- }
- }
- return(ccolor);
- }
-
-
-
- /*
- * Quit
- */
-
- static void Quit()
- {
- exit(0);
- }
-
-
- /*
- * Reread_Maps - Do a brute force reread of the colormaps. Delete
- * everything in the hash table and the table_panel. Then
- * walk down the tree the same as at startup (except this
- * time, our windows are in the tree).
- */
-
- static void Reread_Maps(item, event)
- Panel_item item;
- Event *event;
- {
- int Get_Root();
- boolean WalkWinTree();
- void SelectCMS();
- char *item_name;
- int rootfd;
-
- if (panel_get_value(reset_on_reread)==0) {
- panel_each_item(table_panel, item)
- item_name = (char *) panel_get(item, PANEL_LABEL_STRING);
- *(rindex(item_name, '[')-1) = '\0';
- H_Delete(item_name);
- panel_destroy_item(item);
- panel_end_each
- }
- if ((rootfd=Get_Root(control_panel))==-1)
- Message("<Error: Couldn't open root window device.>", 0);
- else {
- if (!WalkWinTree(rootfd, shallow_walkP))
- Message("<Error: CMS table full. Not all windows processed.>", 0);
- (void) close(rootfd);
- if (H_Member(cur_name, NIL(struct cms_map), NIL(Panel_item *)))
- item_name = cur_name;
- else
- item_name = frame_cms_name;
-
- cur_name = NULL;
- SelectCMS(item_name);
- panel_paint(table_panel, PANEL_CLEAR);
- }
- }
-
-
- /*
- * MakeCMS - Create a new entry as specified by the two params and
- * return true if it doesn't already exist. Otherwise, do
- * nothing and return false.
- */
-
- boolean MakeCMS(cmsdata, themap)
- struct colormapseg *cmsdata;
- struct cms_map *themap;
- {
- char buf[CMS_NAMESIZE+6];
- char *ptr;
- Panel_item item;
-
- (void) sprintf(buf, "%s [%d]", cmsdata->cms_name, cmsdata->cms_size);
-
- for (ptr=buf+strlen(buf); ptr < buf+CMS_NAMESIZE+6-5; ++ptr)
- *ptr = ' ';
- *ptr = '\0';
-
- item = panel_create_item(table_panel, PANEL_MESSAGE,
- PANEL_LABEL_STRING, buf,
- 0);
- if (H_Insert(cmsdata->cms_name, cmsdata->cms_size, item, themap)==false) {
- panel_destroy_item(item);
- return(false);
- }
- else
- return(true);
- }
-
-
- /*
- * ClickOnCMS - Find out which colormap name was clicked on and make it
- * the current color.
- * If it was shift-clicked, delete it from the table.
- */
-
- static void ClickOnCMS(item, event)
- Panel_item item;
- Event *event;
- {
- void SelectCMS();
- static char buf[CMS_NAMESIZE+6]; /* static so cur_name can point to it. */
-
- if (event_id(event) == MS_LEFT && event_is_down(event)) {
- (void) strcpy(buf, panel_get(item, PANEL_LABEL_STRING));
- *(rindex(buf, '[')-1) = '\0';
- if (event_shift_is_down(event)) {
- if (!strcmp(buf, frame_cms_name))
- Message("<Error: Can't delete Palette's colormap>", 0);
- else {
- Message("", 0);
- if (item == cur_cms_item)
- SelectCMS(frame_cms_name);
- H_Delete(buf);
- panel_destroy_item(item);
- panel_paint(table_panel, PANEL_CLEAR);
- }
- }
- else
- SelectCMS(buf);
- }
- }
-
-
- /*
- * ResizeCanvas - Call the canvas.c package routine when the canvas size
- * changes. Then redraw the palette. Also if necessary,
- * call the routine which defends against a window system
- * bug. See BorrowFramesCMS() for details.
- */
-
- static void ResizeCanvas()
- {
- extern void SetPaletteSize();
- void BorrowFramesCMS();
- boolean glob_use = use_colormap;
- char *glob_name = cur_name;
-
- SetPaletteSize();
- use_colormap = false; /* So Palette's other win's don't redraw, too */
- if (cur_size > 2)
- BorrowFramesCMS();
- SelectCMS(glob_name);
- use_colormap = glob_use;
- }
-
-
-
- /*
- * CanvasEvent - Do the right thing with the variety of left- and
- * right-clicks, and drags.
- */
-
- static void CanvasEvent(win, event, arg)
- Window win;
- Event *event;
- caddr_t arg;
- {
- extern void DrawPalette(), BoxSwatches();
- extern int WhichSwatch();
- void SelectEntry();
- int selection;
-
- if (event_id(event) == LOC_DRAG || event_is_button(event)) {
- selection = WhichSwatch(event_x(event), event_y(event));
- if (selection < 0) /* Clicking outside the rect erases the selection */
- DrawPalette(cur_size);
- else if (selection != cur_range_end && selection != cur_entry &&
- ((event_id(event) == MS_MIDDLE && event_is_down(event)) ||
- (event_id(event) == MS_LEFT && event_is_up(event)) ||
- event_id(event) == LOC_DRAG))
- SelectEntry(cur_entry, selection);
- else if (event_id(event) == MS_LEFT && event_is_down(event)) {
- SelectEntry(selection, -1);
- }
- }
- }
-
-
- /*
- * SelectCMS - Get the specs for a colormap, and make it the current one.
- * Note, that there should never be an error, since if a map
- * isn't in the table, the user should have no way to get it
- * to here.
- */
-
- static void SelectCMS(name)
- char *name;
- {
- extern void DrawPalette();
- void UpdateColorMaps();
-
- int size;
-
- if (cur_name)
- panel_set(cur_cms_item, PANEL_LABEL_BOLD, FALSE, 0);
- if (size = H_Member(name, &cur_map, &cur_cms_item)) {
- cur_size = size;
- cur_name = name;
- panel_set(cur_cms_item, PANEL_LABEL_BOLD, TRUE, 0);
- UpdateColorMaps(U_NEW_CMS);
- SelectEntry(cur_entry >= cur_size ? 0 : cur_entry,
- cur_range_end >= cur_size ? -1 : cur_range_end);
- }
- else
- Message("<Weird error: Colormap not in hash table.>", 0);
- }
-
-
-
-
- /*
- * BorrowFramesCMS - SunOS 3.4 apparently gets troubled by deep
- * pixrects and by changes made to a retained pixwin
- * behind its back. Specifically, when a canvas gets
- * resized, the backing pixrect (pw_prretained) gets
- * set to a depth of 1 even for 8 bit deep pixwins.
- * If a color window gets set back to its original
- * color, the scrollbar color gets messed up. Also,
- * when changing a window's icon from an 8-bit to a
- * one bit, two WINGETCMS ioctl errors are generated.
- *
- * This routine protects against that by allowing
- * callers to borrow the frame's original colormap
- * before doing any the above operations. It's a
- * nasty kludge, and a lousy description of the
- * problem. But, hey, get outta my face.
- */
-
- static void BorrowFramesCMS()
- {
- void SelectCMS();
-
- int glob_entry = cur_entry;
- int glob_range_end = cur_range_end;
-
- SelectCMS(frame_cms_name);
- cur_entry = glob_entry; /* In case it was reset to 0 in SelectCMS() */
- cur_range_end = glob_range_end;
- }
-
-