| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % % |
| % 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-2020 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/timer-private.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, |
| strlen(text_info->cursor+1)+1); |
| 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 *const *) 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; |
| XDrawMatteTe
|