blob: c492d9c19fe4e11b0342963832f6a2f9fe7bda05 [file] [log] [blame]
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% %
% W W IIIII DDDD GGGG EEEEE TTTTT %
% W W I D D G E T %
% W W W I D D G GG EEE T %
% WW WW I D D G G E T %
% W W IIIII DDDD GGGG EEEEE T %
% %
% %
% MagickCore X11 User Interface Methods %
% %
% Software Design %
% Cristy %
% September 1993 %
% %
% %
% Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
/*
Include declarations.
*/
#include "MagickCore/studio.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/image.h"
#include "MagickCore/magick.h"
#include "MagickCore/memory_.h"
#include "MagickCore/string_.h"
#include "MagickCore/token.h"
#include "MagickCore/token-private.h"
#include "MagickCore/utility.h"
#include "MagickCore/utility-private.h"
#include "MagickCore/xwindow-private.h"
#include "MagickCore/widget.h"
#include "MagickCore/widget-private.h"
#if defined(MAGICKCORE_X11_DELEGATE)
/*
Define declarations.
*/
#define AreaIsActive(matte_info,position) ( \
((position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
(position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
? MagickTrue : MagickFalse)
#define Extent(s) ((int) strlen(s))
#define MatteIsActive(matte_info,position) ( \
((position.x >= (int) (matte_info.x-matte_info.bevel_width)) && \
(position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \
(position.x < (int) (matte_info.x+matte_info.width+matte_info.bevel_width)) && \
(position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \
? MagickTrue : MagickFalse)
#define MaxTextWidth ((unsigned int) (255*XTextWidth(font_info,"_",1)))
#define MinTextWidth (26*XTextWidth(font_info,"_",1))
#define QuantumMargin MagickMax(font_info->max_bounds.width,12)
#define WidgetTextWidth(font_info,text) \
((unsigned int) XTextWidth(font_info,text,Extent(text)))
#define WindowIsActive(window_info,position) ( \
((position.x >= 0) && (position.y >= 0) && \
(position.x < (int) window_info.width) && \
(position.y < (int) window_info.height)) ? MagickTrue : MagickFalse)
/*
Enum declarations.
*/
typedef enum
{
ControlState = 0x0001,
InactiveWidgetState = 0x0004,
JumpListState = 0x0008,
RedrawActionState = 0x0010,
RedrawListState = 0x0020,
RedrawWidgetState = 0x0040,
UpdateListState = 0x0100
} WidgetState;
/*
Typedef declarations.
*/
typedef struct _XWidgetInfo
{
char
*cursor,
*text,
*marker;
int
id;
unsigned int
bevel_width,
width,
height;
int
x,
y,
min_y,
max_y;
MagickStatusType
raised,
active,
center,
trough,
highlight;
} XWidgetInfo;
/*
Variable declarations.
*/
static XWidgetInfo
monitor_info =
{
(char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
},
submenu_info =
{
(char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
},
*selection_info = (XWidgetInfo *) NULL,
toggle_info =
{
(char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0,
MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse
};
/*
Constant declarations.
*/
static const int
BorderOffset = 4,
DoubleClick = 250;
/*
Method prototypes.
*/
static void
XDrawMatte(Display *,const XWindowInfo *,const XWidgetInfo *),
XSetBevelColor(Display *,const XWindowInfo *,const MagickStatusType),
XSetMatteColor(Display *,const XWindowInfo *,const MagickStatusType),
XSetTextColor(Display *,const XWindowInfo *,const MagickStatusType);
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e s t r o y X W i d g e t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyXWidget() destroys resources associated with the X widget.
%
% The format of the DestroyXWidget method is:
%
% void DestroyXWidget()
%
% A description of each parameter follows:
%
*/
MagickPrivate void DestroyXWidget(void)
{
if (selection_info != (XWidgetInfo *) NULL)
selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w B e v e l %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawBevel() "sets off" an area with a highlighted upper and left bevel and
% a shadowed lower and right bevel. The highlighted and shadowed bevels
% create a 3-D effect.
%
% The format of the XDrawBevel function is:
%
% XDrawBevel(display,window_info,bevel_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o bevel_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the bevel.
%
*/
static void XDrawBevel(Display *display,const XWindowInfo *window_info,
const XWidgetInfo *bevel_info)
{
int
x1,
x2,
y1,
y2;
unsigned int
bevel_width;
XPoint
points[6];
/*
Draw upper and left beveled border.
*/
x1=bevel_info->x;
y1=bevel_info->y+bevel_info->height;
x2=bevel_info->x+bevel_info->width;
y2=bevel_info->y;
bevel_width=bevel_info->bevel_width;
points[0].x=x1;
points[0].y=y1;
points[1].x=x1;
points[1].y=y2;
points[2].x=x2;
points[2].y=y2;
points[3].x=x2+bevel_width;
points[3].y=y2-bevel_width;
points[4].x=x1-bevel_width;
points[4].y=y2-bevel_width;
points[5].x=x1-bevel_width;
points[5].y=y1+bevel_width;
XSetBevelColor(display,window_info,bevel_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,6,Complex,CoordModeOrigin);
/*
Draw lower and right beveled border.
*/
points[0].x=x1;
points[0].y=y1;
points[1].x=x2;
points[1].y=y1;
points[2].x=x2;
points[2].y=y2;
points[3].x=x2+bevel_width;
points[3].y=y2-bevel_width;
points[4].x=x2+bevel_width;
points[4].y=y1+bevel_width;
points[5].x=x1-bevel_width;
points[5].y=y1+bevel_width;
XSetBevelColor(display,window_info,!bevel_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,6,Complex,CoordModeOrigin);
(void) XSetFillStyle(display,window_info->widget_context,FillSolid);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w B e v e l e d B u t t o n %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawBeveledButton() draws a button with a highlighted upper and left bevel
% and a shadowed lower and right bevel. The highlighted and shadowed bevels
% create a 3-D effect.
%
% The format of the XDrawBeveledButton function is:
%
% XDrawBeveledButton(display,window_info,button_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o button_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the button.
%
*/
static void XDrawBeveledButton(Display *display,const XWindowInfo *window_info,
const XWidgetInfo *button_info)
{
int
x,
y;
unsigned int
width;
XFontStruct
*font_info;
XRectangle
crop_info;
/*
Draw matte.
*/
XDrawBevel(display,window_info,button_info);
XSetMatteColor(display,window_info,button_info->raised);
(void) XFillRectangle(display,window_info->id,window_info->widget_context,
button_info->x,button_info->y,button_info->width,button_info->height);
x=button_info->x-button_info->bevel_width-1;
y=button_info->y-button_info->bevel_width-1;
(void) XSetForeground(display,window_info->widget_context,
window_info->pixel_info->trough_color.pixel);
if (button_info->raised || (window_info->depth == 1))
(void) XDrawRectangle(display,window_info->id,window_info->widget_context,
x,y,button_info->width+(button_info->bevel_width << 1)+1,
button_info->height+(button_info->bevel_width << 1)+1);
if (button_info->text == (char *) NULL)
return;
/*
Set cropping region.
*/
crop_info.width=(unsigned short) button_info->width;
crop_info.height=(unsigned short) button_info->height;
crop_info.x=button_info->x;
crop_info.y=button_info->y;
/*
Draw text.
*/
font_info=window_info->font_info;
width=WidgetTextWidth(font_info,button_info->text);
x=button_info->x+(QuantumMargin >> 1);
if (button_info->center)
x=button_info->x+(button_info->width >> 1)-(width >> 1);
y=button_info->y+((button_info->height-
(font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
if ((int) button_info->width == (QuantumMargin >> 1))
{
/*
Option button-- write label to right of button.
*/
XSetTextColor(display,window_info,MagickTrue);
x=button_info->x+button_info->width+button_info->bevel_width+
(QuantumMargin >> 1);
(void) XDrawString(display,window_info->id,window_info->widget_context,
x,y,button_info->text,Extent(button_info->text));
return;
}
(void) XSetClipRectangles(display,window_info->widget_context,0,0,&crop_info,
1,Unsorted);
XSetTextColor(display,window_info,button_info->raised);
(void) XDrawString(display,window_info->id,window_info->widget_context,x,y,
button_info->text,Extent(button_info->text));
(void) XSetClipMask(display,window_info->widget_context,None);
if (button_info->raised == MagickFalse)
XDelay(display,SuspendTime << 2);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w B e v e l e d M a t t e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawBeveledMatte() draws a matte with a shadowed upper and left bevel and
% a highlighted lower and right bevel. The highlighted and shadowed bevels
% create a 3-D effect.
%
% The format of the XDrawBeveledMatte function is:
%
% XDrawBeveledMatte(display,window_info,matte_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o matte_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the matte.
%
*/
static void XDrawBeveledMatte(Display *display,const XWindowInfo *window_info,
const XWidgetInfo *matte_info)
{
/*
Draw matte.
*/
XDrawBevel(display,window_info,matte_info);
XDrawMatte(display,window_info,matte_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w M a t t e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawMatte() fills a rectangular area with the matte color.
%
% The format of the XDrawMatte function is:
%
% XDrawMatte(display,window_info,matte_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o matte_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the matte.
%
*/
static void XDrawMatte(Display *display,const XWindowInfo *window_info,
const XWidgetInfo *matte_info)
{
/*
Draw matte.
*/
if ((matte_info->trough == MagickFalse) || (window_info->depth == 1))
(void) XFillRectangle(display,window_info->id,
window_info->highlight_context,matte_info->x,matte_info->y,
matte_info->width,matte_info->height);
else
{
(void) XSetForeground(display,window_info->widget_context,
window_info->pixel_info->trough_color.pixel);
(void) XFillRectangle(display,window_info->id,window_info->widget_context,
matte_info->x,matte_info->y,matte_info->width,matte_info->height);
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w M a t t e T e x t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawMatteText() draws a matte with text. If the text exceeds the extents
% of the text, a portion of the text relative to the cursor is displayed.
%
% The format of the XDrawMatteText function is:
%
% XDrawMatteText(display,window_info,text_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o text_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the text.
%
*/
static void XDrawMatteText(Display *display,const XWindowInfo *window_info,
XWidgetInfo *text_info)
{
const char
*text;
int
n,
x,
y;
register int
i;
unsigned int
height,
width;
XFontStruct
*font_info;
XRectangle
crop_info;
/*
Clear the text area.
*/
XSetMatteColor(display,window_info,MagickFalse);
(void) XFillRectangle(display,window_info->id,window_info->widget_context,
text_info->x,text_info->y,text_info->width,text_info->height);
if (text_info->text == (char *) NULL)
return;
XSetTextColor(display,window_info,text_info->highlight);
font_info=window_info->font_info;
x=text_info->x+(QuantumMargin >> 2);
y=text_info->y+font_info->ascent+(text_info->height >> 2);
width=text_info->width-(QuantumMargin >> 1);
height=(unsigned int) (font_info->ascent+font_info->descent);
if (*text_info->text == '\0')
{
/*
No text-- just draw cursor.
*/
(void) XDrawLine(display,window_info->id,window_info->annotate_context,
x,y+3,x,y-height+3);
return;
}
/*
Set cropping region.
*/
crop_info.width=(unsigned short) text_info->width;
crop_info.height=(unsigned short) text_info->height;
crop_info.x=text_info->x;
crop_info.y=text_info->y;
/*
Determine beginning of the visible text.
*/
if (text_info->cursor < text_info->marker)
text_info->marker=text_info->cursor;
else
{
text=text_info->marker;
if (XTextWidth(font_info,(char *) text,(int) (text_info->cursor-text)) >
(int) width)
{
text=text_info->text;
for (i=0; i < Extent(text); i++)
{
n=XTextWidth(font_info,(char *) text+i,(int)
(text_info->cursor-text-i));
if (n <= (int) width)
break;
}
text_info->marker=(char *) text+i;
}
}
/*
Draw text and cursor.
*/
if (text_info->highlight == MagickFalse)
{
(void) XSetClipRectangles(display,window_info->widget_context,0,0,
&crop_info,1,Unsorted);
(void) XDrawString(display,window_info->id,window_info->widget_context,
x,y,text_info->marker,Extent(text_info->marker));
(void) XSetClipMask(display,window_info->widget_context,None);
}
else
{
(void) XSetClipRectangles(display,window_info->annotate_context,0,0,
&crop_info,1,Unsorted);
width=WidgetTextWidth(font_info,text_info->marker);
(void) XFillRectangle(display,window_info->id,
window_info->annotate_context,x,y-font_info->ascent,width,height);
(void) XSetClipMask(display,window_info->annotate_context,None);
(void) XSetClipRectangles(display,window_info->highlight_context,0,0,
&crop_info,1,Unsorted);
(void) XDrawString(display,window_info->id,
window_info->highlight_context,x,y,text_info->marker,
Extent(text_info->marker));
(void) XSetClipMask(display,window_info->highlight_context,None);
}
x+=XTextWidth(font_info,text_info->marker,(int)
(text_info->cursor-text_info->marker));
(void) XDrawLine(display,window_info->id,window_info->annotate_context,x,y+3,
x,y-height+3);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w T r i a n g l e E a s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawTriangleEast() draws a triangle with a highlighted left bevel and a
% shadowed right and lower bevel. The highlighted and shadowed bevels create
% a 3-D effect.
%
% The format of the XDrawTriangleEast function is:
%
% XDrawTriangleEast(display,window_info,triangle_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the triangle.
%
*/
static void XDrawTriangleEast(Display *display,const XWindowInfo *window_info,
const XWidgetInfo *triangle_info)
{
int
x1,
x2,
x3,
y1,
y2,
y3;
unsigned int
bevel_width;
XFontStruct
*font_info;
XPoint
points[4];
/*
Draw triangle matte.
*/
x1=triangle_info->x;
y1=triangle_info->y;
x2=triangle_info->x+triangle_info->width;
y2=triangle_info->y+(triangle_info->height >> 1);
x3=triangle_info->x;
y3=triangle_info->y+triangle_info->height;
bevel_width=triangle_info->bevel_width;
points[0].x=x1;
points[0].y=y1;
points[1].x=x2;
points[1].y=y2;
points[2].x=x3;
points[2].y=y3;
XSetMatteColor(display,window_info,triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,3,Complex,CoordModeOrigin);
/*
Draw bottom bevel.
*/
points[0].x=x2;
points[0].y=y2;
points[1].x=x3;
points[1].y=y3;
points[2].x=x3-bevel_width;
points[2].y=y3+bevel_width;
points[3].x=x2+bevel_width;
points[3].y=y2;
XSetBevelColor(display,window_info,!triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
/*
Draw Left bevel.
*/
points[0].x=x3;
points[0].y=y3;
points[1].x=x1;
points[1].y=y1;
points[2].x=x1-bevel_width+1;
points[2].y=y1-bevel_width;
points[3].x=x3-bevel_width+1;
points[3].y=y3+bevel_width;
XSetBevelColor(display,window_info,triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
/*
Draw top bevel.
*/
points[0].x=x1;
points[0].y=y1;
points[1].x=x2;
points[1].y=y2;
points[2].x=x2+bevel_width;
points[2].y=y2;
points[3].x=x1-bevel_width;
points[3].y=y1-bevel_width;
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
(void) XSetFillStyle(display,window_info->widget_context,FillSolid);
if (triangle_info->text == (char *) NULL)
return;
/*
Write label to right of triangle.
*/
font_info=window_info->font_info;
XSetTextColor(display,window_info,MagickTrue);
x1=triangle_info->x+triangle_info->width+triangle_info->bevel_width+
(QuantumMargin >> 1);
y1=triangle_info->y+((triangle_info->height-
(font_info->ascent+font_info->descent)) >> 1)+font_info->ascent;
(void) XDrawString(display,window_info->id,window_info->widget_context,x1,y1,
triangle_info->text,Extent(triangle_info->text));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w T r i a n g l e N o r t h %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawTriangleNorth() draws a triangle with a highlighted left bevel and a
% shadowed right and lower bevel. The highlighted and shadowed bevels create
% a 3-D effect.
%
% The format of the XDrawTriangleNorth function is:
%
% XDrawTriangleNorth(display,window_info,triangle_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the triangle.
%
*/
static void XDrawTriangleNorth(Display *display,const XWindowInfo *window_info,
const XWidgetInfo *triangle_info)
{
int
x1,
x2,
x3,
y1,
y2,
y3;
unsigned int
bevel_width;
XPoint
points[4];
/*
Draw triangle matte.
*/
x1=triangle_info->x;
y1=triangle_info->y+triangle_info->height;
x2=triangle_info->x+(triangle_info->width >> 1);
y2=triangle_info->y;
x3=triangle_info->x+triangle_info->width;
y3=triangle_info->y+triangle_info->height;
bevel_width=triangle_info->bevel_width;
points[0].x=x1;
points[0].y=y1;
points[1].x=x2;
points[1].y=y2;
points[2].x=x3;
points[2].y=y3;
XSetMatteColor(display,window_info,triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,3,Complex,CoordModeOrigin);
/*
Draw left bevel.
*/
points[0].x=x1;
points[0].y=y1;
points[1].x=x2;
points[1].y=y2;
points[2].x=x2;
points[2].y=y2-bevel_width-2;
points[3].x=x1-bevel_width-1;
points[3].y=y1+bevel_width;
XSetBevelColor(display,window_info,triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
/*
Draw right bevel.
*/
points[0].x=x2;
points[0].y=y2;
points[1].x=x3;
points[1].y=y3;
points[2].x=x3+bevel_width;
points[2].y=y3+bevel_width;
points[3].x=x2;
points[3].y=y2-bevel_width;
XSetBevelColor(display,window_info,!triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
/*
Draw lower bevel.
*/
points[0].x=x3;
points[0].y=y3;
points[1].x=x1;
points[1].y=y1;
points[2].x=x1-bevel_width;
points[2].y=y1+bevel_width;
points[3].x=x3+bevel_width;
points[3].y=y3+bevel_width;
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
(void) XSetFillStyle(display,window_info->widget_context,FillSolid);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w T r i a n g l e S o u t h %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawTriangleSouth() draws a border with a highlighted left and right bevel
% and a shadowed lower bevel. The highlighted and shadowed bevels create a
% 3-D effect.
%
% The format of the XDrawTriangleSouth function is:
%
% XDrawTriangleSouth(display,window_info,triangle_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o triangle_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the triangle.
%
*/
static void XDrawTriangleSouth(Display *display,const XWindowInfo *window_info,
const XWidgetInfo *triangle_info)
{
int
x1,
x2,
x3,
y1,
y2,
y3;
unsigned int
bevel_width;
XPoint
points[4];
/*
Draw triangle matte.
*/
x1=triangle_info->x;
y1=triangle_info->y;
x2=triangle_info->x+(triangle_info->width >> 1);
y2=triangle_info->y+triangle_info->height;
x3=triangle_info->x+triangle_info->width;
y3=triangle_info->y;
bevel_width=triangle_info->bevel_width;
points[0].x=x1;
points[0].y=y1;
points[1].x=x2;
points[1].y=y2;
points[2].x=x3;
points[2].y=y3;
XSetMatteColor(display,window_info,triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,3,Complex,CoordModeOrigin);
/*
Draw top bevel.
*/
points[0].x=x3;
points[0].y=y3;
points[1].x=x1;
points[1].y=y1;
points[2].x=x1-bevel_width;
points[2].y=y1-bevel_width;
points[3].x=x3+bevel_width;
points[3].y=y3-bevel_width;
XSetBevelColor(display,window_info,triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
/*
Draw right bevel.
*/
points[0].x=x2;
points[0].y=y2;
points[1].x=x3+1;
points[1].y=y3-bevel_width;
points[2].x=x3+bevel_width;
points[2].y=y3-bevel_width;
points[3].x=x2;
points[3].y=y2+bevel_width;
XSetBevelColor(display,window_info,!triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
/*
Draw left bevel.
*/
points[0].x=x1;
points[0].y=y1;
points[1].x=x2;
points[1].y=y2;
points[2].x=x2;
points[2].y=y2+bevel_width;
points[3].x=x1-bevel_width;
points[3].y=y1-bevel_width;
XSetBevelColor(display,window_info,triangle_info->raised);
(void) XFillPolygon(display,window_info->id,window_info->widget_context,
points,4,Complex,CoordModeOrigin);
(void) XSetFillStyle(display,window_info->widget_context,FillSolid);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D r a w W i d g e t T e x t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawWidgetText() first clears the widget and draws a text string justifed
% left (or center) in the x-direction and centered within the y-direction.
%
% The format of the XDrawWidgetText function is:
%
% XDrawWidgetText(display,window_info,text_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a XWindowText structure.
%
% o text_info: Specifies a pointer to XWidgetInfo structure.
%
*/
static void XDrawWidgetText(Display *display,const XWindowInfo *window_info,
XWidgetInfo *text_info)
{
GC
widget_context;
int
x,
y;
unsigned int
height,
width;
XFontStruct
*font_info;
XRectangle
crop_info;
/*
Clear the text area.
*/
widget_context=window_info->annotate_context;
if (text_info->raised)
(void) XClearArea(display,window_info->id,text_info->x,text_info->y,
text_info->width,text_info->height,MagickFalse);
else
{
(void) XFillRectangle(display,window_info->id,widget_context,text_info->x,
text_info->y,text_info->width,text_info->height);
widget_context=window_info->highlight_context;
}
if (text_info->text == (char *) NULL)
return;
if (*text_info->text == '\0')
return;
/*
Set cropping region.
*/
font_info=window_info->font_info;
crop_info.width=(unsigned short) text_info->width;
crop_info.height=(unsigned short) text_info->height;
crop_info.x=text_info->x;
crop_info.y=text_info->y;
/*
Draw text.
*/
width=WidgetTextWidth(font_info,text_info->text);
x=text_info->x+(QuantumMargin >> 1);
if (text_info->center)
x=text_info->x+(text_info->width >> 1)-(width >> 1);
if (text_info->raised)
if (width > (text_info->width-QuantumMargin))
x+=(text_info->width-QuantumMargin-width);
height=(unsigned int) (font_info->ascent+font_info->descent);
y=text_info->y+((text_info->height-height) >> 1)+font_info->ascent;
(void) XSetClipRectangles(display,widget_context,0,0,&crop_info,1,Unsorted);
(void) XDrawString(display,window_info->id,widget_context,x,y,text_info->text,
Extent(text_info->text));
(void) XSetClipMask(display,widget_context,None);
if (x < text_info->x)
(void) XDrawLine(display,window_info->id,window_info->annotate_context,
text_info->x,text_info->y,text_info->x,text_info->y+text_info->height-1);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X E d i t T e x t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XEditText() edits a text string as indicated by the key symbol.
%
% The format of the XEditText function is:
%
% XEditText(display,text_info,key_symbol,text,state)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o text_info: Specifies a pointer to a XWidgetInfo structure. It
% contains the extents of the text.
%
% o key_symbol: A X11 KeySym that indicates what editing function to
% perform to the text.
%
% o text: A character string to insert into the text.
%
% o state: An size_t that indicates whether the key symbol is a
% control character or not.
%
*/
static void XEditText(Display *display,XWidgetInfo *text_info,
const KeySym key_symbol,char *text,const size_t state)
{
switch ((int) key_symbol)
{
case XK_BackSpace:
case XK_Delete:
{
if (text_info->highlight)
{
/*
Erase the entire line of text.
*/
*text_info->text='\0';
text_info->cursor=text_info->text;
text_info->marker=text_info->text;
text_info->highlight=MagickFalse;
}
/*
Erase one character.
*/
if (text_info->cursor != text_info->text)
{
text_info->cursor--;
(void) memmove(text_info->cursor,text_info->cursor+1,
MagickPathExtent);
text_info->highlight=MagickFalse;
break;
}
}
case XK_Left:
case XK_KP_Left:
{
/*
Move cursor one position left.
*/
if (text_info->cursor == text_info->text)
break;
text_info->cursor--;
break;
}
case XK_Right:
case XK_KP_Right:
{
/*
Move cursor one position right.
*/
if (text_info->cursor == (text_info->text+Extent(text_info->text)))
break;
text_info->cursor++;
break;
}
default:
{
register char
*p,
*q;
register int
i;
if (state & ControlState)
break;
if (*text == '\0')
break;
if ((Extent(text_info->text)+1) >= (int) MagickPathExtent)
(void) XBell(display,0);
else
{
if (text_info->highlight)
{
/*
Erase the entire line of text.
*/
*text_info->text='\0';
text_info->cursor=text_info->text;
text_info->marker=text_info->text;
text_info->highlight=MagickFalse;
}
/*
Insert a string into the text.
*/
q=text_info->text+Extent(text_info->text)+strlen(text);
for (i=0; i <= Extent(text_info->cursor); i++)
{
*q=(*(q-Extent(text)));
q--;
}
p=text;
for (i=0; i < Extent(text); i++)
*text_info->cursor++=(*p++);
}
break;
}
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X G e t W i d g e t I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetWidgetInfo() initializes the XWidgetInfo structure.
%
% The format of the XGetWidgetInfo function is:
%
% XGetWidgetInfo(text,widget_info)
%
% A description of each parameter follows:
%
% o text: A string of characters associated with the widget.
%
% o widget_info: Specifies a pointer to a X11 XWidgetInfo structure.
%
*/
static void XGetWidgetInfo(const char *text,XWidgetInfo *widget_info)
{
/*
Initialize widget info.
*/
widget_info->id=(~0);
widget_info->bevel_width=3;
widget_info->width=1;
widget_info->height=1;
widget_info->x=0;
widget_info->y=0;
widget_info->min_y=0;
widget_info->max_y=0;
widget_info->raised=MagickTrue;
widget_info->active=MagickFalse;
widget_info->center=MagickTrue;
widget_info->trough=MagickFalse;
widget_info->highlight=MagickFalse;
widget_info->text=(char *) text;
widget_info->cursor=(char *) text;
if (text != (char *) NULL)
widget_info->cursor+=Extent(text);
widget_info->marker=(char *) text;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X H i g h l i g h t W i d g e t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XHighlightWidget() draws a highlighted border around a window.
%
% The format of the XHighlightWidget function is:
%
% XHighlightWidget(display,window_info,x,y)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o x: Specifies an integer representing the rectangle offset in the
% x-direction.
%
% o y: Specifies an integer representing the rectangle offset in the
% y-direction.
%
*/
static void XHighlightWidget(Display *display,const XWindowInfo *window_info,
const int x,const int y)
{
/*
Draw the widget highlighting rectangle.
*/
XSetBevelColor(display,window_info,MagickTrue);
(void) XDrawRectangle(display,window_info->id,window_info->widget_context,x,y,
window_info->width-(x << 1),window_info->height-(y << 1));
(void) XDrawRectangle(display,window_info->id,window_info->widget_context,
x-1,y-1,window_info->width-(x << 1)+1,window_info->height-(y << 1)+1);
XSetBevelColor(display,window_info,MagickFalse);
(void) XDrawRectangle(display,window_info->id,window_info->widget_context,
x-1,y-1,window_info->width-(x << 1),window_info->height-(y << 1));
(void) XSetFillStyle(display,window_info->widget_context,FillSolid);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X S c r e e n E v e n t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XScreenEvent() returns MagickTrue if the any event on the X server queue is
% associated with the widget window.
%
% The format of the XScreenEvent function is:
%
% int XScreenEvent(Display *display,XEvent *event,char *data)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o event: Specifies a pointer to a X11 XEvent structure.
%
% o data: Specifies a pointer to a XWindows structure.
%
*/
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
static int XScreenEvent(Display *display,XEvent *event,char *data)
{
XWindows
*windows;
windows=(XWindows *) data;
if (event->xany.window == windows->popup.id)
{
if (event->type == MapNotify)
windows->popup.mapped=MagickTrue;
if (event->type == UnmapNotify)
windows->popup.mapped=MagickFalse;
return(MagickTrue);
}
if (event->xany.window == windows->widget.id)
{
if (event->type == MapNotify)
windows->widget.mapped=MagickTrue;
if (event->type == UnmapNotify)
windows->widget.mapped=MagickFalse;
return(MagickTrue);
}
switch (event->type)
{
case ButtonPress:
{
if ((event->xbutton.button == Button3) &&
(event->xbutton.state & Mod1Mask))
{
/*
Convert Alt-Button3 to Button2.
*/
event->xbutton.button=Button2;
event->xbutton.state&=(~Mod1Mask);
}
return(MagickTrue);
}
case Expose:
{
if (event->xexpose.window == windows->image.id)
{
XRefreshWindow(display,&windows->image,event);
break;
}
if (event->xexpose.window == windows->magnify.id)
if (event->xexpose.count == 0)
if (windows->magnify.mapped)
{
ExceptionInfo
*exception;
exception=AcquireExceptionInfo();
XMakeMagnifyImage(display,windows,exception);
exception=DestroyExceptionInfo(exception);
break;
}
if (event->xexpose.window == windows->command.id)
if (event->xexpose.count == 0)
{
(void) XCommandWidget(display,windows,(const char **) NULL,event);
break;
}
break;
}
case FocusOut:
{
/*
Set input focus for backdrop window.
*/
if (event->xfocus.window == windows->image.id)
(void) XSetInputFocus(display,windows->image.id,RevertToNone,
CurrentTime);
return(MagickTrue);
}
case ButtonRelease:
case KeyPress:
case KeyRelease:
case MotionNotify:
case SelectionNotify:
return(MagickTrue);
default:
break;
}
return(MagickFalse);
}
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X S e t B e v e l C o l o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XSetBevelColor() sets the graphic context for drawing a beveled border.
%
% The format of the XSetBevelColor function is:
%
% XSetBevelColor(display,window_info,raised)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o raised: A value other than zero indicates the color show be a
% "highlight" color, otherwise the "shadow" color is set.
%
*/
static void XSetBevelColor(Display *display,const XWindowInfo *window_info,
const MagickStatusType raised)
{
if (window_info->depth == 1)
{
Pixmap
stipple;
/*
Monochrome window.
*/
(void) XSetBackground(display,window_info->widget_context,
XBlackPixel(display,window_info->screen));
(void) XSetForeground(display,window_info->widget_context,
XWhitePixel(display,window_info->screen));
(void) XSetFillStyle(display,window_info->widget_context,
FillOpaqueStippled);
stipple=window_info->highlight_stipple;
if (raised == MagickFalse)
stipple=window_info->shadow_stipple;
(void) XSetStipple(display,window_info->widget_context,stipple);
}
else
if (raised)
(void) XSetForeground(display,window_info->widget_context,
window_info->pixel_info->highlight_color.pixel);
else
(void) XSetForeground(display,window_info->widget_context,
window_info->pixel_info->shadow_color.pixel);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X S e t M a t t e C o l o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XSetMatteColor() sets the graphic context for drawing the matte.
%
% The format of the XSetMatteColor function is:
%
% XSetMatteColor(display,window_info,raised)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o raised: A value other than zero indicates the matte is active.
%
*/
static void XSetMatteColor(Display *display,const XWindowInfo *window_info,
const MagickStatusType raised)
{
if (window_info->depth == 1)
{
/*
Monochrome window.
*/
if (raised)
(void) XSetForeground(display,window_info->widget_context,
XWhitePixel(display,window_info->screen));
else
(void) XSetForeground(display,window_info->widget_context,
XBlackPixel(display,window_info->screen));
}
else
if (raised)
(void) XSetForeground(display,window_info->widget_context,
window_info->pixel_info->matte_color.pixel);
else
(void) XSetForeground(display,window_info->widget_context,
window_info->pixel_info->depth_color.pixel);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X S e t T e x t C o l o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XSetTextColor() sets the graphic context for drawing text on a matte.
%
% The format of the XSetTextColor function is:
%
% XSetTextColor(display,window_info,raised)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
% o raised: A value other than zero indicates the color show be a
% "highlight" color, otherwise the "shadow" color is set.
%
*/
static void XSetTextColor(Display *display,const XWindowInfo *window_info,
const MagickStatusType raised)
{
ssize_t
foreground,
matte;
if (window_info->depth == 1)
{
/*
Monochrome window.
*/
if (raised)
(void) XSetForeground(display,window_info->widget_context,
XBlackPixel(display,window_info->screen));
else
(void) XSetForeground(display,window_info->widget_context,
XWhitePixel(display,window_info->screen));
return;
}
foreground=(ssize_t) XPixelIntensity(
&window_info->pixel_info->foreground_color);
matte=(ssize_t) XPixelIntensity(&window_info->pixel_info->matte_color);
if (MagickAbsoluteValue((int) (foreground-matte)) > (65535L >> 3))
(void) XSetForeground(display,window_info->widget_context,
window_info->pixel_info->foreground_color.pixel);
else
(void) XSetForeground(display,window_info->widget_context,
window_info->pixel_info->background_color.pixel);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X C o l o r B r o w s e r W i d g e t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XColorBrowserWidget() displays a Color Browser widget with a color query
% to the user. The user keys a reply and presses the Action or Cancel button
% to exit. The typed text is returned as the reply function parameter.
%
% The format of the XColorBrowserWidget method is:
%
% void XColorBrowserWidget(Display *display,XWindows *windows,
% const char *action,char *reply)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o window: Specifies a pointer to a XWindows structure.
%
% o action: Specifies a pointer to the action of this widget.
%
% o reply: the response from the user is returned in this parameter.
%
*/
MagickPrivate void XColorBrowserWidget(Display *display,XWindows *windows,
const char *action,char *reply)
{
#define CancelButtonText "Cancel"
#define ColornameText "Name:"
#define ColorPatternText "Pattern:"
#define GrabButtonText "Grab"
#define ResetButtonText "Reset"
char
**colorlist,
primary_selection[MagickPathExtent],
reset_pattern[MagickPathExtent],
text[MagickPathExtent];
ExceptionInfo
*exception;
int
x,
y;
register int
i;
static char
glob_pattern[MagickPathExtent] = "*";
static MagickStatusType
mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY);
Status
status;
unsigned int
height,
text_width,
visible_colors,
width;
size_t
colors,
delay,
state;
XColor
color;
XEvent
event;
XFontStruct
*font_info;
XTextProperty
window_name;
XWidgetInfo
action_info,
cancel_info,
expose_info,
grab_info,
list_info,
mode_info,
north_info,
reply_info,
reset_info,
scroll_info,
selection_info,
slider_info,
south_info,
text_info;
XWindowChanges
window_changes;
/*
Get color list and sort in ascending order.
*/
assert(display != (Display *) NULL);
assert(windows != (XWindows *) NULL);
assert(action != (char *) NULL);
assert(reply != (char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action);
XSetCursorState(display,windows,MagickTrue);
XCheckRefreshWindows(display,windows);
(void) CopyMagickString(reset_pattern,"*",MagickPathExtent);
exception=AcquireExceptionInfo();
colorlist=GetColorList(glob_pattern,&colors,exception);
if (colorlist == (char **) NULL)
{
/*
Pattern failed, obtain all the colors.
*/
(void) CopyMagickString(glob_pattern,"*",MagickPathExtent);
colorlist=GetColorList(glob_pattern,&colors,exception);
if (colorlist == (char **) NULL)
{
XNoticeWidget(display,windows,"Unable to obtain colors names:",
glob_pattern);
(void) XDialogWidget(display,windows,action,"Enter color name:",
reply);
return;
}
}
/*
Determine Color Browser widget attributes.
*/
font_info=windows->widget.font_info;
text_width=0;
for (i=0; i < (int) colors; i++)
if (WidgetTextWidth(font_info,colorlist[i]) > text_width)
text_width=WidgetTextWidth(font_info,colorlist[i]);
width=WidgetTextWidth(font_info,(char *) action);
if (WidgetTextWidth(font_info,CancelButtonText) > width)
width=WidgetTextWidth(font_info,CancelButtonText);
if (WidgetTextWidth(font_info,ResetButtonText) > width)
width=WidgetTextWidth(font_info,ResetButtonText);
if (WidgetTextWidth(font_info,GrabButtonText) > width)
width=WidgetTextWidth(font_info,GrabButtonText);
width+=QuantumMargin;
if (WidgetTextWidth(font_info,ColorPatternText) > width)
width=WidgetTextWidth(font_info,ColorPatternText);
if (WidgetTextWidth(font_info,ColornameText) > width)
width=WidgetTextWidth(font_info,ColornameText);
height=(unsigned int) (font_info->ascent+font_info->descent);
/*
Position Color Browser widget.
*/
windows->widget.width=(unsigned int)
(width+MagickMin((int) text_width,(int) MaxTextWidth)+6*QuantumMargin);
windows->widget.min_width=(unsigned int)
(width+MinTextWidth+4*QuantumMargin);
if (windows->widget.width < windows->widget.min_width)
windows->widget.width=windows->widget.min_width;
windows->widget.height=(unsigned int)
((81*height) >> 2)+((13*QuantumMargin) >> 1)+4;
windows->widget.min_height=(unsigned int)
(((23*height) >> 1)+((13*QuantumMargin) >> 1)+4);
if (windows->widget.height < windows->widget.min_height)
windows->widget.height=windows->widget.min_height;
XConstrainWindowPosition(display,&windows->widget);
/*
Map Color Browser widget.
*/
(void) CopyMagickString(windows->widget.name,"Browse and Select a Color",
MagickPathExtent);
status=XStringListToTextProperty(&windows->widget.name,1,&window_name);
if (status != False)
{
XSetWMName(display,windows->widget.id,&window_name);
XSetWMIconName(display,windows->widget.id,&window_name);
(void) XFree((void *) window_name.value);
}
window_changes.width=(int) windows->widget.width;
window_changes.height=(int) windows->widget.height;
window_changes.x=windows->widget.x;
window_changes.y=windows->widget.y;
(void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen,
mask,&window_changes);
(void) XMapRaised(display,windows->widget.id);
windows->widget.mapped=MagickFalse;
/*
Respond to X events.
*/
XGetWidgetInfo((char *) NULL,&mode_info);
XGetWidgetInfo((char *) NULL,&slider_info);
XGetWidgetInfo((char *) NULL,&north_info);
XGetWidgetInfo((char *) NULL,&south_info);
XGetWidgetInfo((char *) NULL,&expose_info);
XGetWidgetInfo((char *) NULL,&selection_info);
visible_colors=0;
delay=SuspendTime << 2;
state=UpdateConfigurationState;
do
{
if (state & UpdateConfigurationState)
{
int
id;
/*
Initialize button information.
*/
XGetWidgetInfo(CancelButtonText,&cancel_info);
cancel_info.width=width;
cancel_info.height=(unsigned int) ((3*height) >> 1);
cancel_info.x=(int)
(windows->widget.width-cancel_info.width-QuantumMargin-2);
cancel_info.y=(int)
(windows->widget.height-cancel_info.height-QuantumMargin);
XGetWidgetInfo(action,&action_info);
action_info.width=width;
action_info.height=(unsigned int) ((3*height) >> 1);
action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+
(action_info.bevel_width << 1));
action_info.y=cancel_info.y;
XGetWidgetInfo(GrabButtonText,&grab_info);
grab_info.width=width;
grab_info.height=(unsigned int) ((3*height) >> 1);
grab_info.x=QuantumMargin;
grab_info.y=((5*QuantumMargin) >> 1)+height;
XGetWidgetInfo(ResetButtonText,&reset_info);
reset_info.width=width;
reset_info.height=(unsigned int) ((3*height) >> 1);
reset_info.x=QuantumMargin;
reset_info.y=grab_info.y+grab_info.height+QuantumMargin;
/*
Initialize reply information.
*/
XGetWidgetInfo(reply,&reply_info);
reply_info.raised=MagickFalse;
reply_info.bevel_width--;
reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1);
reply_info.height=height << 1;
reply_info.x=(int) (width+(QuantumMargin << 1));
reply_info.y=action_info.y-reply_info.height-QuantumMargin;
/*
Initialize mode information.
*/
XGetWidgetInfo((char *) NULL,&mode_info);
mode_info.active=MagickTrue;
mode_info.bevel_width=0;
mode_info.width=(unsigned int) (action_info.x-(QuantumMargin << 1));
mode_info.height=action_info.height;
mode_info.x=QuantumMargin;
mode_info.y=action_info.y;
/*
Initialize scroll information.
*/
XGetWidgetInfo((char *) NULL,&scroll_info);
scroll_info.bevel_width--;
scroll_info.width=height;
scroll_info.height=(unsigned int) (reply_info.y-grab_info.y-
(QuantumMargin >> 1));
scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width);
scroll_info.y=grab_info.y-reply_info.bevel_width;
scroll_info.raised=MagickFalse;
scroll_info.trough=MagickTrue;
north_info=scroll_info;
north_info.raised=MagickTrue;
north_info.width-=(north_info.bevel_width << 1);
north_info.height=north_info.width-1;
north_info.x+=north_info.bevel_width;
north_info.y+=north_info.bevel_width;
south_info=north_info;
south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width-
south_info.height;
id=slider_info.id;
slider_info=north_info;
slider_info.id=id;
slider_info.width-=2;
slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+
slider_info.bevel_width+2;
slider_info.height=scroll_info.height-((slider_info.min_y-
scroll_info.y+1) << 1)+4;
visible_colors=scroll_info.height/(height+(height >> 3));
if (colors > visible_colors)
slider_info.height=(unsigned int)
((visible_colors*slider_info.height)/colors);
slider_info.max_y=south_info.y-south_info.bevel_width-
slider_info.bevel_width-2;
slider_info.x=scroll_info.x+slider_info.bevel_width+1;
slider_info.y=slider_info.min_y;
expose_info=scroll_info;
expose_info.y=slider_info.y;
/*
Initialize list information.
*/
XGetWidgetInfo((char *) NULL,&list_info);
list_info.raised=MagickFalse;
list_info.bevel_width--;
list_info.width=(unsigned int)
(scroll_info.x-reply_info.x-(QuantumMargin >> 1));
list_info.height=scroll_info.height;
list_info.x=reply_info.x;
list_info.y=scroll_info.y;
if (windows->widget.mapped == MagickFalse)
state|=JumpListState;
/*
Initialize text information.
*/
*text='\0';
XGetWidgetInfo(text,&text_info);
text_info.center=MagickFalse;
text_info.width=reply_info.width;
text_info.height=height;
text_info.x=list_info.x-(QuantumMargin >> 1);
text_info.y=QuantumMargin;
/*
Initialize selection information.
*/
XGetWidgetInfo((char *) NULL,&selection_info);
selection_info.center=MagickFalse;
selection_info.width=list_info.width;
selection_info.height=(unsigned int) ((9*height) >> 3);
selection_info.x=list_info.x;
state&=(~UpdateConfigurationState);
}
if (state & RedrawWidgetState)
{
/*
Redraw Color Browser window.
*/
x=QuantumMargin;
y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent;
(void) XDrawString(display,windows->widget.id,
windows->widget.annotate_context,x,y,ColorPatternText,
Extent(ColorPatternText));
(void) CopyMagickString(text_info.text,glob_pattern,MagickPathExtent);
XDrawWidgetText(display,&windows->widget,&text_info);
XDrawBeveledButton(display,&windows->widget,&grab_info);
XDrawBeveledButton(display,&windows->widget,&reset_info);
XDrawBeveledMatte(display,&windows->widget,&list_info);
XDrawBeveledMatte(display,&windows->widget,&scroll_info);
XDrawTriangleNorth(display,&windows->widget,&north_info);
XDrawBeveledButton(display,&windows->widget,&slider_info);
XDrawTriangleSouth(display,&windows->widget,&south_info);
x=QuantumMargin;
y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent;
(void) XDrawString(display,windows->widget.id,
windows->widget.annotate_context,x,y,ColornameText,
Extent(ColornameText));
XDrawBeveledMatte(display,&windows->widget,&reply_info);
XDrawMatteText(display,&windows->widget,&reply_info);
XDrawBeveledButton(display,&windows->widget,&action_info);
XDrawBeveledButton(display,&windows->widget,&cancel_info);
XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
selection_info.id=(~0);
state|=RedrawActionState;
state|=RedrawListState;
state&=(~RedrawWidgetState);
}
if (state & UpdateListState)
{
char
**checklist;
size_t
number_colors;
status=XParseColor(display,windows->widget.map_info->colormap,
glob_pattern,&color);
if ((status != False) || (strchr(glob_pattern,'-') != (char *) NULL))
{
/*
Reply is a single color name-- exit.
*/
(void) CopyMagickString(reply,glob_pattern,MagickPathExtent);
(void) CopyMagickString(glob_pattern,reset_pattern,MagickPathExtent);
action_info.raised=MagickFalse;
XDrawBeveledButton(display,&windows->widget,&action_info);
break;
}
/*
Update color list.
*/
checklist=GetColorList(glob_pattern,&number_colors,exception);
if (number_colors == 0)
{
(void) CopyMagickString(glob_pattern,reset_pattern,MagickPathExtent);
(void) XBell(display,0);
}
else
{
for (i=0; i < (int) colors; i++)
colorlist[i]=DestroyString(colorlist[i]);
if (colorlist != (char **) NULL)
colorlist=(char **) RelinquishMagickMemory(colorlist);
colorlist=checklist;
colors=number_colors;
}
/*
Sort color list in ascending order.
*/
slider_info.height=
scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1;
if (colors > visible_colors)
slider_info.height=(unsigned int)
((visible_colors*slider_info.height)/colors);
slider_info.max_y=south_info.y-south_info.bevel_width-
slider_info.bevel_width-2;
slider_info.id=0;
slider_info.y=slider_info.min_y;
expose_info.y=slider_info.y;
selection_info.id=(~0);
list_info.id=(~0);
state|=RedrawListState;
/*
Redraw color name & reply.
*/
*reply_info.text='\0';
reply_info.cursor=reply_info.text;
(void) CopyMagickString(text_info.text,glob_pattern,MagickPathExtent);
XDrawWidgetText(display,&windows->widget,&text_info);
XDrawMatteText(display,&windows->widget,&reply_info);
XDrawBeveledMatte(display,&windows->widget,&scroll_info);
XDrawTriangleNorth(display,&windows->widget,&north_info);
XDrawBeveledButton(display,&windows->widget,&slider_info);
XDrawTriangleSouth(display,&windows->widget,&south_info);
XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset);
state&=(~UpdateListState);
}
if (state & JumpListState)
{
/*
Jump scroll to match user color.
*/
list_info.id=(~0);
for (i=0; i < (int) colors; i++)
if (LocaleCompare(colorlist[i],reply) >= 0)
{
list_info.id=LocaleCompare(colorlist[i],reply) == 0 ? i : ~0;
break;
}
if ((i < slider_info.id) ||
(i >= (int) (slider_info.id+visible_colors)))
slider_info.id=i-(visible_colors >> 1);
selection_info.id=(~0);
state|=RedrawListState;
state&=(~JumpListState);
}
if (state & RedrawListState)
{
/*
Determine slider id and position.
*/
if (slider_info.id >= (int) (colors-visible_colors))
slider_info.id=(int) (colors-visible_colors);
if ((slider_info.id < 0) || (colors <= visible_colors))
slider_info.id=0;
slider_info.y=slider_info.min_y;
if (colors != 0)
slider_info.y+=(int) (slider_info.id*(slider_info.max_y-
slider_info.min_y+1)/colors);
if (slider_info.id != selection_info.id)
{
/*
Redraw scroll bar and file names.
*/
selection_info.id=slider_info.id;
selection_info.y=list_info.y+(height >> 3)+2;
for (i=0; i < (int) visible_colors; i++)
{
selection_info.raised=(slider_info.id+i) != list_info.id ?
MagickTrue : MagickFalse;
selection_info.text=(char *) NULL;
if ((slider_info.id+i) < (int) colors)
selection_info.text=colorlist[slider_info.id+i];
XDrawWidgetText(display,&windows->widget,&selection_info);
selection_info.y+=(int) selection_info.height;
}
/*
Update slider.
*/
if (slider_info.y > expose_info.y)
{
expose_info.height=(unsigned int) slider_info.y-expose_info.y;
expose_info.y=slider_info.y-expose_info.height-
slider_info.bevel_width-1;
}
else
{
expose_info.height=(unsigned int) expose_info.y-slider_info.y;
expose_info.y=slider_info.y+slider_info.height+
slider_info.bevel_width+1;
}
XDrawTriangleNorth(display,&windows->widget,&north_info);
XDrawMatte(display,&windows->widget,&expose_info);
XDrawBeveledButton(display,&windows->widget,&slider_info);
XDrawTriangleSouth(display,&windows->widget,&south_info);
expose_info.y=slider_info.y;
}
state&=(~RedrawListState);
}
if (state & RedrawActionState)
{
static char
colorname[MagickPathExtent];
/*
Display the selected color in a drawing area.
*/
color=windows->widget.pixel_info->matte_color;
(void) XParseColor(display,windows->widget.map_info->colormap,
reply_info.text,&windows->widget.pixel_info->matte_color);
XBestPixel(display,windows->widget.map_info->colormap,(XColor *) NULL,
(unsigned int) windows->widget.visual_info->colormap_size,
&windows->widget.pixel_info->matte_color);
mode_info.text=colorname;
(void) FormatLocaleString(mode_info.text,MagickPathExtent,
"#%02x%02x%02x",windows->widget.pixel_info->matte_color.red,
windows->widget.pixel_info->matte_color.green,
windows->widget.pixel_info->matte_color.blue);
XDrawBeveledButton(display,&windows->widget,&mode_info);
windows->widget.pixel_info->matte_color=color;
state&=(~RedrawActionState);
}
/*
Wait for next event.
*/
if (north_info.raised && south_info.raised)
(void) XIfEvent(display,&event,XScreenEvent,(char *) windows);
else
{
/*
Brief delay before advancing scroll bar.
*/
XDelay(display,delay);
delay=SuspendTime;
(void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows);
if (north_info.raised == MagickFalse)
if (slider_info.id > 0)
{
/*
Move slider up.
*/
slider_info.id--;
state|=RedrawListState;
}
if (south_info.raised == MagickFalse)
if (slider_info.id < (int) colors)
{
/*
Move slider down.
*/
slider_info.id++;
state|=RedrawListState;
}
if (event.type != ButtonRelease)
continue;
}
switch (event.type)
{
case ButtonPress:
{
if (MatteIsActive(slider_info,event.xbutton))
{
/*
Track slider.
*/
slider_info.active=MagickTrue;
break;
}
if (MatteIsActive(north_info,event.xbutton))
if (slider_info.id > 0)
{
/*
Move slider up.
*/
north_info.raised=MagickFalse;
slider_info.id--;
state|=RedrawListState;
break;
}
if (MatteIsActive(south_info,event.xbutton))
if (slider_info.id < (int) colors)
{
/*
Move slider down.
*/
south_info.raised=MagickFalse;
slider_info.id++;
state|=RedrawListState;
break;
}
if (MatteIsActive(scroll_info,event.xbutton))
{
/*
Move slider.
*/
if (event.xbutton.y < slider_info.y)
slider_info.id-=(visible_colors-1);
else
slider_info.id+=(visible_colors-1);
state|=RedrawListState;
break;
}
if (MatteIsActive(list_info,event.xbutton))
{
int
id;
/*
User pressed list matte.
*/
id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/
selection_info.height;
if (id >= (int) colors)
break;
(void) CopyMagickString(reply_info.text,colorlist[id],
MagickPathExtent);
reply_info.highlight=MagickFalse;
reply_info.marker=reply_info.text;
reply_info.cursor=reply_info.text+Extent(reply_info.text);
XDrawMatteText(display,&windows->widget,&reply_info);
state|=RedrawActionState;
if (id == list_info.id)
{
(void) CopyMagickString(glob_pattern,reply_info.text,
MagickPathExtent);
state|=UpdateListState;
}
selection_info.id=(~0);
list_info.id=id;
state|=RedrawListState;
break;
}
if (MatteIsActive(grab_info,event.xbutton))
{
/*
User pressed Grab button.
*/
grab_info.raised=MagickFalse;
XDrawBeveledButton(display,&windows->widget,&grab_info);
break;
}
if (MatteIsActive(reset_info,event.xbutton))
{
/*
User pressed Reset button.
*/
reset_info.raised=MagickFalse;
XDrawBeveledButton(display,&windows->widget,&reset_info);
break;
}
if (MatteIsActive(mode_info,event.xbutton))
{
/*
User pressed mode button.
*/
if (mode_info.text != (char *) NULL)
(void) CopyMagickString(reply_info.text,mode_info.text,
MagickPathExtent);
(void) CopyMagickString(primary_selection,reply_info.text,
MagickPathExtent);
(void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
event.xbutton.time);
reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
windows->widget.id ? MagickTrue : MagickFalse;
reply_info.marker=reply_info.text;
reply_info.cursor=reply_info.text+Extent(reply_info.text);
XDrawMatteText(display,&windows->widget,&reply_info);
break;
}
if (MatteIsActive(action_info,event.xbutton))
{
/*
User pressed action button.
*/
action_info.raised=MagickFalse;
XDrawBeveledButton(display,&windows->widget,&action_info);
break;
}
if (MatteIsActive(cancel_info,event.xbutton))
{
/*
User pressed Cancel button.
*/
cancel_info.raised=MagickFalse;
XDrawBeveledButton(display,&windows->widget,&cancel_info);
break;
}
if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
break;
if (event.xbutton.button != Button2)
{
static Time
click_time;
/*
Move text cursor to position of button press.
*/
x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2);
for (i=1; i <= Extent(reply_info.marker); i++)
if (XTextWidth(font_info,reply_info.marker,i) > x)
break;
reply_info.cursor=reply_info.marker+i-1;
if (event.xbutton.time > (click_time+DoubleClick))
reply_info.highlight=MagickFalse;
else
{
/*
Become the XA_PRIMARY selection owner.
*/
(void) CopyMagickString(primary_selection,reply_info.text,
MagickPathExtent);
(void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id,
event.xbutton.time);
reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) ==
windows->widget.id ? MagickTrue : MagickFalse;
}
XDrawMatteText(display,&windows->widget,&reply_info);
click_time=event.xbutton.time;
break;
}
/*
Request primary selection.
*/
(void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
windows->widget.id,event.xbutton.time);
break;
}
case ButtonRelease:
{
if (windows->widget.mapped == MagickFalse)
break;
if (north_info.raised == MagickFalse)
{
/*
User released up button.
*/
delay=SuspendTime << 2;
north_info.raised=MagickTrue;
XDrawTriangleNorth(display,&windows->widget,&north_info);
}
if (south_info.raised == MagickFalse)
{
/*
User released down button.
*/
delay=SuspendTime << 2;
south_info.raised=MagickTrue;
XDrawTriangleSouth(display,&windows->widget,&south_info);
}
if (slider_info.active)
{
/*
Stop tracking slider.
*/
slider_info.active=MagickFalse;
break;
}
if (grab_info.raised == MagickFalse)
{
if (event.xbutton.window == windows->widget.id)
if (MatteIsActive(grab_info,event.xbutton))
{
/*
Select a fill color from the X server.
*/
(void) XGetWindowColor(display,windows,reply_info.text,
exception);
reply_info.marker=reply_info.text;
reply_info.cursor=reply_info.text+Extent(reply_info.text);
XDrawMatteText(display,&windows->widget,&reply_info);
state|=RedrawActionState;
}
grab_info.raised=MagickTrue;
XDrawBeveledButton(display,&windows->widget,&grab_info);
}
if (reset_info.raised == MagickFalse)
{
if (event.xbutton.window == windows->widget.id)
if (MatteIsActive(reset_info,event.xbutton))
{
(void) CopyMagickString(glob_pattern,reset_pattern,
MagickPathExtent);
state|=UpdateListState;
}
reset_info.raised=MagickTrue;
XDrawBeveledButton(display,&windows->widget,&reset_info);
}
if (action_info.raised == MagickFalse)
{
if (event.xbutton.window == windows->widget.id)
{
if (MatteIsActive(action_info,event.xbutton))
{
if (*reply_info.text == '\0')
(void) XBell(display,0);
else
state|=ExitState;
}
}
action_info.raised=MagickTrue;
XDrawBeveledButton(display,&windows->widget,&action_info);
}
if (cancel_info.raised == MagickFalse)
{
if (event.xbutton.window == windows->widget.id)
if (MatteIsActive(cancel_info,event.xbutton))
{
*reply_info.text='\0';
state|=ExitState;
}
cancel_info.raised=MagickTrue;
XDrawBeveledButton(display,&windows->widget,&cancel_info);
}
if (MatteIsActive(reply_info,event.xbutton) == MagickFalse)
break;
break;
}
case ClientMessage:
{
/*
If client window delete message, exit.
*/
if (event.xclient.message_type != windows->wm_protocols)
break;
if (*event.xclient.data.l == (int) windows->wm_take_focus)
{
(void) XSetInputFocus(display,event.xclient.window,RevertToParent,
(Time) event.xclient.data.l[1]);
break;
}
if (*event.xclient.data.l != (int) windows->wm_delete_window)
break;
if (event.xclient.window == windows->widget.id)
{
*reply_info.text='\0';
state|=ExitState;
break;
}
break;
}
case ConfigureNotify:
{
/*
Update widget configuration.
*/
if (event.xconfigure.window != windows->widget.id)
break;
if ((event.xconfigure.width == (int) windows->widget.width) &&
(event.xconfigure.height == (int) windows->widget.height))
break;
windows->widget.width=(unsigned int)
MagickMax(event.xconfigure.width,(int) windows->widget.min_width);
windows->widget.height=(unsigned int)
MagickMax(event.xconfigure.height,(int) windows->widget.min_height);
state|=UpdateConfigurationState;
break;
}
case EnterNotify:
{
if (event.xcrossing.window != windows->widget.id)
break;
state&=(~InactiveWidgetState);
break;
}
case Expose:
{
if (event.xexpose.window != windows->widget.id)
break;
if (event.xexpose.count != 0)
break;
state|=RedrawWidgetState;
break;
}
case KeyPress:
{
static char
command[MagickPathExtent];
static int
length;
static KeySym
key_symbol;
/*
Respond to a user key press.
*/
if (event.xkey.window != windows->widget.id)
break;
length=XLookupString((XKeyEvent *) &event.xkey,command,
(int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
*(command+length)='\0';
if (AreaIsActive(scroll_info,event.xkey))
{
/*
Move slider.
*/
switch ((int) key_symbol)
{
case XK_Home:
case XK_KP_Home:
{
slider_info.id=0;
break;
}
case XK_Up:
case XK_KP_Up:
{
slider_info.id--;
break;
}
case XK_Down:
case XK_KP_Down:
{
slider_info.id++;
break;
}
case XK_Prior:
case XK_KP_Prior:
{
slider_info.id-=visible_colors;
break;
}
case XK_Next:
case XK_KP_Next:
{
slider_info.id+=visible_colors;
break;
}
case XK_End:
case XK_KP_End:
{
slider_info.id=(int) colors;
break;
}
}
state|=RedrawListState;
break;
}
if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter))
{
/*
Read new color or glob patterm.
*/
if (*reply_info.text == '\0')
break;
(void) CopyMagickString(glob_pattern,reply_info.text,MagickPathExtent);
state|=UpdateListState;
break;
}
if (key_symbol == XK_Control_L)
{
state|=ControlState;
break;
}
if (state & ControlState)
switch ((int) key_symbol)
{
case XK_u:
case XK_U:
{
/*
Erase the entire line of text.
*/
*reply_info.text='\0';
reply_info.cursor=reply_info.text;
reply_info.marker=reply_info.text;
reply_info.highlight=MagickFalse;
break;
}
default:
break;
}
XEditText(display,&reply_info,key_symbol,command,state);
XDrawMatteText(display,&windows->widget,&reply_info);
state|=JumpListState;
status=XParseColor(display,windows->widget.map_info->colormap,
reply_info.text,&color);
if (status != False)
state|=RedrawActionState;
break;
}
case KeyRelease:
{
static char
command[MagickPathExtent];
static KeySym
key_symbol;
/*
Respond to a user key release.
*/
if (event.xkey.window != windows->widget.id)
break;
(void) XLookupString((XKeyEvent *) &event.xkey,command,
(int) sizeof(command),&key_symbol,(XComposeStatus *) NULL);
if (key_symbol == XK_Control_L)
state&=(~ControlState);
break;
}
case LeaveNotify:
{
if (event.xcrossing.window != windows->widget.id)
break;
state|=InactiveWidgetState;
break;
}
case MapNotify:
{
mask&=(~CWX);
mask&=(~CWY);
break;
}
case MotionNotify:
{
/*
Discard pending button motion events.
*/
while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
if (slider_info.active)
{
/*
Move slider matte.
*/
slider_info.y=event.xmotion.y-
((slider_info.height+slider_info.bevel_width) >> 1)+1;
if (slider_info.y < slider_info.min_y)
slider_info.y=slider_info.min_y;
if (slider_info.y > slider_info.max_y)
slider_info.y=slider_info.max_y;
slider_info.id=0;
if (slider_info.y != slider_info.min_y)
slider_info.id=(int) ((colors*(slider_info.y-
slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1));
state|=RedrawListState;
break;
}
if (state & InactiveWidgetState)
break;
if (grab_info.raised == MatteIsActive(grab_info,event.xmotion))
{
/*
Grab button status changed.
*/
grab_info.raised=!grab_info.raised;
XDrawBeveledButton(display,&windows->widget,&grab_info);
break;
}
if (reset_info.raised == MatteIsActive(reset_info,event.xmotion))
{
/*
Reset button status changed.
*/
reset_info.raised=!reset_info.raised;
XDrawBeveledButton(display,&windows->widget,&reset_info);
break;
}
if (action_info.raised == MatteIsActive(action_info,event.xmotion))
{
/*
Action button status changed.
*/
action_info.raised=action_info.raised == MagickFalse ?
MagickTrue : MagickFalse;
XDrawBeveledButton(display,&windows->widget,&action_info);
break;
}
if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion))
{
/*
Cancel button status changed.
*/
cancel_info.raised=cancel_info.raised == MagickFalse ?
MagickTrue : MagickFalse;
XDrawBeveledButton(display,&windows->widget,&cancel_info);
break;
}
break;
}
case SelectionClear:
{
reply_info.highlight=MagickFalse;
XDrawMatteText(display,&windows->widget,&reply_info);
break;