2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* CMWcommands.c --
|
|
|
|
|
*
|
|
|
|
|
* Commands for the color map editor.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
|
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
|
|
|
* * software and its documentation for any purpose and without *
|
|
|
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
|
|
|
* * notice appear in all copies. The University of California *
|
|
|
|
|
* * makes no representations about the suitability of this *
|
|
|
|
|
* * software for any purpose. It is provided "as is" without *
|
|
|
|
|
* * express or implied warranty. Export of this software outside *
|
|
|
|
|
* * of the United States of America may require an export license. *
|
2017-04-25 14:41:48 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef lint
|
2024-10-04 12:28:46 +02:00
|
|
|
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWcmmnds.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
2017-04-25 14:41:48 +02:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "tcltk/tclmagic.h"
|
|
|
|
|
#include "utils/magic.h"
|
|
|
|
|
#include "utils/geometry.h"
|
|
|
|
|
#include "windows/windows.h"
|
|
|
|
|
#include "tiles/tile.h"
|
|
|
|
|
#include "utils/hash.h"
|
|
|
|
|
#include "database/database.h"
|
|
|
|
|
#include "dbwind/dbwind.h"
|
|
|
|
|
#include "utils/main.h"
|
|
|
|
|
#include "commands/commands.h"
|
|
|
|
|
#include "cmwind/cmwind.h"
|
|
|
|
|
#include "graphics/graphics.h"
|
|
|
|
|
#include "textio/textio.h"
|
|
|
|
|
#include "utils/utils.h"
|
|
|
|
|
#include "utils/styles.h"
|
|
|
|
|
#include "textio/txcommands.h"
|
|
|
|
|
#include "utils/undo.h"
|
|
|
|
|
|
|
|
|
|
/* Forward declarations: */
|
|
|
|
|
|
2024-10-04 12:20:05 +02:00
|
|
|
extern void cmwButtonUp(MagWindow *w, Point *p, int button);
|
|
|
|
|
extern void cmwButtonDown(MagWindow *w, Point *p, int button);
|
|
|
|
|
extern void cbUpdate(MagWindow *w, int code, double x, int replace);
|
|
|
|
|
extern bool RGBxHSV(double r, double g, double b, double *h, double *s, double *v);
|
|
|
|
|
extern void HSVxRGB(double h, double s, double v, double *r, double *g, double *b);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* If a button is pressed over the top box in the window, which
|
|
|
|
|
* displays the current color, we must save the window in which
|
|
|
|
|
* it was pressed for use when the button is released. We also
|
|
|
|
|
* set a flag so we remember to process the button release.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MagWindow *cmwWindow;
|
|
|
|
|
bool cmwWatchButtonUp;
|
|
|
|
|
|
|
|
|
|
/* The following variable keeps track of whether or not the color
|
|
|
|
|
* map has been modified, so that we can warn the user if he attempts
|
|
|
|
|
* to exit or load a new color map without saving the changes.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool cmwModified = FALSE;
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CMWcommand --
|
|
|
|
|
*
|
|
|
|
|
* This procedure is invoked by the window package whenever a
|
|
|
|
|
* button is pushed or a command is typed while the cursor is
|
|
|
|
|
* over a colormap window.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* A color may be changed, depending on the command.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:22:59 +02:00
|
|
|
CMWcommand(
|
|
|
|
|
MagWindow *w,
|
|
|
|
|
TxCommand *cmd)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
switch (cmd->tx_button)
|
|
|
|
|
{
|
|
|
|
|
case TX_NO_BUTTON:
|
|
|
|
|
WindExecute(w, CMWclientID, cmd);
|
|
|
|
|
break;
|
|
|
|
|
case TX_LEFT_BUTTON:
|
|
|
|
|
case TX_RIGHT_BUTTON:
|
|
|
|
|
case TX_MIDDLE_BUTTON:
|
|
|
|
|
switch (cmd->tx_buttonAction)
|
|
|
|
|
{
|
|
|
|
|
case TX_BUTTON_UP:
|
|
|
|
|
cmwButtonUp(w, &(cmd->tx_p), cmd->tx_button);
|
|
|
|
|
break;
|
|
|
|
|
case TX_BUTTON_DOWN:
|
|
|
|
|
cmwButtonDown(w, &(cmd->tx_p), cmd->tx_button);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(FALSE, "CMWcommand");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UndoNext();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cmwButtonDown --
|
|
|
|
|
*
|
|
|
|
|
* Process the button command to change a color value.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* May update a color value. Depends on where the button is
|
|
|
|
|
* pushed. If a button is pushed over a color bar, then that
|
|
|
|
|
* bar is updated to fall where the cursor is. If a button
|
|
|
|
|
* is pushed over a color pump, the value is incremented or
|
|
|
|
|
* decremented, depending on which pump is hit. If the left
|
|
|
|
|
* button is pushed then a small increment is made (the value
|
|
|
|
|
* in the associated pump record). If one of the other buttons
|
|
|
|
|
* is pushed, an increment 5 times as great is made.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:22:59 +02:00
|
|
|
cmwButtonDown(
|
|
|
|
|
MagWindow *w, /* Window where the button was pressed. */
|
|
|
|
|
Point *p,
|
|
|
|
|
int button)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2024-10-04 12:33:56 +02:00
|
|
|
const ColorBar *cb;
|
|
|
|
|
const ColorPump *cp;
|
2017-04-25 14:41:48 +02:00
|
|
|
Point surfacePoint;
|
|
|
|
|
int x;
|
|
|
|
|
double dx;
|
|
|
|
|
|
|
|
|
|
if (w == NULL) return;
|
|
|
|
|
|
|
|
|
|
WindPointToSurface(w, p, &surfacePoint, (Rect *) NULL);
|
|
|
|
|
|
|
|
|
|
/* See if the cursor is over a color bar. */
|
|
|
|
|
|
|
|
|
|
for (cb = colorBars; cb->cb_name; cb++)
|
|
|
|
|
{
|
|
|
|
|
if (GEO_ENCLOSE(&surfacePoint, &cb->cb_rect))
|
|
|
|
|
{
|
|
|
|
|
x = surfacePoint.p_x;
|
|
|
|
|
x = MAX(x, cb->cb_rect.r_xbot);
|
|
|
|
|
x = MIN(x, cb->cb_rect.r_xtop);
|
|
|
|
|
dx = (double) (x - cb->cb_rect.r_xbot)
|
|
|
|
|
/ (double) (cb->cb_rect.r_xtop - cb->cb_rect.r_xbot);
|
|
|
|
|
cbUpdate(w, cb->cb_code, dx, TRUE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See if the cursor is over a color pump. */
|
|
|
|
|
|
|
|
|
|
for (cp = colorPumps; cp->cp_code >= 0; cp++)
|
|
|
|
|
{
|
|
|
|
|
if (GEO_ENCLOSE(&surfacePoint, &cp->cp_rect))
|
|
|
|
|
{
|
|
|
|
|
if (button == TX_LEFT_BUTTON)
|
|
|
|
|
cbUpdate(w, cp->cp_code, cp->cp_amount, FALSE);
|
|
|
|
|
else
|
|
|
|
|
cbUpdate(w, cp->cp_code, (double) 5*cp->cp_amount, FALSE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Note that the "color picker" function can't work as implemented
|
|
|
|
|
* because this function is registered only with the color window,
|
|
|
|
|
* so it cannot be called with a different window "w". So, we can
|
|
|
|
|
* only disable the button functions when pushed over the "current
|
|
|
|
|
* color area" rectangle.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef MAGIC_WRAPPER
|
|
|
|
|
|
|
|
|
|
/* See if the cursor is over the current color area. If so, remember
|
|
|
|
|
* the fact and wait for the button to be released.
|
|
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
if (GEO_ENCLOSE(&surfacePoint, &cmwCurrentColorArea))
|
|
|
|
|
{
|
|
|
|
|
cmwWindow = w;
|
|
|
|
|
cmwWatchButtonUp = TRUE;
|
|
|
|
|
if (button == TX_LEFT_BUTTON)
|
|
|
|
|
TxPrintf("Release button over new color to edit.\n");
|
|
|
|
|
else TxPrintf("Release button over color to copy.\n");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cmwButtonUp --
|
|
|
|
|
*
|
|
|
|
|
* This procedure handles button releases.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* The current color, or its value, may be changed.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:22:59 +02:00
|
|
|
cmwButtonUp(
|
|
|
|
|
MagWindow *w, /* Window where the button was released */
|
|
|
|
|
Point *p, /* Point where button was released, in window coords.*/
|
|
|
|
|
int button) /* Button that was released. */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
CMWclientRec *crec;
|
|
|
|
|
int r, g, b, color, oldR, oldG, oldB;
|
2024-10-04 12:20:05 +02:00
|
|
|
extern int cmwRedisplayFunc(MagWindow *w, int color);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* If the button wasn't depressed over the top box in the window
|
|
|
|
|
* (the one displaying the current color), then we ignore the
|
|
|
|
|
* button release.
|
|
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
if (!cmwWatchButtonUp) return;
|
|
|
|
|
cmwWatchButtonUp = FALSE;
|
|
|
|
|
|
|
|
|
|
/* If it's the left button, change the color being edited to the
|
|
|
|
|
* one at the pixel underneath the cursor. Otherwise, copy the
|
|
|
|
|
* color values from the pixel underneath the cursor to the current
|
|
|
|
|
* color.
|
|
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Read the pixel from the window that was underneath the cursor when
|
|
|
|
|
* the button was released.
|
|
|
|
|
*/
|
|
|
|
|
color = GrReadPixel(w, p->p_x, p->p_y);
|
|
|
|
|
if (color < 0)
|
|
|
|
|
{
|
|
|
|
|
TxError("Couldn't read that pixel!\n");
|
|
|
|
|
color = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (button == TX_LEFT_BUTTON)
|
|
|
|
|
CMWloadWindow(cmwWindow, color);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
crec = (CMWclientRec *) cmwWindow->w_clientData;
|
|
|
|
|
(void) GrGetColor(color, &r, &g, &b);
|
|
|
|
|
(void) GrGetColor(crec->cmw_color, &oldR, &oldG, &oldB);
|
|
|
|
|
(void) GrPutColor(crec->cmw_color, r, g, b);
|
|
|
|
|
cmwModified = TRUE;
|
|
|
|
|
|
|
|
|
|
/* Record old values for undo. */
|
|
|
|
|
cmwUndoColor(crec->cmw_color, oldR, oldG, oldB, r, g, b);
|
|
|
|
|
|
|
|
|
|
/* Mark all windows containing this color as modified */
|
|
|
|
|
(void) WindSearch(CMWclientID, (ClientData) NULL, (Rect *) NULL,
|
|
|
|
|
cmwRedisplayFunc, (ClientData)(pointertype) crec->cmw_color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cmwPushbutton --
|
|
|
|
|
*
|
|
|
|
|
* Usage:
|
|
|
|
|
* pushbutton <button>
|
|
|
|
|
*
|
|
|
|
|
* where button is "left", "middle", or "right".
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Performs the default action associated with the button event.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:22:59 +02:00
|
|
|
cmwPushbutton(
|
|
|
|
|
MagWindow *w,
|
|
|
|
|
TxCommand *cmd)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
int button;
|
2024-10-10 21:21:19 +02:00
|
|
|
static const char * const cmwButton[] = {"left", "middle", "right", NULL};
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
if (cmd->tx_argc != 2)
|
|
|
|
|
{
|
|
|
|
|
TxError("Usage: pushbutton <button>\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
button = Lookup(cmd->tx_argv[1], cmwButton);
|
|
|
|
|
if (button < 0)
|
|
|
|
|
{
|
|
|
|
|
TxError("Argument \"button\" must be one of "
|
|
|
|
|
"\"left\", \"middle\", or \"right\".\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else switch(button)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
cmd->tx_button = TX_LEFT_BUTTON;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
cmd->tx_button = TX_MIDDLE_BUTTON;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
cmd->tx_button = TX_RIGHT_BUTTON;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd->tx_buttonAction = TX_BUTTON_DOWN;
|
|
|
|
|
CMWcommand(w, cmd);
|
|
|
|
|
cmwWatchButtonUp = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cmwColor --
|
|
|
|
|
*
|
|
|
|
|
* Load a color map window with a particular color.
|
|
|
|
|
*
|
|
|
|
|
* Usage:
|
|
|
|
|
* color color-#|next|last|get|rgb
|
|
|
|
|
*
|
|
|
|
|
* where color-# is the octal number of the color to be edited.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Loads a new color into this window.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:22:59 +02:00
|
|
|
cmwColor(
|
|
|
|
|
MagWindow *w,
|
|
|
|
|
TxCommand *cmd)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
int color, r, g, b;
|
|
|
|
|
CMWclientRec *crec;
|
|
|
|
|
|
|
|
|
|
if (cmd->tx_argc == 1)
|
|
|
|
|
{
|
|
|
|
|
crec = (CMWclientRec *) w->w_clientData;
|
|
|
|
|
GrGetColor(crec->cmw_color, &r, &g, &b);
|
|
|
|
|
TxPrintf("Current color is %o octal (%d decimal) "
|
|
|
|
|
"(red = %d, green = %d, blue = %d)\n",
|
|
|
|
|
crec->cmw_color, crec->cmw_color, r, g, b);
|
|
|
|
|
}
|
|
|
|
|
else if (cmd->tx_argc == 2)
|
|
|
|
|
{
|
2024-09-30 02:50:14 +02:00
|
|
|
if (sscanf(cmd->tx_argv[1], "%i", &color) != 1)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
/* Invalid color---allow keywords "next" and "last" */
|
|
|
|
|
crec = (CMWclientRec *) w->w_clientData;
|
|
|
|
|
if (!strncmp(cmd->tx_argv[1], "next", 4))
|
|
|
|
|
{
|
|
|
|
|
color = crec->cmw_color + 1;
|
|
|
|
|
if (color >= GrNumColors)
|
|
|
|
|
color = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (!strncmp(cmd->tx_argv[1], "last", 4))
|
|
|
|
|
{
|
|
|
|
|
color = crec->cmw_color - 1;
|
|
|
|
|
if (color < 0)
|
|
|
|
|
color = GrNumColors - 1;
|
|
|
|
|
}
|
|
|
|
|
else if (!strncmp(cmd->tx_argv[1], "get", 3))
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(crec->cmw_color));
|
|
|
|
|
#else
|
|
|
|
|
TxPrintf("Color index %d\n", crec->cmw_color);
|
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (!strncmp(cmd->tx_argv[1], "rgb", 3))
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
Tcl_Obj *cobj = Tcl_NewListObj(0, NULL);
|
|
|
|
|
GrGetColor(crec->cmw_color, &r, &g, &b);
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, cobj, Tcl_NewIntObj(r));
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, cobj, Tcl_NewIntObj(g));
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, cobj, Tcl_NewIntObj(b));
|
|
|
|
|
Tcl_SetObjResult(magicinterp, cobj);
|
|
|
|
|
#else
|
|
|
|
|
GrGetColor(crec->cmw_color, &r, &g, &b);
|
|
|
|
|
TxPrintf("Color RGB=%d %d %d\n", r, g, b);
|
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
TxError("Usage: color [#|next|last|get|rgb]\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (color < 0 || color >= GrNumColors)
|
|
|
|
|
{
|
|
|
|
|
TxError("The colormap only has values from 0 to %d (decimal).\n",
|
|
|
|
|
(GrNumColors - 1));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
CMWloadWindow(w, color);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
else
|
2017-04-25 14:41:48 +02:00
|
|
|
TxError("Usage: color [#|next|last|get|rgb]\n");
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cmwSave --
|
|
|
|
|
*
|
|
|
|
|
* Save the color map to a disk file.
|
|
|
|
|
*
|
|
|
|
|
* Usage:
|
|
|
|
|
* save [techStyle displayStyle monitorType]
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Writes the color map out to disk.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:22:59 +02:00
|
|
|
cmwSave(
|
|
|
|
|
MagWindow *w,
|
|
|
|
|
TxCommand *cmd)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
bool ok;
|
|
|
|
|
if ((cmd->tx_argc != 1) && (cmd->tx_argc != 4))
|
|
|
|
|
{
|
|
|
|
|
TxError("Usage: %s [techStyle displayStyle monitorType]\n",
|
|
|
|
|
cmd->tx_argv[0]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (cmd->tx_argc > 1)
|
|
|
|
|
{
|
|
|
|
|
ok = GrSaveCMap(cmd->tx_argv[1], cmd->tx_argv[2],
|
|
|
|
|
cmd->tx_argv[3], ".", SysLibPath);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ok = GrSaveCMap(DBWStyleType, (char *) NULL, MainMonType,
|
|
|
|
|
".", SysLibPath);
|
|
|
|
|
}
|
|
|
|
|
if (ok) cmwModified = FALSE;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cmwLoad --
|
|
|
|
|
*
|
|
|
|
|
* Load a new color map from a disk file.
|
|
|
|
|
*
|
|
|
|
|
* Usage:
|
|
|
|
|
* load [file]
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* A new color map is read from disk. If the file name isn't
|
|
|
|
|
* given, the current technology, display type, etc. are used.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:22:59 +02:00
|
|
|
cmwLoad(
|
|
|
|
|
MagWindow *w,
|
|
|
|
|
TxCommand *cmd)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
if ((cmd->tx_argc != 1) && (cmd->tx_argc != 4))
|
|
|
|
|
{
|
|
|
|
|
TxError("Usage: %s [techStyle displayStyle monitorType]\n",
|
|
|
|
|
cmd->tx_argv[0]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!CMWCheckWritten()) return;
|
|
|
|
|
if (cmd->tx_argc == 4)
|
|
|
|
|
{
|
|
|
|
|
(void) GrReadCMap(cmd->tx_argv[1], cmd->tx_argv[2],
|
|
|
|
|
cmd->tx_argv[3], ".", SysLibPath);
|
|
|
|
|
}
|
|
|
|
|
else (void) GrReadCMap(DBWStyleType, (char *) NULL,
|
|
|
|
|
MainMonType, ".", SysLibPath);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* cbUpdate --
|
|
|
|
|
*
|
|
|
|
|
* Update the value stored with a particular color bar in
|
|
|
|
|
* this window. This is a low-level routine that does all
|
|
|
|
|
* the dirty work of updating colors.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* The color in window w is changed by either replacing one
|
|
|
|
|
* of its components (replace == TRUE), or by incrementing
|
|
|
|
|
* one of its components. All windows containing this color
|
|
|
|
|
* are forced to be redisplayed.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 12:22:59 +02:00
|
|
|
cbUpdate(
|
|
|
|
|
MagWindow *w, /* Window whose color is to be changed. */
|
|
|
|
|
int code, /* Indicates which color component to change. */
|
|
|
|
|
double x, /* Gives increment or new value for color. */
|
|
|
|
|
int replace) /* TRUE means replace component with x, FALSE
|
2017-04-25 14:41:48 +02:00
|
|
|
* means increment component by x.
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
CMWclientRec *cr = (CMWclientRec *) w->w_clientData;
|
|
|
|
|
double values[6];
|
|
|
|
|
int r, g, b, nr, ng, nb;
|
2024-10-04 12:20:05 +02:00
|
|
|
extern int cmwRedisplayFunc(MagWindow *w, int color);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* Get current color map values */
|
|
|
|
|
(void) GrGetColor(cr->cmw_color, &r, &g, &b);
|
|
|
|
|
values[CB_RED] = ((double) r) / 255.0;
|
|
|
|
|
values[CB_GREEN] = ((double) g) / 255.0;
|
|
|
|
|
values[CB_BLUE] = ((double) b) / 255.0;
|
|
|
|
|
RGBxHSV(values[CB_RED], values[CB_GREEN], values[CB_BLUE],
|
|
|
|
|
&values[CB_HUE], &values[CB_SAT], &values[CB_VALUE]);
|
|
|
|
|
|
|
|
|
|
/* Update the color that changed */
|
|
|
|
|
if (replace) values[code] = x;
|
|
|
|
|
else values[code] = values[code] + x;
|
|
|
|
|
if (values[code] > 1.0) values[code] = 1.0;
|
|
|
|
|
if (values[code] < 0.0) values[code] = 0.0;
|
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case CB_HUE:
|
|
|
|
|
case CB_SAT:
|
|
|
|
|
case CB_VALUE:
|
|
|
|
|
HSVxRGB(values[CB_HUE], values[CB_SAT], values[CB_VALUE],
|
|
|
|
|
&values[CB_RED], &values[CB_GREEN], &values[CB_BLUE]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Store this entry back in the color map */
|
|
|
|
|
nr = (int) (values[CB_RED] * 255.0 + 0.5);
|
|
|
|
|
ng = (int) (values[CB_GREEN] * 255.0 + 0.5);
|
|
|
|
|
nb = (int) (values[CB_BLUE] * 255.0 + 0.5);
|
|
|
|
|
(void) GrPutColor(cr->cmw_color, nr, ng, nb);
|
|
|
|
|
cmwModified = TRUE;
|
|
|
|
|
|
|
|
|
|
/* Record an undo entry */
|
|
|
|
|
cmwUndoColor(cr->cmw_color, r, g, b, nr, ng, nb);
|
|
|
|
|
|
|
|
|
|
/* Mark all windows containing this color as modified */
|
|
|
|
|
(void) WindSearch(CMWclientID, (ClientData) NULL, (Rect *) NULL,
|
|
|
|
|
cmwRedisplayFunc, (ClientData)(pointertype) cr->cmw_color);
|
|
|
|
|
|
|
|
|
|
/* Here. . . ought to mark the layout windows as modified? */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2024-10-04 12:22:59 +02:00
|
|
|
cmwRedisplayFunc(
|
|
|
|
|
MagWindow *w, /* Window that may have to be redisplayed. */
|
|
|
|
|
int color) /* If this color is in window, redisplay the
|
2017-04-25 14:41:48 +02:00
|
|
|
* color bars in the window.
|
|
|
|
|
*/
|
|
|
|
|
{
|
2024-10-04 12:33:56 +02:00
|
|
|
const ColorBar *cb;
|
|
|
|
|
const ColorPump *cp;
|
2017-04-25 14:41:48 +02:00
|
|
|
Rect screenR;
|
|
|
|
|
CMWclientRec *cr = (CMWclientRec *) w->w_clientData;
|
|
|
|
|
|
|
|
|
|
if (cr->cmw_color == color)
|
|
|
|
|
{
|
|
|
|
|
for (cb = colorBars; cb->cb_name; cb++)
|
|
|
|
|
{
|
|
|
|
|
WindSurfaceToScreen(w, &cb->cb_rect, &screenR);
|
|
|
|
|
WindAreaChanged(w, &screenR);
|
|
|
|
|
}
|
|
|
|
|
for (cp = colorPumps; cp->cp_code >= 0; cp++)
|
|
|
|
|
{
|
|
|
|
|
WindSurfaceToScreen(w, &cp->cp_rect, &screenR);
|
|
|
|
|
WindAreaChanged(w, &screenR);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Also update the "color being edited" rectangle */
|
|
|
|
|
WindSurfaceToScreen(w, &cmwCurrentColorArea, &screenR);
|
|
|
|
|
WindAreaChanged(w, &screenR);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CMWCheckWritten --
|
|
|
|
|
*
|
|
|
|
|
* Checks to see if the current color map has been modified
|
|
|
|
|
* but not written back to disk. If so, asks user whether he
|
|
|
|
|
* cares about the changes.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns TRUE if the color map hasn't been modified, or if
|
|
|
|
|
* the user says he doesn't care about the changes. Returns FALSE
|
|
|
|
|
* if the user says he cares.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
2024-10-04 12:22:59 +02:00
|
|
|
CMWCheckWritten(void)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
bool indx;
|
|
|
|
|
char *prompt;
|
2025-01-03 11:38:14 +01:00
|
|
|
static const char * const yesno[] = {"no", "yes", NULL};
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
if (!cmwModified) return TRUE;
|
|
|
|
|
prompt = TxPrintString("The color map has been modified.\n"
|
|
|
|
|
" Do you want to lose the changes? ");
|
|
|
|
|
indx = TxDialog(prompt, yesno, 0);
|
|
|
|
|
return indx;
|
|
|
|
|
}
|