|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % % 00007 % W W IIIII DDDD GGGG EEEEE TTTTT % 00008 % W W I D D G E T % 00009 % W W W I D D G GG EEE T % 00010 % WW WW I D D G G E T % 00011 % W W IIIII DDDD GGGG EEEEE T % 00012 % % 00013 % % 00014 % MagickCore X11 User Interface Methods % 00015 % % 00016 % Software Design % 00017 % John Cristy % 00018 % September 1993 % 00019 % % 00020 % % 00021 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00022 % dedicated to making software imaging solutions freely available. % 00023 % % 00024 % You may not use this file except in compliance with the License. You may % 00025 % obtain a copy of the License at % 00026 % % 00027 % http://www.imagemagick.org/script/license.php % 00028 % % 00029 % Unless required by applicable law or agreed to in writing, software % 00030 % distributed under the License is distributed on an "AS IS" BASIS, % 00031 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00032 % See the License for the specific language governing permissions and % 00033 % limitations under the License. % 00034 % % 00035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00036 % 00037 % 00038 */ 00039 00040 /* 00041 Include declarations. 00042 */ 00043 #include "MagickCore/studio.h" 00044 #include "MagickCore/color.h" 00045 #include "MagickCore/color-private.h" 00046 #include "MagickCore/exception.h" 00047 #include "MagickCore/exception-private.h" 00048 #include "MagickCore/image.h" 00049 #include "MagickCore/magick.h" 00050 #include "MagickCore/memory_.h" 00051 #include "MagickCore/PreRvIcccm.h" 00052 #include "MagickCore/string_.h" 00053 #include "MagickCore/token.h" 00054 #include "MagickCore/token-private.h" 00055 #include "MagickCore/utility.h" 00056 #include "MagickCore/utility-private.h" 00057 #include "MagickCore/xwindow-private.h" 00058 #include "MagickCore/widget.h" 00059 #include "MagickCore/widget-private.h" 00060 00061 #if defined(MAGICKCORE_X11_DELEGATE) 00062 00063 /* 00064 Define declarations. 00065 */ 00066 #define AreaIsActive(matte_info,position) ( \ 00067 ((position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \ 00068 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \ 00069 ? MagickTrue : MagickFalse) 00070 #define Extent(s) ((int) strlen(s)) 00071 #define MatteIsActive(matte_info,position) ( \ 00072 ((position.x >= (int) (matte_info.x-matte_info.bevel_width)) && \ 00073 (position.y >= (int) (matte_info.y-matte_info.bevel_width)) && \ 00074 (position.x < (int) (matte_info.x+matte_info.width+matte_info.bevel_width)) && \ 00075 (position.y < (int) (matte_info.y+matte_info.height+matte_info.bevel_width))) \ 00076 ? MagickTrue : MagickFalse) 00077 #define MaxTextWidth ((unsigned int) (255*XTextWidth(font_info,"_",1))) 00078 #define MinTextWidth (26*XTextWidth(font_info,"_",1)) 00079 #define QuantumMargin MagickMax(font_info->max_bounds.width,12) 00080 #define WidgetTextWidth(font_info,text) \ 00081 ((unsigned int) XTextWidth(font_info,text,Extent(text))) 00082 #define WindowIsActive(window_info,position) ( \ 00083 ((position.x >= 0) && (position.y >= 0) && \ 00084 (position.x < (int) window_info.width) && \ 00085 (position.y < (int) window_info.height)) ? MagickTrue : MagickFalse) 00086 00087 /* 00088 Enum declarations. 00089 */ 00090 typedef enum 00091 { 00092 ControlState = 0x0001, 00093 InactiveWidgetState = 0x0004, 00094 JumpListState = 0x0008, 00095 RedrawActionState = 0x0010, 00096 RedrawListState = 0x0020, 00097 RedrawWidgetState = 0x0040, 00098 UpdateListState = 0x0100 00099 } WidgetState; 00100 00101 /* 00102 Typedef declarations. 00103 */ 00104 typedef struct _XWidgetInfo 00105 { 00106 char 00107 *cursor, 00108 *text, 00109 *marker; 00110 00111 int 00112 id; 00113 00114 unsigned int 00115 bevel_width, 00116 width, 00117 height; 00118 00119 int 00120 x, 00121 y, 00122 min_y, 00123 max_y; 00124 00125 MagickStatusType 00126 raised, 00127 active, 00128 center, 00129 trough, 00130 highlight; 00131 } XWidgetInfo; 00132 00133 /* 00134 Variable declarations. 00135 */ 00136 static XWidgetInfo 00137 monitor_info = 00138 { 00139 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0, 00140 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse 00141 }, 00142 submenu_info = 00143 { 00144 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0, 00145 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse 00146 }, 00147 *selection_info = (XWidgetInfo *) NULL, 00148 toggle_info = 00149 { 00150 (char *) NULL, (char *) NULL, (char *) NULL, 0, 0, 0, 0, 0, 0, 0, 0, 00151 MagickFalse, MagickFalse, MagickFalse, MagickFalse, MagickFalse 00152 }; 00153 00154 /* 00155 Constant declarations. 00156 */ 00157 static const int 00158 BorderOffset = 4, 00159 DoubleClick = 250; 00160 00161 /* 00162 Method prototypes. 00163 */ 00164 static void 00165 XDrawMatte(Display *,const XWindowInfo *,const XWidgetInfo *), 00166 XSetBevelColor(Display *,const XWindowInfo *,const MagickStatusType), 00167 XSetMatteColor(Display *,const XWindowInfo *,const MagickStatusType), 00168 XSetTextColor(Display *,const XWindowInfo *,const MagickStatusType); 00169 00170 /* 00171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00172 % % 00173 % % 00174 % % 00175 % D e s t r o y X W i d g e t % 00176 % % 00177 % % 00178 % % 00179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00180 % 00181 % DestroyXWidget() destroys resources associated with the X widget. 00182 % 00183 % The format of the DestroyXWidget method is: 00184 % 00185 % void DestroyXWidget() 00186 % 00187 % A description of each parameter follows: 00188 % 00189 */ 00190 MagickPrivate void DestroyXWidget(void) 00191 { 00192 if (selection_info != (XWidgetInfo *) NULL) 00193 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info); 00194 } 00195 00196 /* 00197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00198 % % 00199 % % 00200 % % 00201 + X D r a w B e v e l % 00202 % % 00203 % % 00204 % % 00205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00206 % 00207 % XDrawBevel() "sets off" an area with a highlighted upper and left bevel and 00208 % a shadowed lower and right bevel. The highlighted and shadowed bevels 00209 % create a 3-D effect. 00210 % 00211 % The format of the XDrawBevel function is: 00212 % 00213 % XDrawBevel(display,window_info,bevel_info) 00214 % 00215 % A description of each parameter follows: 00216 % 00217 % o display: Specifies a pointer to the Display structure; returned from 00218 % XOpenDisplay. 00219 % 00220 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 00221 % 00222 % o bevel_info: Specifies a pointer to a XWidgetInfo structure. It 00223 % contains the extents of the bevel. 00224 % 00225 */ 00226 static void XDrawBevel(Display *display,const XWindowInfo *window_info, 00227 const XWidgetInfo *bevel_info) 00228 { 00229 int 00230 x1, 00231 x2, 00232 y1, 00233 y2; 00234 00235 unsigned int 00236 bevel_width; 00237 00238 XPoint 00239 points[6]; 00240 00241 /* 00242 Draw upper and left beveled border. 00243 */ 00244 x1=bevel_info->x; 00245 y1=bevel_info->y+bevel_info->height; 00246 x2=bevel_info->x+bevel_info->width; 00247 y2=bevel_info->y; 00248 bevel_width=bevel_info->bevel_width; 00249 points[0].x=x1; 00250 points[0].y=y1; 00251 points[1].x=x1; 00252 points[1].y=y2; 00253 points[2].x=x2; 00254 points[2].y=y2; 00255 points[3].x=x2+bevel_width; 00256 points[3].y=y2-bevel_width; 00257 points[4].x=x1-bevel_width; 00258 points[4].y=y2-bevel_width; 00259 points[5].x=x1-bevel_width; 00260 points[5].y=y1+bevel_width; 00261 XSetBevelColor(display,window_info,bevel_info->raised); 00262 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00263 points,6,Complex,CoordModeOrigin); 00264 /* 00265 Draw lower and right beveled border. 00266 */ 00267 points[0].x=x1; 00268 points[0].y=y1; 00269 points[1].x=x2; 00270 points[1].y=y1; 00271 points[2].x=x2; 00272 points[2].y=y2; 00273 points[3].x=x2+bevel_width; 00274 points[3].y=y2-bevel_width; 00275 points[4].x=x2+bevel_width; 00276 points[4].y=y1+bevel_width; 00277 points[5].x=x1-bevel_width; 00278 points[5].y=y1+bevel_width; 00279 XSetBevelColor(display,window_info,!bevel_info->raised); 00280 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00281 points,6,Complex,CoordModeOrigin); 00282 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 00283 } 00284 00285 /* 00286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00287 % % 00288 % % 00289 % % 00290 + X D r a w B e v e l e d B u t t o n % 00291 % % 00292 % % 00293 % % 00294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00295 % 00296 % XDrawBeveledButton() draws a button with a highlighted upper and left bevel 00297 % and a shadowed lower and right bevel. The highlighted and shadowed bevels 00298 % create a 3-D effect. 00299 % 00300 % The format of the XDrawBeveledButton function is: 00301 % 00302 % XDrawBeveledButton(display,window_info,button_info) 00303 % 00304 % A description of each parameter follows: 00305 % 00306 % o display: Specifies a pointer to the Display structure; returned from 00307 % XOpenDisplay. 00308 % 00309 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 00310 % 00311 % o button_info: Specifies a pointer to a XWidgetInfo structure. It 00312 % contains the extents of the button. 00313 % 00314 */ 00315 00316 static inline int MagickAbsoluteValue(const int x) 00317 { 00318 if (x < 0) 00319 return(-x); 00320 return(x); 00321 } 00322 00323 static inline int MagickMax(const int x,const int y) 00324 { 00325 if (x > y) 00326 return(x); 00327 return(y); 00328 } 00329 00330 static inline int MagickMin(const int x,const int y) 00331 { 00332 if (x < y) 00333 return(x); 00334 return(y); 00335 } 00336 00337 static void XDrawBeveledButton(Display *display,const XWindowInfo *window_info, 00338 const XWidgetInfo *button_info) 00339 { 00340 int 00341 x, 00342 y; 00343 00344 unsigned int 00345 width; 00346 00347 XFontStruct 00348 *font_info; 00349 00350 XRectangle 00351 crop_info; 00352 00353 /* 00354 Draw matte. 00355 */ 00356 XDrawBevel(display,window_info,button_info); 00357 XSetMatteColor(display,window_info,button_info->raised); 00358 (void) XFillRectangle(display,window_info->id,window_info->widget_context, 00359 button_info->x,button_info->y,button_info->width,button_info->height); 00360 x=button_info->x-button_info->bevel_width-1; 00361 y=button_info->y-button_info->bevel_width-1; 00362 (void) XSetForeground(display,window_info->widget_context, 00363 window_info->pixel_info->trough_color.pixel); 00364 if (button_info->raised || (window_info->depth == 1)) 00365 (void) XDrawRectangle(display,window_info->id,window_info->widget_context, 00366 x,y,button_info->width+(button_info->bevel_width << 1)+1, 00367 button_info->height+(button_info->bevel_width << 1)+1); 00368 if (button_info->text == (char *) NULL) 00369 return; 00370 /* 00371 Set cropping region. 00372 */ 00373 crop_info.width=(unsigned short) button_info->width; 00374 crop_info.height=(unsigned short) button_info->height; 00375 crop_info.x=button_info->x; 00376 crop_info.y=button_info->y; 00377 /* 00378 Draw text. 00379 */ 00380 font_info=window_info->font_info; 00381 width=WidgetTextWidth(font_info,button_info->text); 00382 x=button_info->x+(QuantumMargin >> 1); 00383 if (button_info->center) 00384 x=button_info->x+(button_info->width >> 1)-(width >> 1); 00385 y=button_info->y+((button_info->height- 00386 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent; 00387 if ((int) button_info->width == (QuantumMargin >> 1)) 00388 { 00389 /* 00390 Option button-- write label to right of button. 00391 */ 00392 XSetTextColor(display,window_info,MagickTrue); 00393 x=button_info->x+button_info->width+button_info->bevel_width+ 00394 (QuantumMargin >> 1); 00395 (void) XDrawString(display,window_info->id,window_info->widget_context, 00396 x,y,button_info->text,Extent(button_info->text)); 00397 return; 00398 } 00399 (void) XSetClipRectangles(display,window_info->widget_context,0,0,&crop_info, 00400 1,Unsorted); 00401 XSetTextColor(display,window_info,button_info->raised); 00402 (void) XDrawString(display,window_info->id,window_info->widget_context,x,y, 00403 button_info->text,Extent(button_info->text)); 00404 (void) XSetClipMask(display,window_info->widget_context,None); 00405 if (button_info->raised == MagickFalse) 00406 XDelay(display,SuspendTime << 2); 00407 } 00408 00409 /* 00410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00411 % % 00412 % % 00413 % % 00414 + X D r a w B e v e l e d M a t t e % 00415 % % 00416 % % 00417 % % 00418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00419 % 00420 % XDrawBeveledMatte() draws a matte with a shadowed upper and left bevel and 00421 % a highlighted lower and right bevel. The highlighted and shadowed bevels 00422 % create a 3-D effect. 00423 % 00424 % The format of the XDrawBeveledMatte function is: 00425 % 00426 % XDrawBeveledMatte(display,window_info,matte_info) 00427 % 00428 % A description of each parameter follows: 00429 % 00430 % o display: Specifies a pointer to the Display structure; returned from 00431 % XOpenDisplay. 00432 % 00433 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 00434 % 00435 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It 00436 % contains the extents of the matte. 00437 % 00438 */ 00439 static void XDrawBeveledMatte(Display *display,const XWindowInfo *window_info, 00440 const XWidgetInfo *matte_info) 00441 { 00442 /* 00443 Draw matte. 00444 */ 00445 XDrawBevel(display,window_info,matte_info); 00446 XDrawMatte(display,window_info,matte_info); 00447 } 00448 00449 /* 00450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00451 % % 00452 % % 00453 % % 00454 + X D r a w M a t t e % 00455 % % 00456 % % 00457 % % 00458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00459 % 00460 % XDrawMatte() fills a rectangular area with the matte color. 00461 % 00462 % The format of the XDrawMatte function is: 00463 % 00464 % XDrawMatte(display,window_info,matte_info) 00465 % 00466 % A description of each parameter follows: 00467 % 00468 % o display: Specifies a pointer to the Display structure; returned from 00469 % XOpenDisplay. 00470 % 00471 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 00472 % 00473 % o matte_info: Specifies a pointer to a XWidgetInfo structure. It 00474 % contains the extents of the matte. 00475 % 00476 */ 00477 static void XDrawMatte(Display *display,const XWindowInfo *window_info, 00478 const XWidgetInfo *matte_info) 00479 { 00480 /* 00481 Draw matte. 00482 */ 00483 if ((matte_info->trough == MagickFalse) || (window_info->depth == 1)) 00484 (void) XFillRectangle(display,window_info->id, 00485 window_info->highlight_context,matte_info->x,matte_info->y, 00486 matte_info->width,matte_info->height); 00487 else 00488 { 00489 (void) XSetForeground(display,window_info->widget_context, 00490 window_info->pixel_info->trough_color.pixel); 00491 (void) XFillRectangle(display,window_info->id,window_info->widget_context, 00492 matte_info->x,matte_info->y,matte_info->width,matte_info->height); 00493 } 00494 } 00495 00496 /* 00497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00498 % % 00499 % % 00500 % % 00501 + X D r a w M a t t e T e x t % 00502 % % 00503 % % 00504 % % 00505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00506 % 00507 % XDrawMatteText() draws a matte with text. If the text exceeds the extents 00508 % of the text, a portion of the text relative to the cursor is displayed. 00509 % 00510 % The format of the XDrawMatteText function is: 00511 % 00512 % XDrawMatteText(display,window_info,text_info) 00513 % 00514 % A description of each parameter follows: 00515 % 00516 % o display: Specifies a pointer to the Display structure; returned from 00517 % XOpenDisplay. 00518 % 00519 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 00520 % 00521 % o text_info: Specifies a pointer to a XWidgetInfo structure. It 00522 % contains the extents of the text. 00523 % 00524 */ 00525 static void XDrawMatteText(Display *display,const XWindowInfo *window_info, 00526 XWidgetInfo *text_info) 00527 { 00528 const char 00529 *text; 00530 00531 int 00532 n, 00533 x, 00534 y; 00535 00536 register int 00537 i; 00538 00539 unsigned int 00540 height, 00541 width; 00542 00543 XFontStruct 00544 *font_info; 00545 00546 XRectangle 00547 crop_info; 00548 00549 /* 00550 Clear the text area. 00551 */ 00552 XSetMatteColor(display,window_info,MagickFalse); 00553 (void) XFillRectangle(display,window_info->id,window_info->widget_context, 00554 text_info->x,text_info->y,text_info->width,text_info->height); 00555 if (text_info->text == (char *) NULL) 00556 return; 00557 XSetTextColor(display,window_info,text_info->highlight); 00558 font_info=window_info->font_info; 00559 x=text_info->x+(QuantumMargin >> 2); 00560 y=text_info->y+font_info->ascent+(text_info->height >> 2); 00561 width=text_info->width-(QuantumMargin >> 1); 00562 height=(unsigned int) (font_info->ascent+font_info->descent); 00563 if (*text_info->text == '\0') 00564 { 00565 /* 00566 No text-- just draw cursor. 00567 */ 00568 (void) XDrawLine(display,window_info->id,window_info->annotate_context, 00569 x,y+3,x,y-height+3); 00570 return; 00571 } 00572 /* 00573 Set cropping region. 00574 */ 00575 crop_info.width=(unsigned short) text_info->width; 00576 crop_info.height=(unsigned short) text_info->height; 00577 crop_info.x=text_info->x; 00578 crop_info.y=text_info->y; 00579 /* 00580 Determine beginning of the visible text. 00581 */ 00582 if (text_info->cursor < text_info->marker) 00583 text_info->marker=text_info->cursor; 00584 else 00585 { 00586 text=text_info->marker; 00587 if (XTextWidth(font_info,(char *) text,(int) (text_info->cursor-text)) > 00588 (int) width) 00589 { 00590 text=text_info->text; 00591 for (i=0; i < Extent(text); i++) 00592 { 00593 n=XTextWidth(font_info,(char *) text+i,(int) 00594 (text_info->cursor-text-i)); 00595 if (n <= (int) width) 00596 break; 00597 } 00598 text_info->marker=(char *) text+i; 00599 } 00600 } 00601 /* 00602 Draw text and cursor. 00603 */ 00604 if (text_info->highlight == MagickFalse) 00605 { 00606 (void) XSetClipRectangles(display,window_info->widget_context,0,0, 00607 &crop_info,1,Unsorted); 00608 (void) XDrawString(display,window_info->id,window_info->widget_context, 00609 x,y,text_info->marker,Extent(text_info->marker)); 00610 (void) XSetClipMask(display,window_info->widget_context,None); 00611 } 00612 else 00613 { 00614 (void) XSetClipRectangles(display,window_info->annotate_context,0,0, 00615 &crop_info,1,Unsorted); 00616 width=WidgetTextWidth(font_info,text_info->marker); 00617 (void) XFillRectangle(display,window_info->id, 00618 window_info->annotate_context,x,y-font_info->ascent,width,height); 00619 (void) XSetClipMask(display,window_info->annotate_context,None); 00620 (void) XSetClipRectangles(display,window_info->highlight_context,0,0, 00621 &crop_info,1,Unsorted); 00622 (void) XDrawString(display,window_info->id, 00623 window_info->highlight_context,x,y,text_info->marker, 00624 Extent(text_info->marker)); 00625 (void) XSetClipMask(display,window_info->highlight_context,None); 00626 } 00627 x+=XTextWidth(font_info,text_info->marker,(int) 00628 (text_info->cursor-text_info->marker)); 00629 (void) XDrawLine(display,window_info->id,window_info->annotate_context,x,y+3, 00630 x,y-height+3); 00631 } 00632 00633 /* 00634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00635 % % 00636 % % 00637 % % 00638 + X D r a w T r i a n g l e E a s t % 00639 % % 00640 % % 00641 % % 00642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00643 % 00644 % XDrawTriangleEast() draws a triangle with a highlighted left bevel and a 00645 % shadowed right and lower bevel. The highlighted and shadowed bevels create 00646 % a 3-D effect. 00647 % 00648 % The format of the XDrawTriangleEast function is: 00649 % 00650 % XDrawTriangleEast(display,window_info,triangle_info) 00651 % 00652 % A description of each parameter follows: 00653 % 00654 % o display: Specifies a pointer to the Display structure; returned from 00655 % XOpenDisplay. 00656 % 00657 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 00658 % 00659 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It 00660 % contains the extents of the triangle. 00661 % 00662 */ 00663 static void XDrawTriangleEast(Display *display,const XWindowInfo *window_info, 00664 const XWidgetInfo *triangle_info) 00665 { 00666 int 00667 x1, 00668 x2, 00669 x3, 00670 y1, 00671 y2, 00672 y3; 00673 00674 unsigned int 00675 bevel_width; 00676 00677 XFontStruct 00678 *font_info; 00679 00680 XPoint 00681 points[4]; 00682 00683 /* 00684 Draw triangle matte. 00685 */ 00686 x1=triangle_info->x; 00687 y1=triangle_info->y; 00688 x2=triangle_info->x+triangle_info->width; 00689 y2=triangle_info->y+(triangle_info->height >> 1); 00690 x3=triangle_info->x; 00691 y3=triangle_info->y+triangle_info->height; 00692 bevel_width=triangle_info->bevel_width; 00693 points[0].x=x1; 00694 points[0].y=y1; 00695 points[1].x=x2; 00696 points[1].y=y2; 00697 points[2].x=x3; 00698 points[2].y=y3; 00699 XSetMatteColor(display,window_info,triangle_info->raised); 00700 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00701 points,3,Complex,CoordModeOrigin); 00702 /* 00703 Draw bottom bevel. 00704 */ 00705 points[0].x=x2; 00706 points[0].y=y2; 00707 points[1].x=x3; 00708 points[1].y=y3; 00709 points[2].x=x3-bevel_width; 00710 points[2].y=y3+bevel_width; 00711 points[3].x=x2+bevel_width; 00712 points[3].y=y2; 00713 XSetBevelColor(display,window_info,!triangle_info->raised); 00714 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00715 points,4,Complex,CoordModeOrigin); 00716 /* 00717 Draw Left bevel. 00718 */ 00719 points[0].x=x3; 00720 points[0].y=y3; 00721 points[1].x=x1; 00722 points[1].y=y1; 00723 points[2].x=x1-bevel_width+1; 00724 points[2].y=y1-bevel_width; 00725 points[3].x=x3-bevel_width+1; 00726 points[3].y=y3+bevel_width; 00727 XSetBevelColor(display,window_info,triangle_info->raised); 00728 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00729 points,4,Complex,CoordModeOrigin); 00730 /* 00731 Draw top bevel. 00732 */ 00733 points[0].x=x1; 00734 points[0].y=y1; 00735 points[1].x=x2; 00736 points[1].y=y2; 00737 points[2].x=x2+bevel_width; 00738 points[2].y=y2; 00739 points[3].x=x1-bevel_width; 00740 points[3].y=y1-bevel_width; 00741 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00742 points,4,Complex,CoordModeOrigin); 00743 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 00744 if (triangle_info->text == (char *) NULL) 00745 return; 00746 /* 00747 Write label to right of triangle. 00748 */ 00749 font_info=window_info->font_info; 00750 XSetTextColor(display,window_info,MagickTrue); 00751 x1=triangle_info->x+triangle_info->width+triangle_info->bevel_width+ 00752 (QuantumMargin >> 1); 00753 y1=triangle_info->y+((triangle_info->height- 00754 (font_info->ascent+font_info->descent)) >> 1)+font_info->ascent; 00755 (void) XDrawString(display,window_info->id,window_info->widget_context,x1,y1, 00756 triangle_info->text,Extent(triangle_info->text)); 00757 } 00758 00759 /* 00760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00761 % % 00762 % % 00763 % % 00764 + X D r a w T r i a n g l e N o r t h % 00765 % % 00766 % % 00767 % % 00768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00769 % 00770 % XDrawTriangleNorth() draws a triangle with a highlighted left bevel and a 00771 % shadowed right and lower bevel. The highlighted and shadowed bevels create 00772 % a 3-D effect. 00773 % 00774 % The format of the XDrawTriangleNorth function is: 00775 % 00776 % XDrawTriangleNorth(display,window_info,triangle_info) 00777 % 00778 % A description of each parameter follows: 00779 % 00780 % o display: Specifies a pointer to the Display structure; returned from 00781 % XOpenDisplay. 00782 % 00783 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 00784 % 00785 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It 00786 % contains the extents of the triangle. 00787 % 00788 */ 00789 static void XDrawTriangleNorth(Display *display,const XWindowInfo *window_info, 00790 const XWidgetInfo *triangle_info) 00791 { 00792 int 00793 x1, 00794 x2, 00795 x3, 00796 y1, 00797 y2, 00798 y3; 00799 00800 unsigned int 00801 bevel_width; 00802 00803 XPoint 00804 points[4]; 00805 00806 /* 00807 Draw triangle matte. 00808 */ 00809 x1=triangle_info->x; 00810 y1=triangle_info->y+triangle_info->height; 00811 x2=triangle_info->x+(triangle_info->width >> 1); 00812 y2=triangle_info->y; 00813 x3=triangle_info->x+triangle_info->width; 00814 y3=triangle_info->y+triangle_info->height; 00815 bevel_width=triangle_info->bevel_width; 00816 points[0].x=x1; 00817 points[0].y=y1; 00818 points[1].x=x2; 00819 points[1].y=y2; 00820 points[2].x=x3; 00821 points[2].y=y3; 00822 XSetMatteColor(display,window_info,triangle_info->raised); 00823 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00824 points,3,Complex,CoordModeOrigin); 00825 /* 00826 Draw left bevel. 00827 */ 00828 points[0].x=x1; 00829 points[0].y=y1; 00830 points[1].x=x2; 00831 points[1].y=y2; 00832 points[2].x=x2; 00833 points[2].y=y2-bevel_width-2; 00834 points[3].x=x1-bevel_width-1; 00835 points[3].y=y1+bevel_width; 00836 XSetBevelColor(display,window_info,triangle_info->raised); 00837 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00838 points,4,Complex,CoordModeOrigin); 00839 /* 00840 Draw right bevel. 00841 */ 00842 points[0].x=x2; 00843 points[0].y=y2; 00844 points[1].x=x3; 00845 points[1].y=y3; 00846 points[2].x=x3+bevel_width; 00847 points[2].y=y3+bevel_width; 00848 points[3].x=x2; 00849 points[3].y=y2-bevel_width; 00850 XSetBevelColor(display,window_info,!triangle_info->raised); 00851 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00852 points,4,Complex,CoordModeOrigin); 00853 /* 00854 Draw lower bevel. 00855 */ 00856 points[0].x=x3; 00857 points[0].y=y3; 00858 points[1].x=x1; 00859 points[1].y=y1; 00860 points[2].x=x1-bevel_width; 00861 points[2].y=y1+bevel_width; 00862 points[3].x=x3+bevel_width; 00863 points[3].y=y3+bevel_width; 00864 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00865 points,4,Complex,CoordModeOrigin); 00866 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 00867 } 00868 00869 /* 00870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00871 % % 00872 % % 00873 % % 00874 + X D r a w T r i a n g l e S o u t h % 00875 % % 00876 % % 00877 % % 00878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00879 % 00880 % XDrawTriangleSouth() draws a border with a highlighted left and right bevel 00881 % and a shadowed lower bevel. The highlighted and shadowed bevels create a 00882 % 3-D effect. 00883 % 00884 % The format of the XDrawTriangleSouth function is: 00885 % 00886 % XDrawTriangleSouth(display,window_info,triangle_info) 00887 % 00888 % A description of each parameter follows: 00889 % 00890 % o display: Specifies a pointer to the Display structure; returned from 00891 % XOpenDisplay. 00892 % 00893 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 00894 % 00895 % o triangle_info: Specifies a pointer to a XWidgetInfo structure. It 00896 % contains the extents of the triangle. 00897 % 00898 */ 00899 static void XDrawTriangleSouth(Display *display,const XWindowInfo *window_info, 00900 const XWidgetInfo *triangle_info) 00901 { 00902 int 00903 x1, 00904 x2, 00905 x3, 00906 y1, 00907 y2, 00908 y3; 00909 00910 unsigned int 00911 bevel_width; 00912 00913 XPoint 00914 points[4]; 00915 00916 /* 00917 Draw triangle matte. 00918 */ 00919 x1=triangle_info->x; 00920 y1=triangle_info->y; 00921 x2=triangle_info->x+(triangle_info->width >> 1); 00922 y2=triangle_info->y+triangle_info->height; 00923 x3=triangle_info->x+triangle_info->width; 00924 y3=triangle_info->y; 00925 bevel_width=triangle_info->bevel_width; 00926 points[0].x=x1; 00927 points[0].y=y1; 00928 points[1].x=x2; 00929 points[1].y=y2; 00930 points[2].x=x3; 00931 points[2].y=y3; 00932 XSetMatteColor(display,window_info,triangle_info->raised); 00933 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00934 points,3,Complex,CoordModeOrigin); 00935 /* 00936 Draw top bevel. 00937 */ 00938 points[0].x=x3; 00939 points[0].y=y3; 00940 points[1].x=x1; 00941 points[1].y=y1; 00942 points[2].x=x1-bevel_width; 00943 points[2].y=y1-bevel_width; 00944 points[3].x=x3+bevel_width; 00945 points[3].y=y3-bevel_width; 00946 XSetBevelColor(display,window_info,triangle_info->raised); 00947 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00948 points,4,Complex,CoordModeOrigin); 00949 /* 00950 Draw right bevel. 00951 */ 00952 points[0].x=x2; 00953 points[0].y=y2; 00954 points[1].x=x3+1; 00955 points[1].y=y3-bevel_width; 00956 points[2].x=x3+bevel_width; 00957 points[2].y=y3-bevel_width; 00958 points[3].x=x2; 00959 points[3].y=y2+bevel_width; 00960 XSetBevelColor(display,window_info,!triangle_info->raised); 00961 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00962 points,4,Complex,CoordModeOrigin); 00963 /* 00964 Draw left bevel. 00965 */ 00966 points[0].x=x1; 00967 points[0].y=y1; 00968 points[1].x=x2; 00969 points[1].y=y2; 00970 points[2].x=x2; 00971 points[2].y=y2+bevel_width; 00972 points[3].x=x1-bevel_width; 00973 points[3].y=y1-bevel_width; 00974 XSetBevelColor(display,window_info,triangle_info->raised); 00975 (void) XFillPolygon(display,window_info->id,window_info->widget_context, 00976 points,4,Complex,CoordModeOrigin); 00977 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 00978 } 00979 00980 /* 00981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00982 % % 00983 % % 00984 % % 00985 + X D r a w W i d g e t T e x t % 00986 % % 00987 % % 00988 % % 00989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00990 % 00991 % XDrawWidgetText() first clears the widget and draws a text string justifed 00992 % left (or center) in the x-direction and centered within the y-direction. 00993 % 00994 % The format of the XDrawWidgetText function is: 00995 % 00996 % XDrawWidgetText(display,window_info,text_info) 00997 % 00998 % A description of each parameter follows: 00999 % 01000 % o display: Specifies a pointer to the Display structure; returned from 01001 % XOpenDisplay. 01002 % 01003 % o window_info: Specifies a pointer to a XWindowText structure. 01004 % 01005 % o text_info: Specifies a pointer to XWidgetInfo structure. 01006 % 01007 */ 01008 static void XDrawWidgetText(Display *display,const XWindowInfo *window_info, 01009 XWidgetInfo *text_info) 01010 { 01011 GC 01012 widget_context; 01013 01014 int 01015 x, 01016 y; 01017 01018 unsigned int 01019 height, 01020 width; 01021 01022 XFontStruct 01023 *font_info; 01024 01025 XRectangle 01026 crop_info; 01027 01028 /* 01029 Clear the text area. 01030 */ 01031 widget_context=window_info->annotate_context; 01032 if (text_info->raised) 01033 (void) XClearArea(display,window_info->id,text_info->x,text_info->y, 01034 text_info->width,text_info->height,MagickFalse); 01035 else 01036 { 01037 (void) XFillRectangle(display,window_info->id,widget_context,text_info->x, 01038 text_info->y,text_info->width,text_info->height); 01039 widget_context=window_info->highlight_context; 01040 } 01041 if (text_info->text == (char *) NULL) 01042 return; 01043 if (*text_info->text == '\0') 01044 return; 01045 /* 01046 Set cropping region. 01047 */ 01048 font_info=window_info->font_info; 01049 crop_info.width=(unsigned short) text_info->width; 01050 crop_info.height=(unsigned short) text_info->height; 01051 crop_info.x=text_info->x; 01052 crop_info.y=text_info->y; 01053 /* 01054 Draw text. 01055 */ 01056 width=WidgetTextWidth(font_info,text_info->text); 01057 x=text_info->x+(QuantumMargin >> 1); 01058 if (text_info->center) 01059 x=text_info->x+(text_info->width >> 1)-(width >> 1); 01060 if (text_info->raised) 01061 if (width > (text_info->width-QuantumMargin)) 01062 x+=(text_info->width-QuantumMargin-width); 01063 height=(unsigned int) (font_info->ascent+font_info->descent); 01064 y=text_info->y+((text_info->height-height) >> 1)+font_info->ascent; 01065 (void) XSetClipRectangles(display,widget_context,0,0,&crop_info,1,Unsorted); 01066 (void) XDrawString(display,window_info->id,widget_context,x,y,text_info->text, 01067 Extent(text_info->text)); 01068 (void) XSetClipMask(display,widget_context,None); 01069 if (x < text_info->x) 01070 (void) XDrawLine(display,window_info->id,window_info->annotate_context, 01071 text_info->x,text_info->y,text_info->x,text_info->y+text_info->height-1); 01072 } 01073 01074 /* 01075 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01076 % % 01077 % % 01078 % % 01079 + X E d i t T e x t % 01080 % % 01081 % % 01082 % % 01083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01084 % 01085 % XEditText() edits a text string as indicated by the key symbol. 01086 % 01087 % The format of the XEditText function is: 01088 % 01089 % XEditText(display,text_info,key_symbol,text,state) 01090 % 01091 % A description of each parameter follows: 01092 % 01093 % o display: Specifies a connection to an X server; returned from 01094 % XOpenDisplay. 01095 % 01096 % o text_info: Specifies a pointer to a XWidgetInfo structure. It 01097 % contains the extents of the text. 01098 % 01099 % o key_symbol: A X11 KeySym that indicates what editing function to 01100 % perform to the text. 01101 % 01102 % o text: A character string to insert into the text. 01103 % 01104 % o state: An size_t that indicates whether the key symbol is a 01105 % control character or not. 01106 % 01107 */ 01108 static void XEditText(Display *display,XWidgetInfo *text_info, 01109 const KeySym key_symbol,char *text,const size_t state) 01110 { 01111 switch ((int) key_symbol) 01112 { 01113 case XK_BackSpace: 01114 case XK_Delete: 01115 { 01116 if (text_info->highlight) 01117 { 01118 /* 01119 Erase the entire line of text. 01120 */ 01121 *text_info->text='\0'; 01122 text_info->cursor=text_info->text; 01123 text_info->marker=text_info->text; 01124 text_info->highlight=MagickFalse; 01125 } 01126 /* 01127 Erase one character. 01128 */ 01129 if (text_info->cursor != text_info->text) 01130 { 01131 text_info->cursor--; 01132 (void) CopyMagickString(text_info->cursor,text_info->cursor+1, 01133 MaxTextExtent); 01134 text_info->highlight=MagickFalse; 01135 break; 01136 } 01137 } 01138 case XK_Left: 01139 case XK_KP_Left: 01140 { 01141 /* 01142 Move cursor one position left. 01143 */ 01144 if (text_info->cursor == text_info->text) 01145 break; 01146 text_info->cursor--; 01147 break; 01148 } 01149 case XK_Right: 01150 case XK_KP_Right: 01151 { 01152 /* 01153 Move cursor one position right. 01154 */ 01155 if (text_info->cursor == (text_info->text+Extent(text_info->text))) 01156 break; 01157 text_info->cursor++; 01158 break; 01159 } 01160 default: 01161 { 01162 register char 01163 *p, 01164 *q; 01165 01166 register int 01167 i; 01168 01169 if (state & ControlState) 01170 break; 01171 if (*text == '\0') 01172 break; 01173 if ((Extent(text_info->text)+1) >= (int) MaxTextExtent) 01174 (void) XBell(display,0); 01175 else 01176 { 01177 if (text_info->highlight) 01178 { 01179 /* 01180 Erase the entire line of text. 01181 */ 01182 *text_info->text='\0'; 01183 text_info->cursor=text_info->text; 01184 text_info->marker=text_info->text; 01185 text_info->highlight=MagickFalse; 01186 } 01187 /* 01188 Insert a string into the text. 01189 */ 01190 q=text_info->text+Extent(text_info->text)+strlen(text); 01191 for (i=0; i <= Extent(text_info->cursor); i++) 01192 { 01193 *q=(*(q-Extent(text))); 01194 q--; 01195 } 01196 p=text; 01197 for (i=0; i < Extent(text); i++) 01198 *text_info->cursor++=(*p++); 01199 } 01200 break; 01201 } 01202 } 01203 } 01204 01205 /* 01206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01207 % % 01208 % % 01209 % % 01210 + X G e t W i d g e t I n f o % 01211 % % 01212 % % 01213 % % 01214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01215 % 01216 % XGetWidgetInfo() initializes the XWidgetInfo structure. 01217 % 01218 % The format of the XGetWidgetInfo function is: 01219 % 01220 % XGetWidgetInfo(text,widget_info) 01221 % 01222 % A description of each parameter follows: 01223 % 01224 % o text: A string of characters associated with the widget. 01225 % 01226 % o widget_info: Specifies a pointer to a X11 XWidgetInfo structure. 01227 % 01228 */ 01229 static void XGetWidgetInfo(const char *text,XWidgetInfo *widget_info) 01230 { 01231 /* 01232 Initialize widget info. 01233 */ 01234 widget_info->id=(~0); 01235 widget_info->bevel_width=3; 01236 widget_info->width=1; 01237 widget_info->height=1; 01238 widget_info->x=0; 01239 widget_info->y=0; 01240 widget_info->min_y=0; 01241 widget_info->max_y=0; 01242 widget_info->raised=MagickTrue; 01243 widget_info->active=MagickFalse; 01244 widget_info->center=MagickTrue; 01245 widget_info->trough=MagickFalse; 01246 widget_info->highlight=MagickFalse; 01247 widget_info->text=(char *) text; 01248 widget_info->cursor=(char *) text; 01249 if (text != (char *) NULL) 01250 widget_info->cursor+=Extent(text); 01251 widget_info->marker=(char *) text; 01252 } 01253 01254 /* 01255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01256 % % 01257 % % 01258 % % 01259 + X H i g h l i g h t W i d g e t % 01260 % % 01261 % % 01262 % % 01263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01264 % 01265 % XHighlightWidget() draws a highlighted border around a window. 01266 % 01267 % The format of the XHighlightWidget function is: 01268 % 01269 % XHighlightWidget(display,window_info,x,y) 01270 % 01271 % A description of each parameter follows: 01272 % 01273 % o display: Specifies a pointer to the Display structure; returned from 01274 % XOpenDisplay. 01275 % 01276 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 01277 % 01278 % o x: Specifies an integer representing the rectangle offset in the 01279 % x-direction. 01280 % 01281 % o y: Specifies an integer representing the rectangle offset in the 01282 % y-direction. 01283 % 01284 */ 01285 static void XHighlightWidget(Display *display,const XWindowInfo *window_info, 01286 const int x,const int y) 01287 { 01288 /* 01289 Draw the widget highlighting rectangle. 01290 */ 01291 XSetBevelColor(display,window_info,MagickTrue); 01292 (void) XDrawRectangle(display,window_info->id,window_info->widget_context,x,y, 01293 window_info->width-(x << 1),window_info->height-(y << 1)); 01294 (void) XDrawRectangle(display,window_info->id,window_info->widget_context, 01295 x-1,y-1,window_info->width-(x << 1)+1,window_info->height-(y << 1)+1); 01296 XSetBevelColor(display,window_info,MagickFalse); 01297 (void) XDrawRectangle(display,window_info->id,window_info->widget_context, 01298 x-1,y-1,window_info->width-(x << 1),window_info->height-(y << 1)); 01299 (void) XSetFillStyle(display,window_info->widget_context,FillSolid); 01300 } 01301 01302 /* 01303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01304 % % 01305 % % 01306 % % 01307 + X S c r e e n E v e n t % 01308 % % 01309 % % 01310 % % 01311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01312 % 01313 % XScreenEvent() returns MagickTrue if the any event on the X server queue is 01314 % associated with the widget window. 01315 % 01316 % The format of the XScreenEvent function is: 01317 % 01318 % int XScreenEvent(Display *display,XEvent *event,char *data) 01319 % 01320 % A description of each parameter follows: 01321 % 01322 % o display: Specifies a pointer to the Display structure; returned from 01323 % XOpenDisplay. 01324 % 01325 % o event: Specifies a pointer to a X11 XEvent structure. 01326 % 01327 % o data: Specifies a pointer to a XWindows structure. 01328 % 01329 */ 01330 01331 #if defined(__cplusplus) || defined(c_plusplus) 01332 extern "C" { 01333 #endif 01334 01335 static int XScreenEvent(Display *display,XEvent *event,char *data) 01336 { 01337 XWindows 01338 *windows; 01339 01340 windows=(XWindows *) data; 01341 if (event->xany.window == windows->popup.id) 01342 { 01343 if (event->type == MapNotify) 01344 windows->popup.mapped=MagickTrue; 01345 if (event->type == UnmapNotify) 01346 windows->popup.mapped=MagickFalse; 01347 return(MagickTrue); 01348 } 01349 if (event->xany.window == windows->widget.id) 01350 { 01351 if (event->type == MapNotify) 01352 windows->widget.mapped=MagickTrue; 01353 if (event->type == UnmapNotify) 01354 windows->widget.mapped=MagickFalse; 01355 return(MagickTrue); 01356 } 01357 switch (event->type) 01358 { 01359 case ButtonPress: 01360 { 01361 if ((event->xbutton.button == Button3) && 01362 (event->xbutton.state & Mod1Mask)) 01363 { 01364 /* 01365 Convert Alt-Button3 to Button2. 01366 */ 01367 event->xbutton.button=Button2; 01368 event->xbutton.state&=(~Mod1Mask); 01369 } 01370 return(MagickTrue); 01371 } 01372 case Expose: 01373 { 01374 if (event->xexpose.window == windows->image.id) 01375 { 01376 XRefreshWindow(display,&windows->image,event); 01377 break; 01378 } 01379 if (event->xexpose.window == windows->magnify.id) 01380 if (event->xexpose.count == 0) 01381 if (windows->magnify.mapped) 01382 { 01383 ExceptionInfo 01384 *exception; 01385 01386 exception=AcquireExceptionInfo(); 01387 XMakeMagnifyImage(display,windows,exception); 01388 exception=DestroyExceptionInfo(exception); 01389 break; 01390 } 01391 if (event->xexpose.window == windows->command.id) 01392 if (event->xexpose.count == 0) 01393 { 01394 (void) XCommandWidget(display,windows,(const char **) NULL,event); 01395 break; 01396 } 01397 break; 01398 } 01399 case FocusOut: 01400 { 01401 /* 01402 Set input focus for backdrop window. 01403 */ 01404 if (event->xfocus.window == windows->image.id) 01405 (void) XSetInputFocus(display,windows->image.id,RevertToNone, 01406 CurrentTime); 01407 return(MagickTrue); 01408 } 01409 case ButtonRelease: 01410 case KeyPress: 01411 case KeyRelease: 01412 case MotionNotify: 01413 case SelectionNotify: 01414 return(MagickTrue); 01415 default: 01416 break; 01417 } 01418 return(MagickFalse); 01419 } 01420 01421 #if defined(__cplusplus) || defined(c_plusplus) 01422 } 01423 #endif 01424 01425 /* 01426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01427 % % 01428 % % 01429 % % 01430 + X S e t B e v e l C o l o r % 01431 % % 01432 % % 01433 % % 01434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01435 % 01436 % XSetBevelColor() sets the graphic context for drawing a beveled border. 01437 % 01438 % The format of the XSetBevelColor function is: 01439 % 01440 % XSetBevelColor(display,window_info,raised) 01441 % 01442 % A description of each parameter follows: 01443 % 01444 % o display: Specifies a pointer to the Display structure; returned from 01445 % XOpenDisplay. 01446 % 01447 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 01448 % 01449 % o raised: A value other than zero indicates the color show be a 01450 % "highlight" color, otherwise the "shadow" color is set. 01451 % 01452 */ 01453 static void XSetBevelColor(Display *display,const XWindowInfo *window_info, 01454 const MagickStatusType raised) 01455 { 01456 if (window_info->depth == 1) 01457 { 01458 Pixmap 01459 stipple; 01460 01461 /* 01462 Monochrome window. 01463 */ 01464 (void) XSetBackground(display,window_info->widget_context, 01465 XBlackPixel(display,window_info->screen)); 01466 (void) XSetForeground(display,window_info->widget_context, 01467 XWhitePixel(display,window_info->screen)); 01468 (void) XSetFillStyle(display,window_info->widget_context, 01469 FillOpaqueStippled); 01470 stipple=window_info->highlight_stipple; 01471 if (raised == MagickFalse) 01472 stipple=window_info->shadow_stipple; 01473 (void) XSetStipple(display,window_info->widget_context,stipple); 01474 } 01475 else 01476 if (raised) 01477 (void) XSetForeground(display,window_info->widget_context, 01478 window_info->pixel_info->highlight_color.pixel); 01479 else 01480 (void) XSetForeground(display,window_info->widget_context, 01481 window_info->pixel_info->shadow_color.pixel); 01482 } 01483 01484 /* 01485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01486 % % 01487 % % 01488 % % 01489 + X S e t M a t t e C o l o r % 01490 % % 01491 % % 01492 % % 01493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01494 % 01495 % XSetMatteColor() sets the graphic context for drawing the matte. 01496 % 01497 % The format of the XSetMatteColor function is: 01498 % 01499 % XSetMatteColor(display,window_info,raised) 01500 % 01501 % A description of each parameter follows: 01502 % 01503 % o display: Specifies a pointer to the Display structure; returned from 01504 % XOpenDisplay. 01505 % 01506 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 01507 % 01508 % o raised: A value other than zero indicates the matte is active. 01509 % 01510 */ 01511 static void XSetMatteColor(Display *display,const XWindowInfo *window_info, 01512 const MagickStatusType raised) 01513 { 01514 if (window_info->depth == 1) 01515 { 01516 /* 01517 Monochrome window. 01518 */ 01519 if (raised) 01520 (void) XSetForeground(display,window_info->widget_context, 01521 XWhitePixel(display,window_info->screen)); 01522 else 01523 (void) XSetForeground(display,window_info->widget_context, 01524 XBlackPixel(display,window_info->screen)); 01525 } 01526 else 01527 if (raised) 01528 (void) XSetForeground(display,window_info->widget_context, 01529 window_info->pixel_info->matte_color.pixel); 01530 else 01531 (void) XSetForeground(display,window_info->widget_context, 01532 window_info->pixel_info->depth_color.pixel); 01533 } 01534 01535 /* 01536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01537 % % 01538 % % 01539 % % 01540 + X S e t T e x t C o l o r % 01541 % % 01542 % % 01543 % % 01544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01545 % 01546 % XSetTextColor() sets the graphic context for drawing text on a matte. 01547 % 01548 % The format of the XSetTextColor function is: 01549 % 01550 % XSetTextColor(display,window_info,raised) 01551 % 01552 % A description of each parameter follows: 01553 % 01554 % o display: Specifies a pointer to the Display structure; returned from 01555 % XOpenDisplay. 01556 % 01557 % o window_info: Specifies a pointer to a X11 XWindowInfo structure. 01558 % 01559 % o raised: A value other than zero indicates the color show be a 01560 % "highlight" color, otherwise the "shadow" color is set. 01561 % 01562 */ 01563 static void XSetTextColor(Display *display,const XWindowInfo *window_info, 01564 const MagickStatusType raised) 01565 { 01566 ssize_t 01567 foreground, 01568 matte; 01569 01570 if (window_info->depth == 1) 01571 { 01572 /* 01573 Monochrome window. 01574 */ 01575 if (raised) 01576 (void) XSetForeground(display,window_info->widget_context, 01577 XBlackPixel(display,window_info->screen)); 01578 else 01579 (void) XSetForeground(display,window_info->widget_context, 01580 XWhitePixel(display,window_info->screen)); 01581 return; 01582 } 01583 foreground=(ssize_t) XPixelIntensity( 01584 &window_info->pixel_info->foreground_color); 01585 matte=(ssize_t) XPixelIntensity(&window_info->pixel_info->matte_color); 01586 if (MagickAbsoluteValue((int) (foreground-matte)) > (65535L >> 3)) 01587 (void) XSetForeground(display,window_info->widget_context, 01588 window_info->pixel_info->foreground_color.pixel); 01589 else 01590 (void) XSetForeground(display,window_info->widget_context, 01591 window_info->pixel_info->background_color.pixel); 01592 } 01593 01594 /* 01595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01596 % % 01597 % % 01598 % % 01599 % X C o l o r B r o w s e r W i d g e t % 01600 % % 01601 % % 01602 % % 01603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01604 % 01605 % XColorBrowserWidget() displays a Color Browser widget with a color query 01606 % to the user. The user keys a reply and presses the Action or Cancel button 01607 % to exit. The typed text is returned as the reply function parameter. 01608 % 01609 % The format of the XColorBrowserWidget method is: 01610 % 01611 % void XColorBrowserWidget(Display *display,XWindows *windows, 01612 % const char *action,char *reply) 01613 % 01614 % A description of each parameter follows: 01615 % 01616 % o display: Specifies a connection to an X server; returned from 01617 % XOpenDisplay. 01618 % 01619 % o window: Specifies a pointer to a XWindows structure. 01620 % 01621 % o action: Specifies a pointer to the action of this widget. 01622 % 01623 % o reply: the response from the user is returned in this parameter. 01624 % 01625 */ 01626 MagickPrivate void XColorBrowserWidget(Display *display,XWindows *windows, 01627 const char *action,char *reply) 01628 { 01629 #define CancelButtonText "Cancel" 01630 #define ColornameText "Name:" 01631 #define ColorPatternText "Pattern:" 01632 #define GrabButtonText "Grab" 01633 #define ResetButtonText "Reset" 01634 01635 char 01636 **colorlist, 01637 primary_selection[MaxTextExtent], 01638 reset_pattern[MaxTextExtent], 01639 text[MaxTextExtent]; 01640 01641 ExceptionInfo 01642 *exception; 01643 01644 int 01645 x, 01646 y; 01647 01648 register int 01649 i; 01650 01651 static char 01652 glob_pattern[MaxTextExtent] = "*"; 01653 01654 static MagickStatusType 01655 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY); 01656 01657 Status 01658 status; 01659 01660 unsigned int 01661 height, 01662 text_width, 01663 visible_colors, 01664 width; 01665 01666 size_t 01667 colors, 01668 delay, 01669 state; 01670 01671 XColor 01672 color; 01673 01674 XEvent 01675 event; 01676 01677 XFontStruct 01678 *font_info; 01679 01680 XTextProperty 01681 window_name; 01682 01683 XWidgetInfo 01684 action_info, 01685 cancel_info, 01686 expose_info, 01687 grab_info, 01688 list_info, 01689 mode_info, 01690 north_info, 01691 reply_info, 01692 reset_info, 01693 scroll_info, 01694 selection_info, 01695 slider_info, 01696 south_info, 01697 text_info; 01698 01699 XWindowChanges 01700 window_changes; 01701 01702 /* 01703 Get color list and sort in ascending order. 01704 */ 01705 assert(display != (Display *) NULL); 01706 assert(windows != (XWindows *) NULL); 01707 assert(action != (char *) NULL); 01708 assert(reply != (char *) NULL); 01709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 01710 XSetCursorState(display,windows,MagickTrue); 01711 XCheckRefreshWindows(display,windows); 01712 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent); 01713 exception=AcquireExceptionInfo(); 01714 colorlist=GetColorList(glob_pattern,&colors,exception); 01715 if (colorlist == (char **) NULL) 01716 { 01717 /* 01718 Pattern failed, obtain all the colors. 01719 */ 01720 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent); 01721 colorlist=GetColorList(glob_pattern,&colors,exception); 01722 if (colorlist == (char **) NULL) 01723 { 01724 XNoticeWidget(display,windows,"Unable to obtain colors names:", 01725 glob_pattern); 01726 (void) XDialogWidget(display,windows,action,"Enter color name:", 01727 reply); 01728 return; 01729 } 01730 } 01731 /* 01732 Determine Color Browser widget attributes. 01733 */ 01734 font_info=windows->widget.font_info; 01735 text_width=0; 01736 for (i=0; i < (int) colors; i++) 01737 if (WidgetTextWidth(font_info,colorlist[i]) > text_width) 01738 text_width=WidgetTextWidth(font_info,colorlist[i]); 01739 width=WidgetTextWidth(font_info,(char *) action); 01740 if (WidgetTextWidth(font_info,CancelButtonText) > width) 01741 width=WidgetTextWidth(font_info,CancelButtonText); 01742 if (WidgetTextWidth(font_info,ResetButtonText) > width) 01743 width=WidgetTextWidth(font_info,ResetButtonText); 01744 if (WidgetTextWidth(font_info,GrabButtonText) > width) 01745 width=WidgetTextWidth(font_info,GrabButtonText); 01746 width+=QuantumMargin; 01747 if (WidgetTextWidth(font_info,ColorPatternText) > width) 01748 width=WidgetTextWidth(font_info,ColorPatternText); 01749 if (WidgetTextWidth(font_info,ColornameText) > width) 01750 width=WidgetTextWidth(font_info,ColornameText); 01751 height=(unsigned int) (font_info->ascent+font_info->descent); 01752 /* 01753 Position Color Browser widget. 01754 */ 01755 windows->widget.width=(unsigned int) 01756 (width+MagickMin((int) text_width,(int) MaxTextWidth)+6*QuantumMargin); 01757 windows->widget.min_width=(unsigned int) 01758 (width+MinTextWidth+4*QuantumMargin); 01759 if (windows->widget.width < windows->widget.min_width) 01760 windows->widget.width=windows->widget.min_width; 01761 windows->widget.height=(unsigned int) 01762 ((81*height) >> 2)+((13*QuantumMargin) >> 1)+4; 01763 windows->widget.min_height=(unsigned int) 01764 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4); 01765 if (windows->widget.height < windows->widget.min_height) 01766 windows->widget.height=windows->widget.min_height; 01767 XConstrainWindowPosition(display,&windows->widget); 01768 /* 01769 Map Color Browser widget. 01770 */ 01771 (void) CopyMagickString(windows->widget.name,"Browse and Select a Color", 01772 MaxTextExtent); 01773 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 01774 if (status != False) 01775 { 01776 XSetWMName(display,windows->widget.id,&window_name); 01777 XSetWMIconName(display,windows->widget.id,&window_name); 01778 (void) XFree((void *) window_name.value); 01779 } 01780 window_changes.width=(int) windows->widget.width; 01781 window_changes.height=(int) windows->widget.height; 01782 window_changes.x=windows->widget.x; 01783 window_changes.y=windows->widget.y; 01784 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 01785 mask,&window_changes); 01786 (void) XMapRaised(display,windows->widget.id); 01787 windows->widget.mapped=MagickFalse; 01788 /* 01789 Respond to X events. 01790 */ 01791 XGetWidgetInfo((char *) NULL,&slider_info); 01792 XGetWidgetInfo((char *) NULL,&north_info); 01793 XGetWidgetInfo((char *) NULL,&south_info); 01794 XGetWidgetInfo((char *) NULL,&expose_info); 01795 visible_colors=0; 01796 delay=SuspendTime << 2; 01797 state=UpdateConfigurationState; 01798 do 01799 { 01800 if (state & UpdateConfigurationState) 01801 { 01802 int 01803 id; 01804 01805 /* 01806 Initialize button information. 01807 */ 01808 XGetWidgetInfo(CancelButtonText,&cancel_info); 01809 cancel_info.width=width; 01810 cancel_info.height=(unsigned int) ((3*height) >> 1); 01811 cancel_info.x=(int) 01812 (windows->widget.width-cancel_info.width-QuantumMargin-2); 01813 cancel_info.y=(int) 01814 (windows->widget.height-cancel_info.height-QuantumMargin); 01815 XGetWidgetInfo(action,&action_info); 01816 action_info.width=width; 01817 action_info.height=(unsigned int) ((3*height) >> 1); 01818 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+ 01819 (action_info.bevel_width << 1)); 01820 action_info.y=cancel_info.y; 01821 XGetWidgetInfo(GrabButtonText,&grab_info); 01822 grab_info.width=width; 01823 grab_info.height=(unsigned int) ((3*height) >> 1); 01824 grab_info.x=QuantumMargin; 01825 grab_info.y=((5*QuantumMargin) >> 1)+height; 01826 XGetWidgetInfo(ResetButtonText,&reset_info); 01827 reset_info.width=width; 01828 reset_info.height=(unsigned int) ((3*height) >> 1); 01829 reset_info.x=QuantumMargin; 01830 reset_info.y=grab_info.y+grab_info.height+QuantumMargin; 01831 /* 01832 Initialize reply information. 01833 */ 01834 XGetWidgetInfo(reply,&reply_info); 01835 reply_info.raised=MagickFalse; 01836 reply_info.bevel_width--; 01837 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1); 01838 reply_info.height=height << 1; 01839 reply_info.x=(int) (width+(QuantumMargin << 1)); 01840 reply_info.y=action_info.y-reply_info.height-QuantumMargin; 01841 /* 01842 Initialize mode information. 01843 */ 01844 XGetWidgetInfo((char *) NULL,&mode_info); 01845 mode_info.active=MagickTrue; 01846 mode_info.bevel_width=0; 01847 mode_info.width=(unsigned int) (action_info.x-(QuantumMargin << 1)); 01848 mode_info.height=action_info.height; 01849 mode_info.x=QuantumMargin; 01850 mode_info.y=action_info.y; 01851 /* 01852 Initialize scroll information. 01853 */ 01854 XGetWidgetInfo((char *) NULL,&scroll_info); 01855 scroll_info.bevel_width--; 01856 scroll_info.width=height; 01857 scroll_info.height=(unsigned int) (reply_info.y-grab_info.y- 01858 (QuantumMargin >> 1)); 01859 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width); 01860 scroll_info.y=grab_info.y-reply_info.bevel_width; 01861 scroll_info.raised=MagickFalse; 01862 scroll_info.trough=MagickTrue; 01863 north_info=scroll_info; 01864 north_info.raised=MagickTrue; 01865 north_info.width-=(north_info.bevel_width << 1); 01866 north_info.height=north_info.width-1; 01867 north_info.x+=north_info.bevel_width; 01868 north_info.y+=north_info.bevel_width; 01869 south_info=north_info; 01870 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width- 01871 south_info.height; 01872 id=slider_info.id; 01873 slider_info=north_info; 01874 slider_info.id=id; 01875 slider_info.width-=2; 01876 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+ 01877 slider_info.bevel_width+2; 01878 slider_info.height=scroll_info.height-((slider_info.min_y- 01879 scroll_info.y+1) << 1)+4; 01880 visible_colors=scroll_info.height/(height+(height >> 3)); 01881 if (colors > visible_colors) 01882 slider_info.height=(unsigned int) 01883 ((visible_colors*slider_info.height)/colors); 01884 slider_info.max_y=south_info.y-south_info.bevel_width- 01885 slider_info.bevel_width-2; 01886 slider_info.x=scroll_info.x+slider_info.bevel_width+1; 01887 slider_info.y=slider_info.min_y; 01888 expose_info=scroll_info; 01889 expose_info.y=slider_info.y; 01890 /* 01891 Initialize list information. 01892 */ 01893 XGetWidgetInfo((char *) NULL,&list_info); 01894 list_info.raised=MagickFalse; 01895 list_info.bevel_width--; 01896 list_info.width=(unsigned int) 01897 (scroll_info.x-reply_info.x-(QuantumMargin >> 1)); 01898 list_info.height=scroll_info.height; 01899 list_info.x=reply_info.x; 01900 list_info.y=scroll_info.y; 01901 if (windows->widget.mapped == MagickFalse) 01902 state|=JumpListState; 01903 /* 01904 Initialize text information. 01905 */ 01906 *text='\0'; 01907 XGetWidgetInfo(text,&text_info); 01908 text_info.center=MagickFalse; 01909 text_info.width=reply_info.width; 01910 text_info.height=height; 01911 text_info.x=list_info.x-(QuantumMargin >> 1); 01912 text_info.y=QuantumMargin; 01913 /* 01914 Initialize selection information. 01915 */ 01916 XGetWidgetInfo((char *) NULL,&selection_info); 01917 selection_info.center=MagickFalse; 01918 selection_info.width=list_info.width; 01919 selection_info.height=(unsigned int) ((9*height) >> 3); 01920 selection_info.x=list_info.x; 01921 state&=(~UpdateConfigurationState); 01922 } 01923 if (state & RedrawWidgetState) 01924 { 01925 /* 01926 Redraw Color Browser window. 01927 */ 01928 x=QuantumMargin; 01929 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent; 01930 (void) XDrawString(display,windows->widget.id, 01931 windows->widget.annotate_context,x,y,ColorPatternText, 01932 Extent(ColorPatternText)); 01933 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent); 01934 XDrawWidgetText(display,&windows->widget,&text_info); 01935 XDrawBeveledButton(display,&windows->widget,&grab_info); 01936 XDrawBeveledButton(display,&windows->widget,&reset_info); 01937 XDrawBeveledMatte(display,&windows->widget,&list_info); 01938 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 01939 XDrawTriangleNorth(display,&windows->widget,&north_info); 01940 XDrawBeveledButton(display,&windows->widget,&slider_info); 01941 XDrawTriangleSouth(display,&windows->widget,&south_info); 01942 x=QuantumMargin; 01943 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent; 01944 (void) XDrawString(display,windows->widget.id, 01945 windows->widget.annotate_context,x,y,ColornameText, 01946 Extent(ColornameText)); 01947 XDrawBeveledMatte(display,&windows->widget,&reply_info); 01948 XDrawMatteText(display,&windows->widget,&reply_info); 01949 XDrawBeveledButton(display,&windows->widget,&action_info); 01950 XDrawBeveledButton(display,&windows->widget,&cancel_info); 01951 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 01952 selection_info.id=(~0); 01953 state|=RedrawActionState; 01954 state|=RedrawListState; 01955 state&=(~RedrawWidgetState); 01956 } 01957 if (state & UpdateListState) 01958 { 01959 char 01960 **checklist; 01961 01962 size_t 01963 number_colors; 01964 01965 status=XParseColor(display,windows->widget.map_info->colormap, 01966 glob_pattern,&color); 01967 if ((status != False) || (strchr(glob_pattern,'-') != (char *) NULL)) 01968 { 01969 /* 01970 Reply is a single color name-- exit. 01971 */ 01972 (void) CopyMagickString(reply,glob_pattern,MaxTextExtent); 01973 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent); 01974 action_info.raised=MagickFalse; 01975 XDrawBeveledButton(display,&windows->widget,&action_info); 01976 break; 01977 } 01978 /* 01979 Update color list. 01980 */ 01981 checklist=GetColorList(glob_pattern,&number_colors,exception); 01982 if (number_colors == 0) 01983 { 01984 (void) CopyMagickString(glob_pattern,reset_pattern,MaxTextExtent); 01985 (void) XBell(display,0); 01986 } 01987 else 01988 { 01989 for (i=0; i < (int) colors; i++) 01990 colorlist[i]=DestroyString(colorlist[i]); 01991 if (colorlist != (char **) NULL) 01992 colorlist=(char **) RelinquishMagickMemory(colorlist); 01993 colorlist=checklist; 01994 colors=number_colors; 01995 } 01996 /* 01997 Sort color list in ascending order. 01998 */ 01999 slider_info.height= 02000 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1; 02001 if (colors > visible_colors) 02002 slider_info.height=(unsigned int) 02003 ((visible_colors*slider_info.height)/colors); 02004 slider_info.max_y=south_info.y-south_info.bevel_width- 02005 slider_info.bevel_width-2; 02006 slider_info.id=0; 02007 slider_info.y=slider_info.min_y; 02008 expose_info.y=slider_info.y; 02009 selection_info.id=(~0); 02010 list_info.id=(~0); 02011 state|=RedrawListState; 02012 /* 02013 Redraw color name & reply. 02014 */ 02015 *reply_info.text='\0'; 02016 reply_info.cursor=reply_info.text; 02017 (void) CopyMagickString(text_info.text,glob_pattern,MaxTextExtent); 02018 XDrawWidgetText(display,&windows->widget,&text_info); 02019 XDrawMatteText(display,&windows->widget,&reply_info); 02020 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 02021 XDrawTriangleNorth(display,&windows->widget,&north_info); 02022 XDrawBeveledButton(display,&windows->widget,&slider_info); 02023 XDrawTriangleSouth(display,&windows->widget,&south_info); 02024 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 02025 state&=(~UpdateListState); 02026 } 02027 if (state & JumpListState) 02028 { 02029 /* 02030 Jump scroll to match user color. 02031 */ 02032 list_info.id=(~0); 02033 for (i=0; i < (int) colors; i++) 02034 if (LocaleCompare(colorlist[i],reply) >= 0) 02035 { 02036 list_info.id=LocaleCompare(colorlist[i],reply) == 0 ? i : ~0; 02037 break; 02038 } 02039 if ((i < slider_info.id) || 02040 (i >= (int) (slider_info.id+visible_colors))) 02041 slider_info.id=i-(visible_colors >> 1); 02042 selection_info.id=(~0); 02043 state|=RedrawListState; 02044 state&=(~JumpListState); 02045 } 02046 if (state & RedrawListState) 02047 { 02048 /* 02049 Determine slider id and position. 02050 */ 02051 if (slider_info.id >= (int) (colors-visible_colors)) 02052 slider_info.id=(int) (colors-visible_colors); 02053 if ((slider_info.id < 0) || (colors <= visible_colors)) 02054 slider_info.id=0; 02055 slider_info.y=slider_info.min_y; 02056 if (colors != 0) 02057 slider_info.y+=(int) (slider_info.id*(slider_info.max_y- 02058 slider_info.min_y+1)/colors); 02059 if (slider_info.id != selection_info.id) 02060 { 02061 /* 02062 Redraw scroll bar and file names. 02063 */ 02064 selection_info.id=slider_info.id; 02065 selection_info.y=list_info.y+(height >> 3)+2; 02066 for (i=0; i < (int) visible_colors; i++) 02067 { 02068 selection_info.raised=(slider_info.id+i) != list_info.id ? 02069 MagickTrue : MagickFalse; 02070 selection_info.text=(char *) NULL; 02071 if ((slider_info.id+i) < (int) colors) 02072 selection_info.text=colorlist[slider_info.id+i]; 02073 XDrawWidgetText(display,&windows->widget,&selection_info); 02074 selection_info.y+=(int) selection_info.height; 02075 } 02076 /* 02077 Update slider. 02078 */ 02079 if (slider_info.y > expose_info.y) 02080 { 02081 expose_info.height=(unsigned int) slider_info.y-expose_info.y; 02082 expose_info.y=slider_info.y-expose_info.height- 02083 slider_info.bevel_width-1; 02084 } 02085 else 02086 { 02087 expose_info.height=(unsigned int) expose_info.y-slider_info.y; 02088 expose_info.y=slider_info.y+slider_info.height+ 02089 slider_info.bevel_width+1; 02090 } 02091 XDrawTriangleNorth(display,&windows->widget,&north_info); 02092 XDrawMatte(display,&windows->widget,&expose_info); 02093 XDrawBeveledButton(display,&windows->widget,&slider_info); 02094 XDrawTriangleSouth(display,&windows->widget,&south_info); 02095 expose_info.y=slider_info.y; 02096 } 02097 state&=(~RedrawListState); 02098 } 02099 if (state & RedrawActionState) 02100 { 02101 static char 02102 colorname[MaxTextExtent]; 02103 02104 /* 02105 Display the selected color in a drawing area. 02106 */ 02107 color=windows->widget.pixel_info->matte_color; 02108 (void) XParseColor(display,windows->widget.map_info->colormap, 02109 reply_info.text,&windows->widget.pixel_info->matte_color); 02110 XBestPixel(display,windows->widget.map_info->colormap,(XColor *) NULL, 02111 (unsigned int) windows->widget.visual_info->colormap_size, 02112 &windows->widget.pixel_info->matte_color); 02113 mode_info.text=colorname; 02114 (void) FormatLocaleString(mode_info.text,MaxTextExtent,"#%02x%02x%02x", 02115 windows->widget.pixel_info->matte_color.red, 02116 windows->widget.pixel_info->matte_color.green, 02117 windows->widget.pixel_info->matte_color.blue); 02118 XDrawBeveledButton(display,&windows->widget,&mode_info); 02119 windows->widget.pixel_info->matte_color=color; 02120 state&=(~RedrawActionState); 02121 } 02122 /* 02123 Wait for next event. 02124 */ 02125 if (north_info.raised && south_info.raised) 02126 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 02127 else 02128 { 02129 /* 02130 Brief delay before advancing scroll bar. 02131 */ 02132 XDelay(display,delay); 02133 delay=SuspendTime; 02134 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows); 02135 if (north_info.raised == MagickFalse) 02136 if (slider_info.id > 0) 02137 { 02138 /* 02139 Move slider up. 02140 */ 02141 slider_info.id--; 02142 state|=RedrawListState; 02143 } 02144 if (south_info.raised == MagickFalse) 02145 if (slider_info.id < (int) colors) 02146 { 02147 /* 02148 Move slider down. 02149 */ 02150 slider_info.id++; 02151 state|=RedrawListState; 02152 } 02153 if (event.type != ButtonRelease) 02154 continue; 02155 } 02156 switch (event.type) 02157 { 02158 case ButtonPress: 02159 { 02160 if (MatteIsActive(slider_info,event.xbutton)) 02161 { 02162 /* 02163 Track slider. 02164 */ 02165 slider_info.active=MagickTrue; 02166 break; 02167 } 02168 if (MatteIsActive(north_info,event.xbutton)) 02169 if (slider_info.id > 0) 02170 { 02171 /* 02172 Move slider up. 02173 */ 02174 north_info.raised=MagickFalse; 02175 slider_info.id--; 02176 state|=RedrawListState; 02177 break; 02178 } 02179 if (MatteIsActive(south_info,event.xbutton)) 02180 if (slider_info.id < (int) colors) 02181 { 02182 /* 02183 Move slider down. 02184 */ 02185 south_info.raised=MagickFalse; 02186 slider_info.id++; 02187 state|=RedrawListState; 02188 break; 02189 } 02190 if (MatteIsActive(scroll_info,event.xbutton)) 02191 { 02192 /* 02193 Move slider. 02194 */ 02195 if (event.xbutton.y < slider_info.y) 02196 slider_info.id-=(visible_colors-1); 02197 else 02198 slider_info.id+=(visible_colors-1); 02199 state|=RedrawListState; 02200 break; 02201 } 02202 if (MatteIsActive(list_info,event.xbutton)) 02203 { 02204 int 02205 id; 02206 02207 /* 02208 User pressed list matte. 02209 */ 02210 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/ 02211 selection_info.height; 02212 if (id >= (int) colors) 02213 break; 02214 (void) CopyMagickString(reply_info.text,colorlist[id], 02215 MaxTextExtent); 02216 reply_info.highlight=MagickFalse; 02217 reply_info.marker=reply_info.text; 02218 reply_info.cursor=reply_info.text+Extent(reply_info.text); 02219 XDrawMatteText(display,&windows->widget,&reply_info); 02220 state|=RedrawActionState; 02221 if (id == list_info.id) 02222 { 02223 (void) CopyMagickString(glob_pattern,reply_info.text, 02224 MaxTextExtent); 02225 state|=UpdateListState; 02226 } 02227 selection_info.id=(~0); 02228 list_info.id=id; 02229 state|=RedrawListState; 02230 break; 02231 } 02232 if (MatteIsActive(grab_info,event.xbutton)) 02233 { 02234 /* 02235 User pressed Grab button. 02236 */ 02237 grab_info.raised=MagickFalse; 02238 XDrawBeveledButton(display,&windows->widget,&grab_info); 02239 break; 02240 } 02241 if (MatteIsActive(reset_info,event.xbutton)) 02242 { 02243 /* 02244 User pressed Reset button. 02245 */ 02246 reset_info.raised=MagickFalse; 02247 XDrawBeveledButton(display,&windows->widget,&reset_info); 02248 break; 02249 } 02250 if (MatteIsActive(mode_info,event.xbutton)) 02251 { 02252 /* 02253 User pressed mode button. 02254 */ 02255 (void) CopyMagickString(reply_info.text,mode_info.text, 02256 MaxTextExtent); 02257 (void) CopyMagickString(primary_selection,reply_info.text, 02258 MaxTextExtent); 02259 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 02260 event.xbutton.time); 02261 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 02262 windows->widget.id ? MagickTrue : MagickFalse; 02263 reply_info.marker=reply_info.text; 02264 reply_info.cursor=reply_info.text+Extent(reply_info.text); 02265 XDrawMatteText(display,&windows->widget,&reply_info); 02266 break; 02267 } 02268 if (MatteIsActive(action_info,event.xbutton)) 02269 { 02270 /* 02271 User pressed action button. 02272 */ 02273 action_info.raised=MagickFalse; 02274 XDrawBeveledButton(display,&windows->widget,&action_info); 02275 break; 02276 } 02277 if (MatteIsActive(cancel_info,event.xbutton)) 02278 { 02279 /* 02280 User pressed Cancel button. 02281 */ 02282 cancel_info.raised=MagickFalse; 02283 XDrawBeveledButton(display,&windows->widget,&cancel_info); 02284 break; 02285 } 02286 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 02287 break; 02288 if (event.xbutton.button != Button2) 02289 { 02290 static Time 02291 click_time; 02292 02293 /* 02294 Move text cursor to position of button press. 02295 */ 02296 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2); 02297 for (i=1; i <= Extent(reply_info.marker); i++) 02298 if (XTextWidth(font_info,reply_info.marker,i) > x) 02299 break; 02300 reply_info.cursor=reply_info.marker+i-1; 02301 if (event.xbutton.time > (click_time+DoubleClick)) 02302 reply_info.highlight=MagickFalse; 02303 else 02304 { 02305 /* 02306 Become the XA_PRIMARY selection owner. 02307 */ 02308 (void) CopyMagickString(primary_selection,reply_info.text, 02309 MaxTextExtent); 02310 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 02311 event.xbutton.time); 02312 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 02313 windows->widget.id ? MagickTrue : MagickFalse; 02314 } 02315 XDrawMatteText(display,&windows->widget,&reply_info); 02316 click_time=event.xbutton.time; 02317 break; 02318 } 02319 /* 02320 Request primary selection. 02321 */ 02322 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, 02323 windows->widget.id,event.xbutton.time); 02324 break; 02325 } 02326 case ButtonRelease: 02327 { 02328 if (windows->widget.mapped == MagickFalse) 02329 break; 02330 if (north_info.raised == MagickFalse) 02331 { 02332 /* 02333 User released up button. 02334 */ 02335 delay=SuspendTime << 2; 02336 north_info.raised=MagickTrue; 02337 XDrawTriangleNorth(display,&windows->widget,&north_info); 02338 } 02339 if (south_info.raised == MagickFalse) 02340 { 02341 /* 02342 User released down button. 02343 */ 02344 delay=SuspendTime << 2; 02345 south_info.raised=MagickTrue; 02346 XDrawTriangleSouth(display,&windows->widget,&south_info); 02347 } 02348 if (slider_info.active) 02349 { 02350 /* 02351 Stop tracking slider. 02352 */ 02353 slider_info.active=MagickFalse; 02354 break; 02355 } 02356 if (grab_info.raised == MagickFalse) 02357 { 02358 if (event.xbutton.window == windows->widget.id) 02359 if (MatteIsActive(grab_info,event.xbutton)) 02360 { 02361 /* 02362 Select a fill color from the X server. 02363 */ 02364 (void) XGetWindowColor(display,windows,reply_info.text, 02365 exception); 02366 reply_info.marker=reply_info.text; 02367 reply_info.cursor=reply_info.text+Extent(reply_info.text); 02368 XDrawMatteText(display,&windows->widget,&reply_info); 02369 state|=RedrawActionState; 02370 } 02371 grab_info.raised=MagickTrue; 02372 XDrawBeveledButton(display,&windows->widget,&grab_info); 02373 } 02374 if (reset_info.raised == MagickFalse) 02375 { 02376 if (event.xbutton.window == windows->widget.id) 02377 if (MatteIsActive(reset_info,event.xbutton)) 02378 { 02379 (void) CopyMagickString(glob_pattern,reset_pattern, 02380 MaxTextExtent); 02381 state|=UpdateListState; 02382 } 02383 reset_info.raised=MagickTrue; 02384 XDrawBeveledButton(display,&windows->widget,&reset_info); 02385 } 02386 if (action_info.raised == MagickFalse) 02387 { 02388 if (event.xbutton.window == windows->widget.id) 02389 { 02390 if (MatteIsActive(action_info,event.xbutton)) 02391 { 02392 if (*reply_info.text == '\0') 02393 (void) XBell(display,0); 02394 else 02395 state|=ExitState; 02396 } 02397 } 02398 action_info.raised=MagickTrue; 02399 XDrawBeveledButton(display,&windows->widget,&action_info); 02400 } 02401 if (cancel_info.raised == MagickFalse) 02402 { 02403 if (event.xbutton.window == windows->widget.id) 02404 if (MatteIsActive(cancel_info,event.xbutton)) 02405 { 02406 *reply_info.text='\0'; 02407 state|=ExitState; 02408 } 02409 cancel_info.raised=MagickTrue; 02410 XDrawBeveledButton(display,&windows->widget,&cancel_info); 02411 } 02412 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 02413 break; 02414 break; 02415 } 02416 case ClientMessage: 02417 { 02418 /* 02419 If client window delete message, exit. 02420 */ 02421 if (event.xclient.message_type != windows->wm_protocols) 02422 break; 02423 if (*event.xclient.data.l == (int) windows->wm_take_focus) 02424 { 02425 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 02426 (Time) event.xclient.data.l[1]); 02427 break; 02428 } 02429 if (*event.xclient.data.l != (int) windows->wm_delete_window) 02430 break; 02431 if (event.xclient.window == windows->widget.id) 02432 { 02433 *reply_info.text='\0'; 02434 state|=ExitState; 02435 break; 02436 } 02437 break; 02438 } 02439 case ConfigureNotify: 02440 { 02441 /* 02442 Update widget configuration. 02443 */ 02444 if (event.xconfigure.window != windows->widget.id) 02445 break; 02446 if ((event.xconfigure.width == (int) windows->widget.width) && 02447 (event.xconfigure.height == (int) windows->widget.height)) 02448 break; 02449 windows->widget.width=(unsigned int) 02450 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 02451 windows->widget.height=(unsigned int) 02452 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 02453 state|=UpdateConfigurationState; 02454 break; 02455 } 02456 case EnterNotify: 02457 { 02458 if (event.xcrossing.window != windows->widget.id) 02459 break; 02460 state&=(~InactiveWidgetState); 02461 break; 02462 } 02463 case Expose: 02464 { 02465 if (event.xexpose.window != windows->widget.id) 02466 break; 02467 if (event.xexpose.count != 0) 02468 break; 02469 state|=RedrawWidgetState; 02470 break; 02471 } 02472 case KeyPress: 02473 { 02474 static char 02475 command[MaxTextExtent]; 02476 02477 static int 02478 length; 02479 02480 static KeySym 02481 key_symbol; 02482 02483 /* 02484 Respond to a user key press. 02485 */ 02486 if (event.xkey.window != windows->widget.id) 02487 break; 02488 length=XLookupString((XKeyEvent *) &event.xkey,command, 02489 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 02490 *(command+length)='\0'; 02491 if (AreaIsActive(scroll_info,event.xkey)) 02492 { 02493 /* 02494 Move slider. 02495 */ 02496 switch ((int) key_symbol) 02497 { 02498 case XK_Home: 02499 case XK_KP_Home: 02500 { 02501 slider_info.id=0; 02502 break; 02503 } 02504 case XK_Up: 02505 case XK_KP_Up: 02506 { 02507 slider_info.id--; 02508 break; 02509 } 02510 case XK_Down: 02511 case XK_KP_Down: 02512 { 02513 slider_info.id++; 02514 break; 02515 } 02516 case XK_Prior: 02517 case XK_KP_Prior: 02518 { 02519 slider_info.id-=visible_colors; 02520 break; 02521 } 02522 case XK_Next: 02523 case XK_KP_Next: 02524 { 02525 slider_info.id+=visible_colors; 02526 break; 02527 } 02528 case XK_End: 02529 case XK_KP_End: 02530 { 02531 slider_info.id=(int) colors; 02532 break; 02533 } 02534 } 02535 state|=RedrawListState; 02536 break; 02537 } 02538 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 02539 { 02540 /* 02541 Read new color or glob patterm. 02542 */ 02543 if (*reply_info.text == '\0') 02544 break; 02545 (void) CopyMagickString(glob_pattern,reply_info.text,MaxTextExtent); 02546 state|=UpdateListState; 02547 break; 02548 } 02549 if (key_symbol == XK_Control_L) 02550 { 02551 state|=ControlState; 02552 break; 02553 } 02554 if (state & ControlState) 02555 switch ((int) key_symbol) 02556 { 02557 case XK_u: 02558 case XK_U: 02559 { 02560 /* 02561 Erase the entire line of text. 02562 */ 02563 *reply_info.text='\0'; 02564 reply_info.cursor=reply_info.text; 02565 reply_info.marker=reply_info.text; 02566 reply_info.highlight=MagickFalse; 02567 break; 02568 } 02569 default: 02570 break; 02571 } 02572 XEditText(display,&reply_info,key_symbol,command,state); 02573 XDrawMatteText(display,&windows->widget,&reply_info); 02574 state|=JumpListState; 02575 status=XParseColor(display,windows->widget.map_info->colormap, 02576 reply_info.text,&color); 02577 if (status != False) 02578 state|=RedrawActionState; 02579 break; 02580 } 02581 case KeyRelease: 02582 { 02583 static char 02584 command[MaxTextExtent]; 02585 02586 static KeySym 02587 key_symbol; 02588 02589 /* 02590 Respond to a user key release. 02591 */ 02592 if (event.xkey.window != windows->widget.id) 02593 break; 02594 (void) XLookupString((XKeyEvent *) &event.xkey,command, 02595 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 02596 if (key_symbol == XK_Control_L) 02597 state&=(~ControlState); 02598 break; 02599 } 02600 case LeaveNotify: 02601 { 02602 if (event.xcrossing.window != windows->widget.id) 02603 break; 02604 state|=InactiveWidgetState; 02605 break; 02606 } 02607 case MapNotify: 02608 { 02609 mask&=(~CWX); 02610 mask&=(~CWY); 02611 break; 02612 } 02613 case MotionNotify: 02614 { 02615 /* 02616 Discard pending button motion events. 02617 */ 02618 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 02619 if (slider_info.active) 02620 { 02621 /* 02622 Move slider matte. 02623 */ 02624 slider_info.y=event.xmotion.y- 02625 ((slider_info.height+slider_info.bevel_width) >> 1)+1; 02626 if (slider_info.y < slider_info.min_y) 02627 slider_info.y=slider_info.min_y; 02628 if (slider_info.y > slider_info.max_y) 02629 slider_info.y=slider_info.max_y; 02630 slider_info.id=0; 02631 if (slider_info.y != slider_info.min_y) 02632 slider_info.id=(int) ((colors*(slider_info.y- 02633 slider_info.min_y+1))/(slider_info.max_y-slider_info.min_y+1)); 02634 state|=RedrawListState; 02635 break; 02636 } 02637 if (state & InactiveWidgetState) 02638 break; 02639 if (grab_info.raised == MatteIsActive(grab_info,event.xmotion)) 02640 { 02641 /* 02642 Grab button status changed. 02643 */ 02644 grab_info.raised=!grab_info.raised; 02645 XDrawBeveledButton(display,&windows->widget,&grab_info); 02646 break; 02647 } 02648 if (reset_info.raised == MatteIsActive(reset_info,event.xmotion)) 02649 { 02650 /* 02651 Reset button status changed. 02652 */ 02653 reset_info.raised=!reset_info.raised; 02654 XDrawBeveledButton(display,&windows->widget,&reset_info); 02655 break; 02656 } 02657 if (action_info.raised == MatteIsActive(action_info,event.xmotion)) 02658 { 02659 /* 02660 Action button status changed. 02661 */ 02662 action_info.raised=action_info.raised == MagickFalse ? 02663 MagickTrue : MagickFalse; 02664 XDrawBeveledButton(display,&windows->widget,&action_info); 02665 break; 02666 } 02667 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 02668 { 02669 /* 02670 Cancel button status changed. 02671 */ 02672 cancel_info.raised=cancel_info.raised == MagickFalse ? 02673 MagickTrue : MagickFalse; 02674 XDrawBeveledButton(display,&windows->widget,&cancel_info); 02675 break; 02676 } 02677 break; 02678 } 02679 case SelectionClear: 02680 { 02681 reply_info.highlight=MagickFalse; 02682 XDrawMatteText(display,&windows->widget,&reply_info); 02683 break; 02684 } 02685 case SelectionNotify: 02686 { 02687 Atom 02688 type; 02689 02690 int 02691 format; 02692 02693 unsigned char 02694 *data; 02695 02696 unsigned long 02697 after, 02698 length; 02699 02700 /* 02701 Obtain response from primary selection. 02702 */ 02703 if (event.xselection.property == (Atom) None) 02704 break; 02705 status=XGetWindowProperty(display,event.xselection.requestor, 02706 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type, 02707 &format,&length,&after,&data); 02708 if ((status != Success) || (type != XA_STRING) || (format == 32) || 02709 (length == 0)) 02710 break; 02711 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1)) 02712 (void) XBell(display,0); 02713 else 02714 { 02715 /* 02716 Insert primary selection in reply text. 02717 */ 02718 *(data+length)='\0'; 02719 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data, 02720 state); 02721 XDrawMatteText(display,&windows->widget,&reply_info); 02722 state|=JumpListState; 02723 state|=RedrawActionState; 02724 } 02725 (void) XFree((void *) data); 02726 break; 02727 } 02728 case SelectionRequest: 02729 { 02730 XSelectionEvent 02731 notify; 02732 02733 XSelectionRequestEvent 02734 *request; 02735 02736 if (reply_info.highlight == MagickFalse) 02737 break; 02738 /* 02739 Set primary selection. 02740 */ 02741 request=(&(event.xselectionrequest)); 02742 (void) XChangeProperty(request->display,request->requestor, 02743 request->property,request->target,8,PropModeReplace, 02744 (unsigned char *) primary_selection,Extent(primary_selection)); 02745 notify.type=SelectionNotify; 02746 notify.send_event=MagickTrue; 02747 notify.display=request->display; 02748 notify.requestor=request->requestor; 02749 notify.selection=request->selection; 02750 notify.target=request->target; 02751 notify.time=request->time; 02752 if (request->property == None) 02753 notify.property=request->target; 02754 else 02755 notify.property=request->property; 02756 (void) XSendEvent(request->display,request->requestor,False, 02757 NoEventMask,(XEvent *) ¬ify); 02758 } 02759 default: 02760 break; 02761 } 02762 } while ((state & ExitState) == 0); 02763 XSetCursorState(display,windows,MagickFalse); 02764 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 02765 XCheckRefreshWindows(display,windows); 02766 /* 02767 Free color list. 02768 */ 02769 for (i=0; i < (int) colors; i++) 02770 colorlist[i]=DestroyString(colorlist[i]); 02771 if (colorlist != (char **) NULL) 02772 colorlist=(char **) RelinquishMagickMemory(colorlist); 02773 exception=DestroyExceptionInfo(exception); 02774 if ((*reply == '\0') || (strchr(reply,'-') != (char *) NULL)) 02775 return; 02776 status=XParseColor(display,windows->widget.map_info->colormap,reply,&color); 02777 if (status != False) 02778 return; 02779 XNoticeWidget(display,windows,"Color is unknown to X server:",reply); 02780 (void) CopyMagickString(reply,"gray",MaxTextExtent); 02781 } 02782 02783 /* 02784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02785 % % 02786 % % 02787 % % 02788 % X C o m m a n d W i d g e t % 02789 % % 02790 % % 02791 % % 02792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02793 % 02794 % XCommandWidget() maps a menu and returns the command pointed to by the user 02795 % when the button is released. 02796 % 02797 % The format of the XCommandWidget method is: 02798 % 02799 % int XCommandWidget(Display *display,XWindows *windows, 02800 % const char **selections,XEvent *event) 02801 % 02802 % A description of each parameter follows: 02803 % 02804 % o selection_number: Specifies the number of the selection that the 02805 % user choose. 02806 % 02807 % o display: Specifies a connection to an X server; returned from 02808 % XOpenDisplay. 02809 % 02810 % o window: Specifies a pointer to a XWindows structure. 02811 % 02812 % o selections: Specifies a pointer to one or more strings that comprise 02813 % the choices in the menu. 02814 % 02815 % o event: Specifies a pointer to a X11 XEvent structure. 02816 % 02817 */ 02818 MagickPrivate int XCommandWidget(Display *display,XWindows *windows, 02819 const char **selections,XEvent *event) 02820 { 02821 #define tile_width 112 02822 #define tile_height 70 02823 02824 static const unsigned char 02825 tile_bits[]= 02826 { 02827 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02828 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02829 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 02831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 02832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 02833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02834 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02835 0x00, 0x00, 0x1e, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02836 0x00, 0x00, 0x00, 0x00, 0x1e, 0xbc, 0x9f, 0x03, 0x00, 0x3e, 0x00, 0xc0, 02837 0x1f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x0f, 0x80, 0x3f, 02838 0x00, 0xf0, 0x1f, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0x1f, 02839 0xe0, 0x3f, 0x00, 0xfc, 0x1f, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0xfc, 02840 0xff, 0x1f, 0xf0, 0x3f, 0x00, 0xfe, 0x1f, 0xf8, 0x0f, 0x00, 0x00, 0x00, 02841 0x1e, 0xfc, 0xfc, 0x3f, 0xf8, 0x3f, 0x00, 0xff, 0x1e, 0xfc, 0x0f, 0x00, 02842 0x00, 0x00, 0x1e, 0x7c, 0xfc, 0x3e, 0xf8, 0x3c, 0x80, 0x1f, 0x1e, 0x7c, 02843 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 0xc0, 0x0f, 02844 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 0x7c, 0x3c, 02845 0xc0, 0x07, 0x1e, 0x3e, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x78, 0x78, 0x3c, 02846 0x7c, 0x7c, 0xc0, 0x0f, 0x1e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x78, 02847 0x78, 0x3c, 0xfc, 0x7c, 0x80, 0x7f, 0x1e, 0x7c, 0x00, 0x00, 0x00, 0x00, 02848 0x1e, 0xf8, 0x78, 0x7c, 0xf8, 0xff, 0x00, 0xff, 0x1f, 0xf8, 0xff, 0x00, 02849 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xfe, 0x1f, 0xf8, 02850 0xff, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xf0, 0xff, 0x07, 0xf8, 02851 0x1f, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0xf8, 0x78, 0x7c, 0xc0, 0xef, 02852 0x07, 0xe0, 0x1f, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x1e, 0x70, 0x40, 0x78, 02853 0x00, 0xc7, 0x07, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00, 02854 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 02855 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 02856 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 02857 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 02858 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02859 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02860 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02861 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 02862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 02863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 02864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 02865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02866 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00, 02867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 02868 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02869 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02870 0x60, 0x00, 0xc0, 0x0f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02871 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 02872 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc0, 0x8f, 0x3f, 0x00, 0x00, 0x00, 02873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0x9f, 0x7f, 0x00, 02874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xe0, 0xdf, 02875 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 02876 0xe0, 0xdf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0c, 02877 0x78, 0x30, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 02878 0x00, 0x0f, 0xf8, 0x70, 0xf0, 0xff, 0x7b, 0x00, 0x00, 0x1f, 0x00, 0xe0, 02879 0x0f, 0x1e, 0x80, 0x0f, 0xf8, 0x78, 0xf0, 0xfd, 0xf9, 0x00, 0xc0, 0x1f, 02880 0x00, 0xf8, 0x0f, 0x00, 0xe0, 0x1f, 0xf8, 0x7c, 0xf0, 0xfc, 0xf9, 0x00, 02881 0xf0, 0x1f, 0x00, 0xfe, 0x0f, 0x00, 0xf0, 0x07, 0xf8, 0x3e, 0xf8, 0xfc, 02882 0xf0, 0x01, 0xf8, 0x1f, 0x00, 0xff, 0x0f, 0x1e, 0xf0, 0x03, 0xf8, 0x3f, 02883 0xf8, 0xf8, 0xf0, 0x01, 0xfc, 0x1f, 0x80, 0x7f, 0x0f, 0x1e, 0xf8, 0x00, 02884 0xf8, 0x1f, 0x78, 0x18, 0xf0, 0x01, 0x7c, 0x1e, 0xc0, 0x0f, 0x0f, 0x1e, 02885 0x7c, 0x00, 0xf0, 0x0f, 0x78, 0x00, 0xf0, 0x01, 0x3e, 0x1e, 0xe0, 0x07, 02886 0x0f, 0x1e, 0x7c, 0x00, 0xf0, 0x07, 0x7c, 0x00, 0xe0, 0x01, 0x3e, 0x1e, 02887 0xe0, 0x03, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x0f, 0x7c, 0x00, 0xe0, 0x03, 02888 0x3e, 0x3e, 0xe0, 0x07, 0x0f, 0x1e, 0x1e, 0x00, 0xf0, 0x1f, 0x3c, 0x00, 02889 0xe0, 0x03, 0x7e, 0x3e, 0xc0, 0x3f, 0x0f, 0x1e, 0x3e, 0x00, 0xf0, 0x1f, 02890 0x3e, 0x00, 0xe0, 0x03, 0xfc, 0x7f, 0x80, 0xff, 0x0f, 0x1e, 0xfc, 0x00, 02891 0xf0, 0x3e, 0x3e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xff, 0x0f, 0x1e, 02892 0xfc, 0x07, 0xf0, 0x7c, 0x1e, 0x00, 0xc0, 0x03, 0xf8, 0xff, 0x03, 0xfc, 02893 0x0f, 0x1e, 0xf8, 0x1f, 0xf0, 0xf8, 0x1e, 0x00, 0xc0, 0x03, 0xe0, 0xf7, 02894 0x03, 0xf0, 0x0f, 0x1e, 0xe0, 0x3f, 0xf0, 0x78, 0x1c, 0x00, 0x80, 0x03, 02895 0x80, 0xe3, 0x03, 0x00, 0x0f, 0x1e, 0xc0, 0x3f, 0xf0, 0x30, 0x00, 0x00, 02896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0x3e, 0x00, 0x00, 02897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x10, 02898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 02899 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 02900 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02901 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02902 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02903 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 02904 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 02905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 02906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 02907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 02908 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 02909 }; 02910 02911 int 02912 id, 02913 y; 02914 02915 register int 02916 i; 02917 02918 static unsigned int 02919 number_selections; 02920 02921 unsigned int 02922 height; 02923 02924 size_t 02925 state; 02926 02927 XFontStruct 02928 *font_info; 02929 02930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 02931 assert(display != (Display *) NULL); 02932 assert(windows != (XWindows *) NULL); 02933 font_info=windows->command.font_info; 02934 height=(unsigned int) (font_info->ascent+font_info->descent); 02935 id=(~0); 02936 state=DefaultState; 02937 if (event == (XEvent *) NULL) 02938 { 02939 unsigned int 02940 width; 02941 02942 XTextProperty 02943 window_name; 02944 02945 XWindowChanges 02946 window_changes; 02947 02948 /* 02949 Determine command window attributes. 02950 */ 02951 assert(selections != (const char **) NULL); 02952 windows->command.width=0; 02953 for (i=0; selections[i] != (char *) NULL; i++) 02954 { 02955 width=WidgetTextWidth(font_info,(char *) selections[i]); 02956 if (width > windows->command.width) 02957 windows->command.width=width; 02958 } 02959 number_selections=(unsigned int) i; 02960 windows->command.width+=3*QuantumMargin+10; 02961 if ((int) windows->command.width < (tile_width+QuantumMargin+10)) 02962 windows->command.width=(unsigned int) (tile_width+QuantumMargin+10); 02963 windows->command.height=(unsigned int) (number_selections* 02964 (((3*height) >> 1)+10)+tile_height+20); 02965 windows->command.min_width=windows->command.width; 02966 windows->command.min_height=windows->command.height; 02967 XConstrainWindowPosition(display,&windows->command); 02968 if (windows->command.id != (Window) NULL) 02969 { 02970 Status 02971 status; 02972 02973 /* 02974 Reconfigure command window. 02975 */ 02976 status=XStringListToTextProperty(&windows->command.name,1, 02977 &window_name); 02978 if (status != False) 02979 { 02980 XSetWMName(display,windows->command.id,&window_name); 02981 XSetWMIconName(display,windows->command.id,&window_name); 02982 (void) XFree((void *) window_name.value); 02983 } 02984 window_changes.width=(int) windows->command.width; 02985 window_changes.height=(int) windows->command.height; 02986 (void) XReconfigureWMWindow(display,windows->command.id, 02987 windows->command.screen,(unsigned int) (CWWidth | CWHeight), 02988 &window_changes); 02989 } 02990 /* 02991 Allocate selection info memory. 02992 */ 02993 if (selection_info != (XWidgetInfo *) NULL) 02994 selection_info=(XWidgetInfo *) RelinquishMagickMemory(selection_info); 02995 selection_info=(XWidgetInfo *) AcquireQuantumMemory(number_selections, 02996 sizeof(*selection_info)); 02997 if (selection_info == (XWidgetInfo *) NULL) 02998 { 02999 ThrowXWindowFatalException(ResourceLimitError, 03000 "MemoryAllocationFailed","..."); 03001 return(id); 03002 } 03003 state|=UpdateConfigurationState | RedrawWidgetState; 03004 } 03005 /* 03006 Wait for next event. 03007 */ 03008 if (event != (XEvent *) NULL) 03009 switch (event->type) 03010 { 03011 case ButtonPress: 03012 { 03013 for (i=0; i < (int) number_selections; i++) 03014 { 03015 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse) 03016 continue; 03017 if (i >= (int) windows->command.data) 03018 { 03019 selection_info[i].raised=MagickFalse; 03020 XDrawBeveledButton(display,&windows->command,&selection_info[i]); 03021 break; 03022 } 03023 submenu_info=selection_info[i]; 03024 submenu_info.active=MagickTrue; 03025 toggle_info.y= 03026 submenu_info.y+(submenu_info.height >> 1)-(toggle_info.height >> 1); 03027 id=i; 03028 (void) XCheckWindowEvent(display,windows->widget.id,LeaveWindowMask, 03029 event); 03030 break; 03031 } 03032 break; 03033 } 03034 case ButtonRelease: 03035 { 03036 for (i=0; i < (int) number_selections; i++) 03037 { 03038 if (MatteIsActive(selection_info[i],event->xbutton) == MagickFalse) 03039 continue; 03040 id=i; 03041 if (id >= (int) windows->command.data) 03042 { 03043 selection_info[id].raised=MagickTrue; 03044 XDrawBeveledButton(display,&windows->command,&selection_info[id]); 03045 break; 03046 } 03047 break; 03048 } 03049 break; 03050 } 03051 case ClientMessage: 03052 { 03053 /* 03054 If client window delete message, withdraw command widget. 03055 */ 03056 if (event->xclient.message_type != windows->wm_protocols) 03057 break; 03058 if (*event->xclient.data.l != (int) windows->wm_delete_window) 03059 break; 03060 (void) XWithdrawWindow(display,windows->command.id, 03061 windows->command.screen); 03062 break; 03063 } 03064 case ConfigureNotify: 03065 { 03066 /* 03067 Update widget configuration. 03068 */ 03069 if (event->xconfigure.window != windows->command.id) 03070 break; 03071 if (event->xconfigure.send_event != 0) 03072 { 03073 windows->command.x=event->xconfigure.x; 03074 windows->command.y=event->xconfigure.y; 03075 } 03076 if ((event->xconfigure.width == (int) windows->command.width) && 03077 (event->xconfigure.height == (int) windows->command.height)) 03078 break; 03079 windows->command.width=(unsigned int) 03080 MagickMax(event->xconfigure.width,(int) windows->command.min_width); 03081 windows->command.height=(unsigned int) 03082 MagickMax(event->xconfigure.height,(int) windows->command.min_height); 03083 state|=UpdateConfigurationState; 03084 break; 03085 } 03086 case Expose: 03087 { 03088 if (event->xexpose.window != windows->command.id) 03089 break; 03090 if (event->xexpose.count != 0) 03091 break; 03092 state|=RedrawWidgetState; 03093 break; 03094 } 03095 case MotionNotify: 03096 { 03097 /* 03098 Return the ID of the highlighted menu entry. 03099 */ 03100 for ( ; ; ) 03101 { 03102 for (i=0; i < (int) number_selections; i++) 03103 { 03104 if (i >= (int) windows->command.data) 03105 { 03106 if (selection_info[i].raised == 03107 MatteIsActive(selection_info[i],event->xmotion)) 03108 { 03109 /* 03110 Button status changed. 03111 */ 03112 selection_info[i].raised=!selection_info[i].raised; 03113 XDrawBeveledButton(display,&windows->command, 03114 &selection_info[i]); 03115 } 03116 continue; 03117 } 03118 if (MatteIsActive(selection_info[i],event->xmotion) == MagickFalse) 03119 continue; 03120 submenu_info=selection_info[i]; 03121 submenu_info.active=MagickTrue; 03122 toggle_info.raised=MagickTrue; 03123 toggle_info.y=submenu_info.y+(submenu_info.height >> 1)- 03124 (toggle_info.height >> 1); 03125 XDrawTriangleEast(display,&windows->command,&toggle_info); 03126 id=i; 03127 } 03128 XDelay(display,SuspendTime); 03129 if (XCheckMaskEvent(display,ButtonMotionMask,event) == MagickFalse) 03130 break; 03131 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ; 03132 toggle_info.raised=MagickFalse; 03133 if (windows->command.data != 0) 03134 XDrawTriangleEast(display,&windows->command,&toggle_info); 03135 } 03136 break; 03137 } 03138 case MapNotify: 03139 { 03140 windows->command.mapped=MagickTrue; 03141 break; 03142 } 03143 case UnmapNotify: 03144 { 03145 windows->command.mapped=MagickFalse; 03146 break; 03147 } 03148 default: 03149 break; 03150 } 03151 if (state & UpdateConfigurationState) 03152 { 03153 /* 03154 Initialize button information. 03155 */ 03156 assert(selections != (const char **) NULL); 03157 y=tile_height+20; 03158 for (i=0; i < (int) number_selections; i++) 03159 { 03160 XGetWidgetInfo(selections[i],&selection_info[i]); 03161 selection_info[i].center=MagickFalse; 03162 selection_info[i].bevel_width--; 03163 selection_info[i].height=(unsigned int) ((3*height) >> 1); 03164 selection_info[i].x=(QuantumMargin >> 1)+4; 03165 selection_info[i].width=(unsigned int) 03166 (windows->command.width-(selection_info[i].x << 1)); 03167 selection_info[i].y=y; 03168 y+=selection_info[i].height+(selection_info[i].bevel_width << 1)+6; 03169 } 03170 XGetWidgetInfo((char *) NULL,&toggle_info); 03171 toggle_info.bevel_width--; 03172 toggle_info.width=(unsigned int) 03173 (((5*height) >> 3)-(toggle_info.bevel_width << 1)); 03174 toggle_info.height=toggle_info.width; 03175 toggle_info.x=selection_info[0].x+selection_info[0].width- 03176 toggle_info.width-(QuantumMargin >> 1); 03177 if (windows->command.mapped) 03178 (void) XClearWindow(display,windows->command.id); 03179 } 03180 if (state & RedrawWidgetState) 03181 { 03182 Pixmap 03183 tile_pixmap; 03184 03185 /* 03186 Draw command buttons. 03187 */ 03188 tile_pixmap=XCreatePixmapFromBitmapData(display,windows->command.id, 03189 (char *) tile_bits,tile_width,tile_height,1L,0L,1); 03190 if (tile_pixmap != (Pixmap) NULL) 03191 { 03192 (void) XCopyPlane(display,tile_pixmap,windows->command.id, 03193 windows->command.annotate_context,0,0,tile_width,tile_height, 03194 (int) ((windows->command.width-tile_width) >> 1),10,1L); 03195 (void) XFreePixmap(display,tile_pixmap); 03196 } 03197 for (i=0; i < (int) number_selections; i++) 03198 { 03199 XDrawBeveledButton(display,&windows->command,&selection_info[i]); 03200 if (i >= (int) windows->command.data) 03201 continue; 03202 toggle_info.raised=i == id ? MagickTrue : MagickFalse; 03203 toggle_info.y=selection_info[i].y+ 03204 (selection_info[i].height >> 1)-(toggle_info.height >> 1); 03205 XDrawTriangleEast(display,&windows->command,&toggle_info); 03206 } 03207 XHighlightWidget(display,&windows->command,BorderOffset,BorderOffset); 03208 } 03209 return(id); 03210 } 03211 03212 /* 03213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03214 % % 03215 % % 03216 % % 03217 % X C o n f i r m W i d g e t % 03218 % % 03219 % % 03220 % % 03221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03222 % 03223 % XConfirmWidget() displays a Confirm widget with a notice to the user. The 03224 % function returns -1 if Dismiss is pressed, 0 for Cancel, and 1 for Yes. 03225 % 03226 % The format of the XConfirmWidget method is: 03227 % 03228 % int XConfirmWidget(Display *display,XWindows *windows, 03229 % const char *reason,const char *description) 03230 % 03231 % A description of each parameter follows: 03232 % 03233 % o display: Specifies a connection to an X server; returned from 03234 % XOpenDisplay. 03235 % 03236 % o window: Specifies a pointer to a XWindows structure. 03237 % 03238 % o reason: Specifies the message to display before terminating the 03239 % program. 03240 % 03241 % o description: Specifies any description to the message. 03242 % 03243 */ 03244 MagickPrivate int XConfirmWidget(Display *display,XWindows *windows, 03245 const char *reason,const char *description) 03246 { 03247 #define CancelButtonText "Cancel" 03248 #define DismissButtonText "Dismiss" 03249 #define YesButtonText "Yes" 03250 03251 int 03252 confirm, 03253 x, 03254 y; 03255 03256 Status 03257 status; 03258 03259 unsigned int 03260 height, 03261 width; 03262 03263 size_t 03264 state; 03265 03266 XEvent 03267 event; 03268 03269 XFontStruct 03270 *font_info; 03271 03272 XTextProperty 03273 window_name; 03274 03275 XWidgetInfo 03276 cancel_info, 03277 dismiss_info, 03278 yes_info; 03279 03280 XWindowChanges 03281 window_changes; 03282 03283 /* 03284 Determine Confirm widget attributes. 03285 */ 03286 assert(display != (Display *) NULL); 03287 assert(windows != (XWindows *) NULL); 03288 assert(reason != (char *) NULL); 03289 assert(description != (char *) NULL); 03290 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",reason); 03291 XCheckRefreshWindows(display,windows); 03292 font_info=windows->widget.font_info; 03293 width=WidgetTextWidth(font_info,CancelButtonText); 03294 if (WidgetTextWidth(font_info,DismissButtonText) > width) 03295 width=WidgetTextWidth(font_info,DismissButtonText); 03296 if (WidgetTextWidth(font_info,YesButtonText) > width) 03297 width=WidgetTextWidth(font_info,YesButtonText); 03298 width<<=1; 03299 if (description != (char *) NULL) 03300 if (WidgetTextWidth(font_info,(char *) description) > width) 03301 width=WidgetTextWidth(font_info,(char *) description); 03302 height=(unsigned int) (font_info->ascent+font_info->descent); 03303 /* 03304 Position Confirm widget. 03305 */ 03306 windows->widget.width=(unsigned int) (width+9*QuantumMargin); 03307 windows->widget.min_width=(unsigned int) (9*QuantumMargin+ 03308 WidgetTextWidth(font_info,CancelButtonText)+ 03309 WidgetTextWidth(font_info,DismissButtonText)+ 03310 WidgetTextWidth(font_info,YesButtonText)); 03311 if (windows->widget.width < windows->widget.min_width) 03312 windows->widget.width=windows->widget.min_width; 03313 windows->widget.height=(unsigned int) (12*height); 03314 windows->widget.min_height=(unsigned int) (7*height); 03315 if (windows->widget.height < windows->widget.min_height) 03316 windows->widget.height=windows->widget.min_height; 03317 XConstrainWindowPosition(display,&windows->widget); 03318 /* 03319 Map Confirm widget. 03320 */ 03321 (void) CopyMagickString(windows->widget.name,"Confirm",MaxTextExtent); 03322 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 03323 if (status != False) 03324 { 03325 XSetWMName(display,windows->widget.id,&window_name); 03326 XSetWMIconName(display,windows->widget.id,&window_name); 03327 (void) XFree((void *) window_name.value); 03328 } 03329 window_changes.width=(int) windows->widget.width; 03330 window_changes.height=(int) windows->widget.height; 03331 window_changes.x=windows->widget.x; 03332 window_changes.y=windows->widget.y; 03333 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 03334 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes); 03335 (void) XMapRaised(display,windows->widget.id); 03336 windows->widget.mapped=MagickFalse; 03337 /* 03338 Respond to X events. 03339 */ 03340 confirm=0; 03341 state=UpdateConfigurationState; 03342 XSetCursorState(display,windows,MagickTrue); 03343 do 03344 { 03345 if (state & UpdateConfigurationState) 03346 { 03347 /* 03348 Initialize button information. 03349 */ 03350 XGetWidgetInfo(CancelButtonText,&cancel_info); 03351 cancel_info.width=(unsigned int) QuantumMargin+ 03352 WidgetTextWidth(font_info,CancelButtonText); 03353 cancel_info.height=(unsigned int) ((3*height) >> 1); 03354 cancel_info.x=(int) (windows->widget.width-cancel_info.width- 03355 QuantumMargin); 03356 cancel_info.y=(int) (windows->widget.height-(cancel_info.height << 1)); 03357 dismiss_info=cancel_info; 03358 dismiss_info.text=(char *) DismissButtonText; 03359 if (LocaleCompare(description,"Do you want to save it") == 0) 03360 dismiss_info.text=(char *) "Don't Save"; 03361 dismiss_info.width=(unsigned int) QuantumMargin+ 03362 WidgetTextWidth(font_info,dismiss_info.text); 03363 dismiss_info.x=(int) 03364 ((windows->widget.width >> 1)-(dismiss_info.width >> 1)); 03365 yes_info=cancel_info; 03366 yes_info.text=(char *) YesButtonText; 03367 if (LocaleCompare(description,"Do you want to save it") == 0) 03368 yes_info.text=(char *) "Save"; 03369 yes_info.width=(unsigned int) QuantumMargin+ 03370 WidgetTextWidth(font_info,yes_info.text); 03371 if (yes_info.width < cancel_info.width) 03372 yes_info.width=cancel_info.width; 03373 yes_info.x=QuantumMargin; 03374 state&=(~UpdateConfigurationState); 03375 } 03376 if (state & RedrawWidgetState) 03377 { 03378 /* 03379 Redraw Confirm widget. 03380 */ 03381 width=WidgetTextWidth(font_info,(char *) reason); 03382 x=(int) ((windows->widget.width >> 1)-(width >> 1)); 03383 y=(int) ((windows->widget.height >> 1)-(height << 1)); 03384 (void) XDrawString(display,windows->widget.id, 03385 windows->widget.annotate_context,x,y,(char *) reason,Extent(reason)); 03386 if (description != (char *) NULL) 03387 { 03388 char 03389 question[MaxTextExtent]; 03390 03391 (void) CopyMagickString(question,description,MaxTextExtent); 03392 (void) ConcatenateMagickString(question,"?",MaxTextExtent); 03393 width=WidgetTextWidth(font_info,question); 03394 x=(int) ((windows->widget.width >> 1)-(width >> 1)); 03395 y+=height; 03396 (void) XDrawString(display,windows->widget.id, 03397 windows->widget.annotate_context,x,y,question,Extent(question)); 03398 } 03399 XDrawBeveledButton(display,&windows->widget,&cancel_info); 03400 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 03401 XDrawBeveledButton(display,&windows->widget,&yes_info); 03402 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 03403 state&=(~RedrawWidgetState); 03404 } 03405 /* 03406 Wait for next event. 03407 */ 03408 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 03409 switch (event.type) 03410 { 03411 case ButtonPress: 03412 { 03413 if (MatteIsActive(cancel_info,event.xbutton)) 03414 { 03415 /* 03416 User pressed No button. 03417 */ 03418 cancel_info.raised=MagickFalse; 03419 XDrawBeveledButton(display,&windows->widget,&cancel_info); 03420 break; 03421 } 03422 if (MatteIsActive(dismiss_info,event.xbutton)) 03423 { 03424 /* 03425 User pressed Dismiss button. 03426 */ 03427 dismiss_info.raised=MagickFalse; 03428 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 03429 break; 03430 } 03431 if (MatteIsActive(yes_info,event.xbutton)) 03432 { 03433 /* 03434 User pressed Yes button. 03435 */ 03436 yes_info.raised=MagickFalse; 03437 XDrawBeveledButton(display,&windows->widget,&yes_info); 03438 break; 03439 } 03440 break; 03441 } 03442 case ButtonRelease: 03443 { 03444 if (windows->widget.mapped == MagickFalse) 03445 break; 03446 if (cancel_info.raised == MagickFalse) 03447 { 03448 if (event.xbutton.window == windows->widget.id) 03449 if (MatteIsActive(cancel_info,event.xbutton)) 03450 { 03451 confirm=0; 03452 state|=ExitState; 03453 } 03454 cancel_info.raised=MagickTrue; 03455 XDrawBeveledButton(display,&windows->widget,&cancel_info); 03456 } 03457 if (dismiss_info.raised == MagickFalse) 03458 { 03459 if (event.xbutton.window == windows->widget.id) 03460 if (MatteIsActive(dismiss_info,event.xbutton)) 03461 { 03462 confirm=(-1); 03463 state|=ExitState; 03464 } 03465 dismiss_info.raised=MagickTrue; 03466 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 03467 } 03468 if (yes_info.raised == MagickFalse) 03469 { 03470 if (event.xbutton.window == windows->widget.id) 03471 if (MatteIsActive(yes_info,event.xbutton)) 03472 { 03473 confirm=1; 03474 state|=ExitState; 03475 } 03476 yes_info.raised=MagickTrue; 03477 XDrawBeveledButton(display,&windows->widget,&yes_info); 03478 } 03479 break; 03480 } 03481 case ClientMessage: 03482 { 03483 /* 03484 If client window delete message, exit. 03485 */ 03486 if (event.xclient.message_type != windows->wm_protocols) 03487 break; 03488 if (*event.xclient.data.l == (int) windows->wm_take_focus) 03489 { 03490 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 03491 (Time) event.xclient.data.l[1]); 03492 break; 03493 } 03494 if (*event.xclient.data.l != (int) windows->wm_delete_window) 03495 break; 03496 if (event.xclient.window == windows->widget.id) 03497 { 03498 state|=ExitState; 03499 break; 03500 } 03501 break; 03502 } 03503 case ConfigureNotify: 03504 { 03505 /* 03506 Update widget configuration. 03507 */ 03508 if (event.xconfigure.window != windows->widget.id) 03509 break; 03510 if ((event.xconfigure.width == (int) windows->widget.width) && 03511 (event.xconfigure.height == (int) windows->widget.height)) 03512 break; 03513 windows->widget.width=(unsigned int) 03514 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 03515 windows->widget.height=(unsigned int) 03516 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 03517 state|=UpdateConfigurationState; 03518 break; 03519 } 03520 case EnterNotify: 03521 { 03522 if (event.xcrossing.window != windows->widget.id) 03523 break; 03524 state&=(~InactiveWidgetState); 03525 break; 03526 } 03527 case Expose: 03528 { 03529 if (event.xexpose.window != windows->widget.id) 03530 break; 03531 if (event.xexpose.count != 0) 03532 break; 03533 state|=RedrawWidgetState; 03534 break; 03535 } 03536 case KeyPress: 03537 { 03538 static char 03539 command[MaxTextExtent]; 03540 03541 static KeySym 03542 key_symbol; 03543 03544 /* 03545 Respond to a user key press. 03546 */ 03547 if (event.xkey.window != windows->widget.id) 03548 break; 03549 (void) XLookupString((XKeyEvent *) &event.xkey,command, 03550 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 03551 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 03552 { 03553 yes_info.raised=MagickFalse; 03554 XDrawBeveledButton(display,&windows->widget,&yes_info); 03555 confirm=1; 03556 state|=ExitState; 03557 break; 03558 } 03559 break; 03560 } 03561 case LeaveNotify: 03562 { 03563 if (event.xcrossing.window != windows->widget.id) 03564 break; 03565 state|=InactiveWidgetState; 03566 break; 03567 } 03568 case MotionNotify: 03569 { 03570 /* 03571 Discard pending button motion events. 03572 */ 03573 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 03574 if (state & InactiveWidgetState) 03575 break; 03576 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 03577 { 03578 /* 03579 Cancel button status changed. 03580 */ 03581 cancel_info.raised=cancel_info.raised == MagickFalse ? 03582 MagickTrue : MagickFalse; 03583 XDrawBeveledButton(display,&windows->widget,&cancel_info); 03584 break; 03585 } 03586 if (dismiss_info.raised == MatteIsActive(dismiss_info,event.xmotion)) 03587 { 03588 /* 03589 Dismiss button status changed. 03590 */ 03591 dismiss_info.raised=cancel_info.raised == MagickFalse ? 03592 MagickTrue : MagickFalse; 03593 XDrawBeveledButton(display,&windows->widget,&dismiss_info); 03594 break; 03595 } 03596 if (yes_info.raised == MatteIsActive(yes_info,event.xmotion)) 03597 { 03598 /* 03599 Yes button status changed. 03600 */ 03601 yes_info.raised=yes_info.raised == MagickFalse ? 03602 MagickTrue : MagickFalse; 03603 XDrawBeveledButton(display,&windows->widget,&yes_info); 03604 break; 03605 } 03606 break; 03607 } 03608 default: 03609 break; 03610 } 03611 } while ((state & ExitState) == 0); 03612 XSetCursorState(display,windows,MagickFalse); 03613 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 03614 XCheckRefreshWindows(display,windows); 03615 return(confirm); 03616 } 03617 03618 /* 03619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03620 % % 03621 % % 03622 % % 03623 % X D i a l o g W i d g e t % 03624 % % 03625 % % 03626 % % 03627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03628 % 03629 % XDialogWidget() displays a Dialog widget with a query to the user. The user 03630 % keys a reply and presses the Ok or Cancel button to exit. The typed text is 03631 % returned as the reply function parameter. 03632 % 03633 % The format of the XDialogWidget method is: 03634 % 03635 % int XDialogWidget(Display *display,XWindows *windows,const char *action, 03636 % const char *query,char *reply) 03637 % 03638 % A description of each parameter follows: 03639 % 03640 % o display: Specifies a connection to an X server; returned from 03641 % XOpenDisplay. 03642 % 03643 % o window: Specifies a pointer to a XWindows structure. 03644 % 03645 % o action: Specifies a pointer to the action of this widget. 03646 % 03647 % o query: Specifies a pointer to the query to present to the user. 03648 % 03649 % o reply: the response from the user is returned in this parameter. 03650 % 03651 */ 03652 MagickPrivate int XDialogWidget(Display *display,XWindows *windows, 03653 const char *action,const char *query,char *reply) 03654 { 03655 #define CancelButtonText "Cancel" 03656 03657 char 03658 primary_selection[MaxTextExtent]; 03659 03660 int 03661 x; 03662 03663 register int 03664 i; 03665 03666 static MagickBooleanType 03667 raised = MagickFalse; 03668 03669 Status 03670 status; 03671 03672 unsigned int 03673 anomaly, 03674 height, 03675 width; 03676 03677 size_t 03678 state; 03679 03680 XEvent 03681 event; 03682 03683 XFontStruct 03684 *font_info; 03685 03686 XTextProperty 03687 window_name; 03688 03689 XWidgetInfo 03690 action_info, 03691 cancel_info, 03692 reply_info, 03693 special_info, 03694 text_info; 03695 03696 XWindowChanges 03697 window_changes; 03698 03699 /* 03700 Determine Dialog widget attributes. 03701 */ 03702 assert(display != (Display *) NULL); 03703 assert(windows != (XWindows *) NULL); 03704 assert(action != (char *) NULL); 03705 assert(query != (char *) NULL); 03706 assert(reply != (char *) NULL); 03707 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 03708 XCheckRefreshWindows(display,windows); 03709 font_info=windows->widget.font_info; 03710 width=WidgetTextWidth(font_info,(char *) action); 03711 if (WidgetTextWidth(font_info,CancelButtonText) > width) 03712 width=WidgetTextWidth(font_info,CancelButtonText); 03713 width+=(3*QuantumMargin) >> 1; 03714 height=(unsigned int) (font_info->ascent+font_info->descent); 03715 /* 03716 Position Dialog widget. 03717 */ 03718 windows->widget.width=(unsigned int) MagickMax((int) (2*width),(int) 03719 WidgetTextWidth(font_info,(char *) query)); 03720 if (windows->widget.width < WidgetTextWidth(font_info,reply)) 03721 windows->widget.width=WidgetTextWidth(font_info,reply); 03722 windows->widget.width+=6*QuantumMargin; 03723 windows->widget.min_width=(unsigned int) 03724 (width+28*XTextWidth(font_info,"#",1)+4*QuantumMargin); 03725 if (windows->widget.width < windows->widget.min_width) 03726 windows->widget.width=windows->widget.min_width; 03727 windows->widget.height=(unsigned int) (7*height+(QuantumMargin << 1)); 03728 windows->widget.min_height=windows->widget.height; 03729 if (windows->widget.height < windows->widget.min_height) 03730 windows->widget.height=windows->widget.min_height; 03731 XConstrainWindowPosition(display,&windows->widget); 03732 /* 03733 Map Dialog widget. 03734 */ 03735 (void) CopyMagickString(windows->widget.name,"Dialog",MaxTextExtent); 03736 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 03737 if (status != False) 03738 { 03739 XSetWMName(display,windows->widget.id,&window_name); 03740 XSetWMIconName(display,windows->widget.id,&window_name); 03741 (void) XFree((void *) window_name.value); 03742 } 03743 window_changes.width=(int) windows->widget.width; 03744 window_changes.height=(int) windows->widget.height; 03745 window_changes.x=windows->widget.x; 03746 window_changes.y=windows->widget.y; 03747 (void) XReconfigureWMWindow(display,windows->widget.id,windows->widget.screen, 03748 (unsigned int) (CWWidth | CWHeight | CWX | CWY),&window_changes); 03749 (void) XMapRaised(display,windows->widget.id); 03750 windows->widget.mapped=MagickFalse; 03751 /* 03752 Respond to X events. 03753 */ 03754 anomaly=(LocaleCompare(action,"Background") == 0) || 03755 (LocaleCompare(action,"New") == 0) || 03756 (LocaleCompare(action,"Quantize") == 0) || 03757 (LocaleCompare(action,"Resize") == 0) || 03758 (LocaleCompare(action,"Save") == 0) || 03759 (LocaleCompare(action,"Shade") == 0); 03760 state=UpdateConfigurationState; 03761 XSetCursorState(display,windows,MagickTrue); 03762 do 03763 { 03764 if (state & UpdateConfigurationState) 03765 { 03766 /* 03767 Initialize button information. 03768 */ 03769 XGetWidgetInfo(CancelButtonText,&cancel_info); 03770 cancel_info.width=width; 03771 cancel_info.height=(unsigned int) ((3*height) >> 1); 03772 cancel_info.x=(int) 03773 (windows->widget.width-cancel_info.width-((3*QuantumMargin) >> 1)); 03774 cancel_info.y=(int) 03775 (windows->widget.height-cancel_info.height-((3*QuantumMargin) >> 1)); 03776 XGetWidgetInfo(action,&action_info); 03777 action_info.width=width; 03778 action_info.height=(unsigned int) ((3*height) >> 1); 03779 action_info.x=cancel_info.x-(cancel_info.width+QuantumMargin+ 03780 (action_info.bevel_width << 1)); 03781 action_info.y=cancel_info.y; 03782 /* 03783 Initialize reply information. 03784 */ 03785 XGetWidgetInfo(reply,&reply_info); 03786 reply_info.raised=MagickFalse; 03787 reply_info.bevel_width--; 03788 reply_info.width=windows->widget.width-(3*QuantumMargin); 03789 reply_info.height=height << 1; 03790 reply_info.x=(3*QuantumMargin) >> 1; 03791 reply_info.y=action_info.y-reply_info.height-QuantumMargin; 03792 /* 03793 Initialize option information. 03794 */ 03795 XGetWidgetInfo("Dither",&special_info); 03796 special_info.raised=raised; 03797 special_info.bevel_width--; 03798 special_info.width=(unsigned int) QuantumMargin >> 1; 03799 special_info.height=(unsigned int) QuantumMargin >> 1; 03800 special_info.x=reply_info.x; 03801 special_info.y=action_info.y+action_info.height-special_info.height; 03802 if (LocaleCompare(action,"Background") == 0) 03803 special_info.text=(char *) "Backdrop"; 03804 if (LocaleCompare(action,"New") == 0) 03805 special_info.text=(char *) "Gradation"; 03806 if (LocaleCompare(action,"Resize") == 0) 03807 special_info.text=(char *) "Constrain ratio"; 03808 if (LocaleCompare(action,"Save") == 0) 03809 special_info.text=(char *) "Non-progressive"; 03810 if (LocaleCompare(action,"Shade") == 0) 03811 special_info.text=(char *) "Color shading"; 03812 /* 03813 Initialize text information. 03814 */ 03815 XGetWidgetInfo(query,&text_info); 03816 text_info.width=reply_info.width; 03817 text_info.height=height; 03818 text_info.x=reply_info.x-(QuantumMargin >> 1); 03819 text_info.y=QuantumMargin; 03820 text_info.center=MagickFalse; 03821 state&=(~UpdateConfigurationState); 03822 } 03823 if (state & RedrawWidgetState) 03824 { 03825 /* 03826 Redraw Dialog widget. 03827 */ 03828 XDrawWidgetText(display,&windows->widget,&text_info); 03829 XDrawBeveledMatte(display,&windows->widget,&reply_info); 03830 XDrawMatteText(display,&windows->widget,&reply_info); 03831 if (anomaly) 03832 XDrawBeveledButton(display,&windows->widget,&special_info); 03833 XDrawBeveledButton(display,&windows->widget,&action_info); 03834 XDrawBeveledButton(display,&windows->widget,&cancel_info); 03835 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 03836 state&=(~RedrawWidgetState); 03837 } 03838 /* 03839 Wait for next event. 03840 */ 03841 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 03842 switch (event.type) 03843 { 03844 case ButtonPress: 03845 { 03846 if (anomaly) 03847 if (MatteIsActive(special_info,event.xbutton)) 03848 { 03849 /* 03850 Option button status changed. 03851 */ 03852 special_info.raised=!special_info.raised; 03853 XDrawBeveledButton(display,&windows->widget,&special_info); 03854 break; 03855 } 03856 if (MatteIsActive(action_info,event.xbutton)) 03857 { 03858 /* 03859 User pressed Action button. 03860 */ 03861 action_info.raised=MagickFalse; 03862 XDrawBeveledButton(display,&windows->widget,&action_info); 03863 break; 03864 } 03865 if (MatteIsActive(cancel_info,event.xbutton)) 03866 { 03867 /* 03868 User pressed Cancel button. 03869 */ 03870 cancel_info.raised=MagickFalse; 03871 XDrawBeveledButton(display,&windows->widget,&cancel_info); 03872 break; 03873 } 03874 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 03875 break; 03876 if (event.xbutton.button != Button2) 03877 { 03878 static Time 03879 click_time; 03880 03881 /* 03882 Move text cursor to position of button press. 03883 */ 03884 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2); 03885 for (i=1; i <= Extent(reply_info.marker); i++) 03886 if (XTextWidth(font_info,reply_info.marker,i) > x) 03887 break; 03888 reply_info.cursor=reply_info.marker+i-1; 03889 if (event.xbutton.time > (click_time+DoubleClick)) 03890 reply_info.highlight=MagickFalse; 03891 else 03892 { 03893 /* 03894 Become the XA_PRIMARY selection owner. 03895 */ 03896 (void) CopyMagickString(primary_selection,reply_info.text, 03897 MaxTextExtent); 03898 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 03899 event.xbutton.time); 03900 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 03901 windows->widget.id ? MagickTrue : MagickFalse; 03902 } 03903 XDrawMatteText(display,&windows->widget,&reply_info); 03904 click_time=event.xbutton.time; 03905 break; 03906 } 03907 /* 03908 Request primary selection. 03909 */ 03910 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, 03911 windows->widget.id,event.xbutton.time); 03912 break; 03913 } 03914 case ButtonRelease: 03915 { 03916 if (windows->widget.mapped == MagickFalse) 03917 break; 03918 if (action_info.raised == MagickFalse) 03919 { 03920 if (event.xbutton.window == windows->widget.id) 03921 if (MatteIsActive(action_info,event.xbutton)) 03922 state|=ExitState; 03923 action_info.raised=MagickTrue; 03924 XDrawBeveledButton(display,&windows->widget,&action_info); 03925 } 03926 if (cancel_info.raised == MagickFalse) 03927 { 03928 if (event.xbutton.window == windows->widget.id) 03929 if (MatteIsActive(cancel_info,event.xbutton)) 03930 { 03931 *reply_info.text='\0'; 03932 state|=ExitState; 03933 } 03934 cancel_info.raised=MagickTrue; 03935 XDrawBeveledButton(display,&windows->widget,&cancel_info); 03936 } 03937 break; 03938 } 03939 case ClientMessage: 03940 { 03941 /* 03942 If client window delete message, exit. 03943 */ 03944 if (event.xclient.message_type != windows->wm_protocols) 03945 break; 03946 if (*event.xclient.data.l == (int) windows->wm_take_focus) 03947 { 03948 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 03949 (Time) event.xclient.data.l[1]); 03950 break; 03951 } 03952 if (*event.xclient.data.l != (int) windows->wm_delete_window) 03953 break; 03954 if (event.xclient.window == windows->widget.id) 03955 { 03956 *reply_info.text='\0'; 03957 state|=ExitState; 03958 break; 03959 } 03960 break; 03961 } 03962 case ConfigureNotify: 03963 { 03964 /* 03965 Update widget configuration. 03966 */ 03967 if (event.xconfigure.window != windows->widget.id) 03968 break; 03969 if ((event.xconfigure.width == (int) windows->widget.width) && 03970 (event.xconfigure.height == (int) windows->widget.height)) 03971 break; 03972 windows->widget.width=(unsigned int) 03973 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 03974 windows->widget.height=(unsigned int) 03975 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 03976 state|=UpdateConfigurationState; 03977 break; 03978 } 03979 case EnterNotify: 03980 { 03981 if (event.xcrossing.window != windows->widget.id) 03982 break; 03983 state&=(~InactiveWidgetState); 03984 break; 03985 } 03986 case Expose: 03987 { 03988 if (event.xexpose.window != windows->widget.id) 03989 break; 03990 if (event.xexpose.count != 0) 03991 break; 03992 state|=RedrawWidgetState; 03993 break; 03994 } 03995 case KeyPress: 03996 { 03997 static char 03998 command[MaxTextExtent]; 03999 04000 static int 04001 length; 04002 04003 static KeySym 04004 key_symbol; 04005 04006 /* 04007 Respond to a user key press. 04008 */ 04009 if (event.xkey.window != windows->widget.id) 04010 break; 04011 length=XLookupString((XKeyEvent *) &event.xkey,command, 04012 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 04013 *(command+length)='\0'; 04014 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 04015 { 04016 action_info.raised=MagickFalse; 04017 XDrawBeveledButton(display,&windows->widget,&action_info); 04018 state|=ExitState; 04019 break; 04020 } 04021 if (key_symbol == XK_Control_L) 04022 { 04023 state|=ControlState; 04024 break; 04025 } 04026 if (state & ControlState) 04027 switch ((int) key_symbol) 04028 { 04029 case XK_u: 04030 case XK_U: 04031 { 04032 /* 04033 Erase the entire line of text. 04034 */ 04035 *reply_info.text='\0'; 04036 reply_info.cursor=reply_info.text; 04037 reply_info.marker=reply_info.text; 04038 reply_info.highlight=MagickFalse; 04039 break; 04040 } 04041 default: 04042 break; 04043 } 04044 XEditText(display,&reply_info,key_symbol,command,state); 04045 XDrawMatteText(display,&windows->widget,&reply_info); 04046 break; 04047 } 04048 case KeyRelease: 04049 { 04050 static char 04051 command[MaxTextExtent]; 04052 04053 static KeySym 04054 key_symbol; 04055 04056 /* 04057 Respond to a user key release. 04058 */ 04059 if (event.xkey.window != windows->widget.id) 04060 break; 04061 (void) XLookupString((XKeyEvent *) &event.xkey,command, 04062 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 04063 if (key_symbol == XK_Control_L) 04064 state&=(~ControlState); 04065 break; 04066 } 04067 case LeaveNotify: 04068 { 04069 if (event.xcrossing.window != windows->widget.id) 04070 break; 04071 state|=InactiveWidgetState; 04072 break; 04073 } 04074 case MotionNotify: 04075 { 04076 /* 04077 Discard pending button motion events. 04078 */ 04079 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 04080 if (state & InactiveWidgetState) 04081 break; 04082 if (action_info.raised == MatteIsActive(action_info,event.xmotion)) 04083 { 04084 /* 04085 Action button status changed. 04086 */ 04087 action_info.raised=action_info.raised == MagickFalse ? 04088 MagickTrue : MagickFalse; 04089 XDrawBeveledButton(display,&windows->widget,&action_info); 04090 break; 04091 } 04092 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 04093 { 04094 /* 04095 Cancel button status changed. 04096 */ 04097 cancel_info.raised=cancel_info.raised == MagickFalse ? 04098 MagickTrue : MagickFalse; 04099 XDrawBeveledButton(display,&windows->widget,&cancel_info); 04100 break; 04101 } 04102 break; 04103 } 04104 case SelectionClear: 04105 { 04106 reply_info.highlight=MagickFalse; 04107 XDrawMatteText(display,&windows->widget,&reply_info); 04108 break; 04109 } 04110 case SelectionNotify: 04111 { 04112 Atom 04113 type; 04114 04115 int 04116 format; 04117 04118 unsigned char 04119 *data; 04120 04121 unsigned long 04122 after, 04123 length; 04124 04125 /* 04126 Obtain response from primary selection. 04127 */ 04128 if (event.xselection.property == (Atom) None) 04129 break; 04130 status=XGetWindowProperty(display,event.xselection.requestor, 04131 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type, 04132 &format,&length,&after,&data); 04133 if ((status != Success) || (type != XA_STRING) || (format == 32) || 04134 (length == 0)) 04135 break; 04136 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1)) 04137 (void) XBell(display,0); 04138 else 04139 { 04140 /* 04141 Insert primary selection in reply text. 04142 */ 04143 *(data+length)='\0'; 04144 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data, 04145 state); 04146 XDrawMatteText(display,&windows->widget,&reply_info); 04147 } 04148 (void) XFree((void *) data); 04149 break; 04150 } 04151 case SelectionRequest: 04152 { 04153 XSelectionEvent 04154 notify; 04155 04156 XSelectionRequestEvent 04157 *request; 04158 04159 if (reply_info.highlight == MagickFalse) 04160 break; 04161 /* 04162 Set primary selection. 04163 */ 04164 request=(&(event.xselectionrequest)); 04165 (void) XChangeProperty(request->display,request->requestor, 04166 request->property,request->target,8,PropModeReplace, 04167 (unsigned char *) primary_selection,Extent(primary_selection)); 04168 notify.type=SelectionNotify; 04169 notify.display=request->display; 04170 notify.requestor=request->requestor; 04171 notify.selection=request->selection; 04172 notify.target=request->target; 04173 notify.time=request->time; 04174 if (request->property == None) 04175 notify.property=request->target; 04176 else 04177 notify.property=request->property; 04178 (void) XSendEvent(request->display,request->requestor,False,0, 04179 (XEvent *) ¬ify); 04180 } 04181 default: 04182 break; 04183 } 04184 } while ((state & ExitState) == 0); 04185 XSetCursorState(display,windows,MagickFalse); 04186 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 04187 XCheckRefreshWindows(display,windows); 04188 if (anomaly) 04189 if (special_info.raised) 04190 if (*reply != '\0') 04191 raised=MagickTrue; 04192 return(raised == MagickFalse); 04193 } 04194 04195 /* 04196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 04197 % % 04198 % % 04199 % % 04200 % X F i l e B r o w s e r W i d g e t % 04201 % % 04202 % % 04203 % % 04204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 04205 % 04206 % XFileBrowserWidget() displays a File Browser widget with a file query to the 04207 % user. The user keys a reply and presses the Action or Cancel button to 04208 % exit. The typed text is returned as the reply function parameter. 04209 % 04210 % The format of the XFileBrowserWidget method is: 04211 % 04212 % void XFileBrowserWidget(Display *display,XWindows *windows, 04213 % const char *action,char *reply) 04214 % 04215 % A description of each parameter follows: 04216 % 04217 % o display: Specifies a connection to an X server; returned from 04218 % XOpenDisplay. 04219 % 04220 % o window: Specifies a pointer to a XWindows structure. 04221 % 04222 % o action: Specifies a pointer to the action of this widget. 04223 % 04224 % o reply: the response from the user is returned in this parameter. 04225 % 04226 */ 04227 MagickPrivate void XFileBrowserWidget(Display *display,XWindows *windows, 04228 const char *action,char *reply) 04229 { 04230 #define CancelButtonText "Cancel" 04231 #define DirectoryText "Directory:" 04232 #define FilenameText "File name:" 04233 #define GrabButtonText "Grab" 04234 #define FormatButtonText "Format" 04235 #define HomeButtonText "Home" 04236 #define UpButtonText "Up" 04237 04238 char 04239 *directory, 04240 **filelist, 04241 home_directory[MaxTextExtent], 04242 primary_selection[MaxTextExtent], 04243 text[MaxTextExtent], 04244 working_path[MaxTextExtent]; 04245 04246 int 04247 x, 04248 y; 04249 04250 register ssize_t 04251 i; 04252 04253 static char 04254 glob_pattern[MaxTextExtent] = "*", 04255 format[MaxTextExtent] = "miff"; 04256 04257 static MagickStatusType 04258 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY); 04259 04260 Status 04261 status; 04262 04263 unsigned int 04264 anomaly, 04265 height, 04266 text_width, 04267 visible_files, 04268 width; 04269 04270 size_t 04271 delay, 04272 files, 04273 state; 04274 04275 XEvent 04276 event; 04277 04278 XFontStruct 04279 *font_info; 04280 04281 XTextProperty 04282 window_name; 04283 04284 XWidgetInfo 04285 action_info, 04286 cancel_info, 04287 expose_info, 04288 special_info, 04289 list_info, 04290 home_info, 04291 north_info, 04292 reply_info, 04293 scroll_info, 04294 selection_info, 04295 slider_info, 04296 south_info, 04297 text_info, 04298 up_info; 04299 04300 XWindowChanges 04301 window_changes; 04302 04303 /* 04304 Read filelist from current directory. 04305 */ 04306 assert(display != (Display *) NULL); 04307 assert(windows != (XWindows *) NULL); 04308 assert(action != (char *) NULL); 04309 assert(reply != (char *) NULL); 04310 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 04311 XSetCursorState(display,windows,MagickTrue); 04312 XCheckRefreshWindows(display,windows); 04313 directory=getcwd(home_directory,MaxTextExtent); 04314 (void) directory; 04315 (void) CopyMagickString(working_path,home_directory,MaxTextExtent); 04316 filelist=ListFiles(working_path,glob_pattern,&files); 04317 if (filelist == (char **) NULL) 04318 { 04319 /* 04320 Directory read failed. 04321 */ 04322 XNoticeWidget(display,windows,"Unable to read directory:",working_path); 04323 (void) XDialogWidget(display,windows,action,"Enter filename:",reply); 04324 return; 04325 } 04326 /* 04327 Determine File Browser widget attributes. 04328 */ 04329 font_info=windows->widget.font_info; 04330 text_width=0; 04331 for (i=0; i < (ssize_t) files; i++) 04332 if (WidgetTextWidth(font_info,filelist[i]) > text_width) 04333 text_width=WidgetTextWidth(font_info,filelist[i]); 04334 width=WidgetTextWidth(font_info,(char *) action); 04335 if (WidgetTextWidth(font_info,GrabButtonText) > width) 04336 width=WidgetTextWidth(font_info,GrabButtonText); 04337 if (WidgetTextWidth(font_info,FormatButtonText) > width) 04338 width=WidgetTextWidth(font_info,FormatButtonText); 04339 if (WidgetTextWidth(font_info,CancelButtonText) > width) 04340 width=WidgetTextWidth(font_info,CancelButtonText); 04341 if (WidgetTextWidth(font_info,HomeButtonText) > width) 04342 width=WidgetTextWidth(font_info,HomeButtonText); 04343 if (WidgetTextWidth(font_info,UpButtonText) > width) 04344 width=WidgetTextWidth(font_info,UpButtonText); 04345 width+=QuantumMargin; 04346 if (WidgetTextWidth(font_info,DirectoryText) > width) 04347 width=WidgetTextWidth(font_info,DirectoryText); 04348 if (WidgetTextWidth(font_info,FilenameText) > width) 04349 width=WidgetTextWidth(font_info,FilenameText); 04350 height=(unsigned int) (font_info->ascent+font_info->descent); 04351 /* 04352 Position File Browser widget. 04353 */ 04354 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+ 04355 6*QuantumMargin; 04356 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin; 04357 if (windows->widget.width < windows->widget.min_width) 04358 windows->widget.width=windows->widget.min_width; 04359 windows->widget.height=(unsigned int) 04360 (((81*height) >> 2)+((13*QuantumMargin) >> 1)+4); 04361 windows->widget.min_height=(unsigned int) 04362 (((23*height) >> 1)+((13*QuantumMargin) >> 1)+4); 04363 if (windows->widget.height < windows->widget.min_height) 04364 windows->widget.height=windows->widget.min_height; 04365 XConstrainWindowPosition(display,&windows->widget); 04366 /* 04367 Map File Browser widget. 04368 */ 04369 (void) CopyMagickString(windows->widget.name,"Browse and Select a File", 04370 MaxTextExtent); 04371 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 04372 if (status != False) 04373 { 04374 XSetWMName(display,windows->widget.id,&window_name); 04375 XSetWMIconName(display,windows->widget.id,&window_name); 04376 (void) XFree((void *) window_name.value); 04377 } 04378 window_changes.width=(int) windows->widget.width; 04379 window_changes.height=(int) windows->widget.height; 04380 window_changes.x=windows->widget.x; 04381 window_changes.y=windows->widget.y; 04382 (void) XReconfigureWMWindow(display,windows->widget.id, 04383 windows->widget.screen,mask,&window_changes); 04384 (void) XMapRaised(display,windows->widget.id); 04385 windows->widget.mapped=MagickFalse; 04386 /* 04387 Respond to X events. 04388 */ 04389 XGetWidgetInfo((char *) NULL,&slider_info); 04390 XGetWidgetInfo((char *) NULL,&north_info); 04391 XGetWidgetInfo((char *) NULL,&south_info); 04392 XGetWidgetInfo((char *) NULL,&expose_info); 04393 visible_files=0; 04394 anomaly=(LocaleCompare(action,"Composite") == 0) || 04395 (LocaleCompare(action,"Open") == 0) || (LocaleCompare(action,"Map") == 0); 04396 *reply='\0'; 04397 delay=SuspendTime << 2; 04398 state=UpdateConfigurationState; 04399 do 04400 { 04401 if (state & UpdateConfigurationState) 04402 { 04403 int 04404 id; 04405 04406 /* 04407 Initialize button information. 04408 */ 04409 XGetWidgetInfo(CancelButtonText,&cancel_info); 04410 cancel_info.width=width; 04411 cancel_info.height=(unsigned int) ((3*height) >> 1); 04412 cancel_info.x=(int) 04413 (windows->widget.width-cancel_info.width-QuantumMargin-2); 04414 cancel_info.y=(int) 04415 (windows->widget.height-cancel_info.height-QuantumMargin); 04416 XGetWidgetInfo(action,&action_info); 04417 action_info.width=width; 04418 action_info.height=(unsigned int) ((3*height) >> 1); 04419 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+ 04420 (action_info.bevel_width << 1)); 04421 action_info.y=cancel_info.y; 04422 XGetWidgetInfo(GrabButtonText,&special_info); 04423 special_info.width=width; 04424 special_info.height=(unsigned int) ((3*height) >> 1); 04425 special_info.x=action_info.x-(action_info.width+(QuantumMargin >> 1)+ 04426 (special_info.bevel_width << 1)); 04427 special_info.y=action_info.y; 04428 if (anomaly == MagickFalse) 04429 { 04430 register char 04431 *p; 04432 04433 special_info.text=(char *) FormatButtonText; 04434 p=reply+Extent(reply)-1; 04435 while ((p > (reply+1)) && (*(p-1) != '.')) 04436 p--; 04437 if ((p > (reply+1)) && (*(p-1) == '.')) 04438 (void) CopyMagickString(format,p,MaxTextExtent); 04439 } 04440 XGetWidgetInfo(UpButtonText,&up_info); 04441 up_info.width=width; 04442 up_info.height=(unsigned int) ((3*height) >> 1); 04443 up_info.x=QuantumMargin; 04444 up_info.y=((5*QuantumMargin) >> 1)+height; 04445 XGetWidgetInfo(HomeButtonText,&home_info); 04446 home_info.width=width; 04447 home_info.height=(unsigned int) ((3*height) >> 1); 04448 home_info.x=QuantumMargin; 04449 home_info.y=up_info.y+up_info.height+QuantumMargin; 04450 /* 04451 Initialize reply information. 04452 */ 04453 XGetWidgetInfo(reply,&reply_info); 04454 reply_info.raised=MagickFalse; 04455 reply_info.bevel_width--; 04456 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1); 04457 reply_info.height=height << 1; 04458 reply_info.x=(int) (width+(QuantumMargin << 1)); 04459 reply_info.y=action_info.y-reply_info.height-QuantumMargin; 04460 /* 04461 Initialize scroll information. 04462 */ 04463 XGetWidgetInfo((char *) NULL,&scroll_info); 04464 scroll_info.bevel_width--; 04465 scroll_info.width=height; 04466 scroll_info.height=(unsigned int) 04467 (reply_info.y-up_info.y-(QuantumMargin >> 1)); 04468 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width); 04469 scroll_info.y=up_info.y-reply_info.bevel_width; 04470 scroll_info.raised=MagickFalse; 04471 scroll_info.trough=MagickTrue; 04472 north_info=scroll_info; 04473 north_info.raised=MagickTrue; 04474 north_info.width-=(north_info.bevel_width << 1); 04475 north_info.height=north_info.width-1; 04476 north_info.x+=north_info.bevel_width; 04477 north_info.y+=north_info.bevel_width; 04478 south_info=north_info; 04479 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width- 04480 south_info.height; 04481 id=slider_info.id; 04482 slider_info=north_info; 04483 slider_info.id=id; 04484 slider_info.width-=2; 04485 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+ 04486 slider_info.bevel_width+2; 04487 slider_info.height=scroll_info.height-((slider_info.min_y- 04488 scroll_info.y+1) << 1)+4; 04489 visible_files=scroll_info.height/(height+(height >> 3)); 04490 if (files > visible_files) 04491 slider_info.height=(unsigned int) 04492 ((visible_files*slider_info.height)/files); 04493 slider_info.max_y=south_info.y-south_info.bevel_width- 04494 slider_info.bevel_width-2; 04495 slider_info.x=scroll_info.x+slider_info.bevel_width+1; 04496 slider_info.y=slider_info.min_y; 04497 expose_info=scroll_info; 04498 expose_info.y=slider_info.y; 04499 /* 04500 Initialize list information. 04501 */ 04502 XGetWidgetInfo((char *) NULL,&list_info); 04503 list_info.raised=MagickFalse; 04504 list_info.bevel_width--; 04505 list_info.width=(unsigned int) 04506 (scroll_info.x-reply_info.x-(QuantumMargin >> 1)); 04507 list_info.height=scroll_info.height; 04508 list_info.x=reply_info.x; 04509 list_info.y=scroll_info.y; 04510 if (windows->widget.mapped == MagickFalse) 04511 state|=JumpListState; 04512 /* 04513 Initialize text information. 04514 */ 04515 *text='\0'; 04516 XGetWidgetInfo(text,&text_info); 04517 text_info.center=MagickFalse; 04518 text_info.width=reply_info.width; 04519 text_info.height=height; 04520 text_info.x=list_info.x-(QuantumMargin >> 1); 04521 text_info.y=QuantumMargin; 04522 /* 04523 Initialize selection information. 04524 */ 04525 XGetWidgetInfo((char *) NULL,&selection_info); 04526 selection_info.center=MagickFalse; 04527 selection_info.width=list_info.width; 04528 selection_info.height=(unsigned int) ((9*height) >> 3); 04529 selection_info.x=list_info.x; 04530 state&=(~UpdateConfigurationState); 04531 } 04532 if (state & RedrawWidgetState) 04533 { 04534 /* 04535 Redraw File Browser window. 04536 */ 04537 x=QuantumMargin; 04538 y=text_info.y+((text_info.height-height) >> 1)+font_info->ascent; 04539 (void) XDrawString(display,windows->widget.id, 04540 windows->widget.annotate_context,x,y,DirectoryText, 04541 Extent(DirectoryText)); 04542 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent); 04543 (void) ConcatenateMagickString(text_info.text,DirectorySeparator, 04544 MaxTextExtent); 04545 (void) ConcatenateMagickString(text_info.text,glob_pattern, 04546 MaxTextExtent); 04547 XDrawWidgetText(display,&windows->widget,&text_info); 04548 XDrawBeveledButton(display,&windows->widget,&up_info); 04549 XDrawBeveledButton(display,&windows->widget,&home_info); 04550 XDrawBeveledMatte(display,&windows->widget,&list_info); 04551 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 04552 XDrawTriangleNorth(display,&windows->widget,&north_info); 04553 XDrawBeveledButton(display,&windows->widget,&slider_info); 04554 XDrawTriangleSouth(display,&windows->widget,&south_info); 04555 x=QuantumMargin; 04556 y=reply_info.y+((reply_info.height-height) >> 1)+font_info->ascent; 04557 (void) XDrawString(display,windows->widget.id, 04558 windows->widget.annotate_context,x,y,FilenameText, 04559 Extent(FilenameText)); 04560 XDrawBeveledMatte(display,&windows->widget,&reply_info); 04561 XDrawMatteText(display,&windows->widget,&reply_info); 04562 XDrawBeveledButton(display,&windows->widget,&special_info); 04563 XDrawBeveledButton(display,&windows->widget,&action_info); 04564 XDrawBeveledButton(display,&windows->widget,&cancel_info); 04565 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 04566 selection_info.id=(~0); 04567 state|=RedrawListState; 04568 state&=(~RedrawWidgetState); 04569 } 04570 if (state & UpdateListState) 04571 { 04572 char 04573 **checklist; 04574 04575 size_t 04576 number_files; 04577 04578 /* 04579 Update file list. 04580 */ 04581 checklist=ListFiles(working_path,glob_pattern,&number_files); 04582 if (checklist == (char **) NULL) 04583 { 04584 /* 04585 Reply is a filename, exit. 04586 */ 04587 action_info.raised=MagickFalse; 04588 XDrawBeveledButton(display,&windows->widget,&action_info); 04589 break; 04590 } 04591 for (i=0; i < (ssize_t) files; i++) 04592 filelist[i]=DestroyString(filelist[i]); 04593 if (filelist != (char **) NULL) 04594 filelist=(char **) RelinquishMagickMemory(filelist); 04595 filelist=checklist; 04596 files=number_files; 04597 /* 04598 Update file list. 04599 */ 04600 slider_info.height= 04601 scroll_info.height-((slider_info.min_y-scroll_info.y+1) << 1)+1; 04602 if (files > visible_files) 04603 slider_info.height=(unsigned int) 04604 ((visible_files*slider_info.height)/files); 04605 slider_info.max_y=south_info.y-south_info.bevel_width- 04606 slider_info.bevel_width-2; 04607 slider_info.id=0; 04608 slider_info.y=slider_info.min_y; 04609 expose_info.y=slider_info.y; 04610 selection_info.id=(~0); 04611 list_info.id=(~0); 04612 state|=RedrawListState; 04613 /* 04614 Redraw directory name & reply. 04615 */ 04616 if (IsGlob(reply_info.text) == MagickFalse) 04617 { 04618 *reply_info.text='\0'; 04619 reply_info.cursor=reply_info.text; 04620 } 04621 (void) CopyMagickString(text_info.text,working_path,MaxTextExtent); 04622 (void) ConcatenateMagickString(text_info.text,DirectorySeparator, 04623 MaxTextExtent); 04624 (void) ConcatenateMagickString(text_info.text,glob_pattern, 04625 MaxTextExtent); 04626 XDrawWidgetText(display,&windows->widget,&text_info); 04627 XDrawMatteText(display,&windows->widget,&reply_info); 04628 XDrawBeveledMatte(display,&windows->widget,&scroll_info); 04629 XDrawTriangleNorth(display,&windows->widget,&north_info); 04630 XDrawBeveledButton(display,&windows->widget,&slider_info); 04631 XDrawTriangleSouth(display,&windows->widget,&south_info); 04632 XHighlightWidget(display,&windows->widget,BorderOffset,BorderOffset); 04633 state&=(~UpdateListState); 04634 } 04635 if (state & JumpListState) 04636 { 04637 /* 04638 Jump scroll to match user filename. 04639 */ 04640 list_info.id=(~0); 04641 for (i=0; i < (ssize_t) files; i++) 04642 if (LocaleCompare(filelist[i],reply) >= 0) 04643 { 04644 list_info.id=(int) 04645 (LocaleCompare(filelist[i],reply) == 0 ? i : ~0); 04646 break; 04647 } 04648 if ((i < (ssize_t) slider_info.id) || 04649 (i >= (ssize_t) (slider_info.id+visible_files))) 04650 slider_info.id=(int) i-(visible_files >> 1); 04651 selection_info.id=(~0); 04652 state|=RedrawListState; 04653 state&=(~JumpListState); 04654 } 04655 if (state & RedrawListState) 04656 { 04657 /* 04658 Determine slider id and position. 04659 */ 04660 if (slider_info.id >= (int) (files-visible_files)) 04661 slider_info.id=(int) (files-visible_files); 04662 if ((slider_info.id < 0) || (files <= visible_files)) 04663 slider_info.id=0; 04664 slider_info.y=slider_info.min_y; 04665 if (files > 0) 04666 slider_info.y+=(int) (slider_info.id*(slider_info.max_y- 04667 slider_info.min_y+1)/files); 04668 if (slider_info.id != selection_info.id) 04669 { 04670 /* 04671 Redraw scroll bar and file names. 04672 */ 04673 selection_info.id=slider_info.id; 04674 selection_info.y=list_info.y+(height >> 3)+2; 04675 for (i=0; i < (ssize_t) visible_files; i++) 04676 { 04677 selection_info.raised=(int) (slider_info.id+i) != list_info.id ? 04678 MagickTrue : MagickFalse; 04679 selection_info.text=(char *) NULL; 04680 if ((slider_info.id+i) < (ssize_t) files) 04681 selection_info.text=filelist[slider_info.id+i]; 04682 XDrawWidgetText(display,&windows->widget,&selection_info); 04683 selection_info.y+=(int) selection_info.height; 04684 } 04685 /* 04686 Update slider. 04687 */ 04688 if (slider_info.y > expose_info.y) 04689 { 04690 expose_info.height=(unsigned int) slider_info.y-expose_info.y; 04691 expose_info.y=slider_info.y-expose_info.height- 04692 slider_info.bevel_width-1; 04693 } 04694 else 04695 { 04696 expose_info.height=(unsigned int) expose_info.y-slider_info.y; 04697 expose_info.y=slider_info.y+slider_info.height+ 04698 slider_info.bevel_width+1; 04699 } 04700 XDrawTriangleNorth(display,&windows->widget,&north_info); 04701 XDrawMatte(display,&windows->widget,&expose_info); 04702 XDrawBeveledButton(display,&windows->widget,&slider_info); 04703 XDrawTriangleSouth(display,&windows->widget,&south_info); 04704 expose_info.y=slider_info.y; 04705 } 04706 state&=(~RedrawListState); 04707 } 04708 /* 04709 Wait for next event. 04710 */ 04711 if (north_info.raised && south_info.raised) 04712 (void) XIfEvent(display,&event,XScreenEvent,(char *) windows); 04713 else 04714 { 04715 /* 04716 Brief delay before advancing scroll bar. 04717 */ 04718 XDelay(display,delay); 04719 delay=SuspendTime; 04720 (void) XCheckIfEvent(display,&event,XScreenEvent,(char *) windows); 04721 if (north_info.raised == MagickFalse) 04722 if (slider_info.id > 0) 04723 { 04724 /* 04725 Move slider up. 04726 */ 04727 slider_info.id--; 04728 state|=RedrawListState; 04729 } 04730 if (south_info.raised == MagickFalse) 04731 if (slider_info.id < (int) files) 04732 { 04733 /* 04734 Move slider down. 04735 */ 04736 slider_info.id++; 04737 state|=RedrawListState; 04738 } 04739 if (event.type != ButtonRelease) 04740 continue; 04741 } 04742 switch (event.type) 04743 { 04744 case ButtonPress: 04745 { 04746 if (MatteIsActive(slider_info,event.xbutton)) 04747 { 04748 /* 04749 Track slider. 04750 */ 04751 slider_info.active=MagickTrue; 04752 break; 04753 } 04754 if (MatteIsActive(north_info,event.xbutton)) 04755 if (slider_info.id > 0) 04756 { 04757 /* 04758 Move slider up. 04759 */ 04760 north_info.raised=MagickFalse; 04761 slider_info.id--; 04762 state|=RedrawListState; 04763 break; 04764 } 04765 if (MatteIsActive(south_info,event.xbutton)) 04766 if (slider_info.id < (int) files) 04767 { 04768 /* 04769 Move slider down. 04770 */ 04771 south_info.raised=MagickFalse; 04772 slider_info.id++; 04773 state|=RedrawListState; 04774 break; 04775 } 04776 if (MatteIsActive(scroll_info,event.xbutton)) 04777 { 04778 /* 04779 Move slider. 04780 */ 04781 if (event.xbutton.y < slider_info.y) 04782 slider_info.id-=(visible_files-1); 04783 else 04784 slider_info.id+=(visible_files-1); 04785 state|=RedrawListState; 04786 break; 04787 } 04788 if (MatteIsActive(list_info,event.xbutton)) 04789 { 04790 int 04791 id; 04792 04793 /* 04794 User pressed file matte. 04795 */ 04796 id=slider_info.id+(event.xbutton.y-(list_info.y+(height >> 1))+1)/ 04797 selection_info.height; 04798 if (id >= (int) files) 04799 break; 04800 (void) CopyMagickString(reply_info.text,filelist[id],MaxTextExtent); 04801 reply_info.highlight=MagickFalse; 04802 reply_info.marker=reply_info.text; 04803 reply_info.cursor=reply_info.text+Extent(reply_info.text); 04804 XDrawMatteText(display,&windows->widget,&reply_info); 04805 if (id == list_info.id) 04806 { 04807 register char 04808 *p; 04809 04810 p=reply_info.text+strlen(reply_info.text)-1; 04811 if (*p == *DirectorySeparator) 04812 ChopPathComponents(reply_info.text,1); 04813 (void) ConcatenateMagickString(working_path,DirectorySeparator, 04814 MaxTextExtent); 04815 (void) ConcatenateMagickString(working_path,reply_info.text, 04816 MaxTextExtent); 04817 *reply='\0'; 04818 state|=UpdateListState; 04819 } 04820 selection_info.id=(~0); 04821 list_info.id=id; 04822 state|=RedrawListState; 04823 break; 04824 } 04825 if (MatteIsActive(up_info,event.xbutton)) 04826 { 04827 /* 04828 User pressed Up button. 04829 */ 04830 up_info.raised=MagickFalse; 04831 XDrawBeveledButton(display,&windows->widget,&up_info); 04832 break; 04833 } 04834 if (MatteIsActive(home_info,event.xbutton)) 04835 { 04836 /* 04837 User pressed Home button. 04838 */ 04839 home_info.raised=MagickFalse; 04840 XDrawBeveledButton(display,&windows->widget,&home_info); 04841 break; 04842 } 04843 if (MatteIsActive(special_info,event.xbutton)) 04844 { 04845 /* 04846 User pressed Special button. 04847 */ 04848 special_info.raised=MagickFalse; 04849 XDrawBeveledButton(display,&windows->widget,&special_info); 04850 break; 04851 } 04852 if (MatteIsActive(action_info,event.xbutton)) 04853 { 04854 /* 04855 User pressed action button. 04856 */ 04857 action_info.raised=MagickFalse; 04858 XDrawBeveledButton(display,&windows->widget,&action_info); 04859 break; 04860 } 04861 if (MatteIsActive(cancel_info,event.xbutton)) 04862 { 04863 /* 04864 User pressed Cancel button. 04865 */ 04866 cancel_info.raised=MagickFalse; 04867 XDrawBeveledButton(display,&windows->widget,&cancel_info); 04868 break; 04869 } 04870 if (MatteIsActive(reply_info,event.xbutton) == MagickFalse) 04871 break; 04872 if (event.xbutton.button != Button2) 04873 { 04874 static Time 04875 click_time; 04876 04877 /* 04878 Move text cursor to position of button press. 04879 */ 04880 x=event.xbutton.x-reply_info.x-(QuantumMargin >> 2); 04881 for (i=1; i <= (ssize_t) Extent(reply_info.marker); i++) 04882 if (XTextWidth(font_info,reply_info.marker,(int) i) > x) 04883 break; 04884 reply_info.cursor=reply_info.marker+i-1; 04885 if (event.xbutton.time > (click_time+DoubleClick)) 04886 reply_info.highlight=MagickFalse; 04887 else 04888 { 04889 /* 04890 Become the XA_PRIMARY selection owner. 04891 */ 04892 (void) CopyMagickString(primary_selection,reply_info.text, 04893 MaxTextExtent); 04894 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->widget.id, 04895 event.xbutton.time); 04896 reply_info.highlight=XGetSelectionOwner(display,XA_PRIMARY) == 04897 windows->widget.id ? MagickTrue : MagickFalse; 04898 } 04899 XDrawMatteText(display,&windows->widget,&reply_info); 04900 click_time=event.xbutton.time; 04901 break; 04902 } 04903 /* 04904 Request primary selection. 04905 */ 04906 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING, 04907 windows->widget.id,event.xbutton.time); 04908 break; 04909 } 04910 case ButtonRelease: 04911 { 04912 if (windows->widget.mapped == MagickFalse) 04913 break; 04914 if (north_info.raised == MagickFalse) 04915 { 04916 /* 04917 User released up button. 04918 */ 04919 delay=SuspendTime << 2; 04920 north_info.raised=MagickTrue; 04921 XDrawTriangleNorth(display,&windows->widget,&north_info); 04922 } 04923 if (south_info.raised == MagickFalse) 04924 { 04925 /* 04926 User released down button. 04927 */ 04928 delay=SuspendTime << 2; 04929 south_info.raised=MagickTrue; 04930 XDrawTriangleSouth(display,&windows->widget,&south_info); 04931 } 04932 if (slider_info.active) 04933 { 04934 /* 04935 Stop tracking slider. 04936 */ 04937 slider_info.active=MagickFalse; 04938 break; 04939 } 04940 if (up_info.raised == MagickFalse) 04941 { 04942 if (event.xbutton.window == windows->widget.id) 04943 if (MatteIsActive(up_info,event.xbutton)) 04944 { 04945 ChopPathComponents(working_path,1); 04946 if (*working_path == '\0') 04947 (void) CopyMagickString(working_path,DirectorySeparator, 04948 MaxTextExtent); 04949 state|=UpdateListState; 04950 } 04951 up_info.raised=MagickTrue; 04952 XDrawBeveledButton(display,&windows->widget,&up_info); 04953 } 04954 if (home_info.raised == MagickFalse) 04955 { 04956 if (event.xbutton.window == windows->widget.id) 04957 if (MatteIsActive(home_info,event.xbutton)) 04958 { 04959 (void) CopyMagickString(working_path,home_directory, 04960 MaxTextExtent); 04961 state|=UpdateListState; 04962 } 04963 home_info.raised=MagickTrue; 04964 XDrawBeveledButton(display,&windows->widget,&home_info); 04965 } 04966 if (special_info.raised == MagickFalse) 04967 { 04968 if (anomaly == MagickFalse) 04969 { 04970 char 04971 **formats; 04972 04973 ExceptionInfo 04974 *exception; 04975 04976 size_t 04977 number_formats; 04978 04979 /* 04980 Let user select image format. 04981 */ 04982 exception=AcquireExceptionInfo(); 04983 formats=GetMagickList("*",&number_formats,exception); 04984 exception=DestroyExceptionInfo(exception); 04985 (void) XCheckDefineCursor(display,windows->widget.id, 04986 windows->widget.busy_cursor); 04987 windows->popup.x=windows->widget.x+60; 04988 windows->popup.y=windows->widget.y+60; 04989 XListBrowserWidget(display,windows,&windows->popup, 04990 (const char **) formats,"Select","Select image format type:", 04991 format); 04992 XSetCursorState(display,windows,MagickTrue); 04993 (void) XCheckDefineCursor(display,windows->widget.id, 04994 windows->widget.cursor); 04995 LocaleLower(format); 04996 AppendImageFormat(format,reply_info.text); 04997 reply_info.cursor=reply_info.text+Extent(reply_info.text); 04998 XDrawMatteText(display,&windows->widget,&reply_info); 04999 special_info.raised=MagickTrue; 05000 XDrawBeveledButton(display,&windows->widget,&special_info); 05001 for (i=0; i < (ssize_t) number_formats; i++) 05002 formats[i]=DestroyString(formats[i]); 05003 formats=(char **) RelinquishMagickMemory(formats); 05004 break; 05005 } 05006 if (event.xbutton.window == windows->widget.id) 05007 if (MatteIsActive(special_info,event.xbutton)) 05008 { 05009 (void) CopyMagickString(working_path,"x:",MaxTextExtent); 05010 state|=ExitState; 05011 } 05012 special_info.raised=MagickTrue; 05013 XDrawBeveledButton(display,&windows->widget,&special_info); 05014 } 05015 if (action_info.raised == MagickFalse) 05016 { 05017 if (event.xbutton.window == windows->widget.id) 05018 { 05019 if (MatteIsActive(action_info,event.xbutton)) 05020 { 05021 if (*reply_info.text == '\0') 05022 (void) XBell(display,0); 05023 else 05024 state|=ExitState; 05025 } 05026 } 05027 action_info.raised=MagickTrue; 05028 XDrawBeveledButton(display,&windows->widget,&action_info); 05029 } 05030 if (cancel_info.raised == MagickFalse) 05031 { 05032 if (event.xbutton.window == windows->widget.id) 05033 if (MatteIsActive(cancel_info,event.xbutton)) 05034 { 05035 *reply_info.text='\0'; 05036 *reply='\0'; 05037 state|=ExitState; 05038 } 05039 cancel_info.raised=MagickTrue; 05040 XDrawBeveledButton(display,&windows->widget,&cancel_info); 05041 } 05042 break; 05043 } 05044 case ClientMessage: 05045 { 05046 /* 05047 If client window delete message, exit. 05048 */ 05049 if (event.xclient.message_type != windows->wm_protocols) 05050 break; 05051 if (*event.xclient.data.l == (int) windows->wm_take_focus) 05052 { 05053 (void) XSetInputFocus(display,event.xclient.window,RevertToParent, 05054 (Time) event.xclient.data.l[1]); 05055 break; 05056 } 05057 if (*event.xclient.data.l != (int) windows->wm_delete_window) 05058 break; 05059 if (event.xclient.window == windows->widget.id) 05060 { 05061 *reply_info.text='\0'; 05062 state|=ExitState; 05063 break; 05064 } 05065 break; 05066 } 05067 case ConfigureNotify: 05068 { 05069 /* 05070 Update widget configuration. 05071 */ 05072 if (event.xconfigure.window != windows->widget.id) 05073 break; 05074 if ((event.xconfigure.width == (int) windows->widget.width) && 05075 (event.xconfigure.height == (int) windows->widget.height)) 05076 break; 05077 windows->widget.width=(unsigned int) 05078 MagickMax(event.xconfigure.width,(int) windows->widget.min_width); 05079 windows->widget.height=(unsigned int) 05080 MagickMax(event.xconfigure.height,(int) windows->widget.min_height); 05081 state|=UpdateConfigurationState; 05082 break; 05083 } 05084 case EnterNotify: 05085 { 05086 if (event.xcrossing.window != windows->widget.id) 05087 break; 05088 state&=(~InactiveWidgetState); 05089 break; 05090 } 05091 case Expose: 05092 { 05093 if (event.xexpose.window != windows->widget.id) 05094 break; 05095 if (event.xexpose.count != 0) 05096 break; 05097 state|=RedrawWidgetState; 05098 break; 05099 } 05100 case KeyPress: 05101 { 05102 static char 05103 command[MaxTextExtent]; 05104 05105 static int 05106 length; 05107 05108 static KeySym 05109 key_symbol; 05110 05111 /* 05112 Respond to a user key press. 05113 */ 05114 if (event.xkey.window != windows->widget.id) 05115 break; 05116 length=XLookupString((XKeyEvent *) &event.xkey,command, 05117 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 05118 *(command+length)='\0'; 05119 if (AreaIsActive(scroll_info,event.xkey)) 05120 { 05121 /* 05122 Move slider. 05123 */ 05124 switch ((int) key_symbol) 05125 { 05126 case XK_Home: 05127 case XK_KP_Home: 05128 { 05129 slider_info.id=0; 05130 break; 05131 } 05132 case XK_Up: 05133 case XK_KP_Up: 05134 { 05135 slider_info.id--; 05136 break; 05137 } 05138 case XK_Down: 05139 case XK_KP_Down: 05140 { 05141 slider_info.id++; 05142 break; 05143 } 05144 case XK_Prior: 05145 case XK_KP_Prior: 05146 { 05147 slider_info.id-=visible_files; 05148 break; 05149 } 05150 case XK_Next: 05151 case XK_KP_Next: 05152 { 05153 slider_info.id+=visible_files; 05154 break; 05155 } 05156 case XK_End: 05157 case XK_KP_End: 05158 { 05159 slider_info.id=(int) files; 05160 break; 05161 } 05162 } 05163 state|=RedrawListState; 05164 break; 05165 } 05166 if ((key_symbol == XK_Return) || (key_symbol == XK_KP_Enter)) 05167 { 05168 /* 05169 Read new directory or glob patterm. 05170 */ 05171 if (*reply_info.text == '\0') 05172 break; 05173 if (IsGlob(reply_info.text)) 05174 (void) CopyMagickString(glob_pattern,reply_info.text, 05175 MaxTextExtent); 05176 else 05177 { 05178 (void) ConcatenateMagickString(working_path,DirectorySeparator, 05179 MaxTextExtent); 05180 (void) ConcatenateMagickString(working_path,reply_info.text, 05181 MaxTextExtent); 05182 if (*working_path == '~') 05183 ExpandFilename(working_path); 05184 *reply='\0'; 05185 } 05186 state|=UpdateListState; 05187 break; 05188 } 05189 if (key_symbol == XK_Control_L) 05190 { 05191 state|=ControlState; 05192 break; 05193 } 05194 if (state & ControlState) 05195 switch ((int) key_symbol) 05196 { 05197 case XK_u: 05198 case XK_U: 05199 { 05200 /* 05201 Erase the entire line of text. 05202 */ 05203 *reply_info.text='\0'; 05204 reply_info.cursor=reply_info.text; 05205 reply_info.marker=reply_info.text; 05206 reply_info.highlight=MagickFalse; 05207 break; 05208 } 05209 default: 05210 break; 05211 } 05212 XEditText(display,&reply_info,key_symbol,command,state); 05213 XDrawMatteText(display,&windows->widget,&reply_info); 05214 state|=JumpListState; 05215 break; 05216 } 05217 case KeyRelease: 05218 { 05219 static char 05220 command[MaxTextExtent]; 05221 05222 static KeySym 05223 key_symbol; 05224 05225 /* 05226 Respond to a user key release. 05227 */ 05228 if (event.xkey.window != windows->widget.id) 05229 break; 05230 (void) XLookupString((XKeyEvent *) &event.xkey,command, 05231 (int) sizeof(command),&key_symbol,(XComposeStatus *) NULL); 05232 if (key_symbol == XK_Control_L) 05233 state&=(~ControlState); 05234 break; 05235 } 05236 case LeaveNotify: 05237 { 05238 if (event.xcrossing.window != windows->widget.id) 05239 break; 05240 state|=InactiveWidgetState; 05241 break; 05242 } 05243 case MapNotify: 05244 { 05245 mask&=(~CWX); 05246 mask&=(~CWY); 05247 break; 05248 } 05249 case MotionNotify: 05250 { 05251 /* 05252 Discard pending button motion events. 05253 */ 05254 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ; 05255 if (slider_info.active) 05256 { 05257 /* 05258 Move slider matte. 05259 */ 05260 slider_info.y=event.xmotion.y- 05261 ((slider_info.height+slider_info.bevel_width) >> 1)+1; 05262 if (slider_info.y < slider_info.min_y) 05263 slider_info.y=slider_info.min_y; 05264 if (slider_info.y > slider_info.max_y) 05265 slider_info.y=slider_info.max_y; 05266 slider_info.id=0; 05267 if (slider_info.y != slider_info.min_y) 05268 slider_info.id=(int) ((files*(slider_info.y-slider_info.min_y+1))/ 05269 (slider_info.max_y-slider_info.min_y+1)); 05270 state|=RedrawListState; 05271 break; 05272 } 05273 if (state & InactiveWidgetState) 05274 break; 05275 if (up_info.raised == MatteIsActive(up_info,event.xmotion)) 05276 { 05277 /* 05278 Up button status changed. 05279 */ 05280 up_info.raised=!up_info.raised; 05281 XDrawBeveledButton(display,&windows->widget,&up_info); 05282 break; 05283 } 05284 if (home_info.raised == MatteIsActive(home_info,event.xmotion)) 05285 { 05286 /* 05287 Home button status changed. 05288 */ 05289 home_info.raised=!home_info.raised; 05290 XDrawBeveledButton(display,&windows->widget,&home_info); 05291 break; 05292 } 05293 if (special_info.raised == MatteIsActive(special_info,event.xmotion)) 05294 { 05295 /* 05296 Grab button status changed. 05297 */ 05298 special_info.raised=!special_info.raised; 05299 XDrawBeveledButton(display,&windows->widget,&special_info); 05300 break; 05301 } 05302 if (action_info.raised == MatteIsActive(action_info,event.xmotion)) 05303 { 05304 /* 05305 Action button status changed. 05306 */ 05307 action_info.raised=action_info.raised == MagickFalse ? 05308 MagickTrue : MagickFalse; 05309 XDrawBeveledButton(display,&windows->widget,&action_info); 05310 break; 05311 } 05312 if (cancel_info.raised == MatteIsActive(cancel_info,event.xmotion)) 05313 { 05314 /* 05315 Cancel button status changed. 05316 */ 05317 cancel_info.raised=cancel_info.raised == MagickFalse ? 05318 MagickTrue : MagickFalse; 05319 XDrawBeveledButton(display,&windows->widget,&cancel_info); 05320 break; 05321 } 05322 break; 05323 } 05324 case SelectionClear: 05325 { 05326 reply_info.highlight=MagickFalse; 05327 XDrawMatteText(display,&windows->widget,&reply_info); 05328 break; 05329 } 05330 case SelectionNotify: 05331 { 05332 Atom 05333 type; 05334 05335 int 05336 format; 05337 05338 unsigned char 05339 *data; 05340 05341 unsigned long 05342 after, 05343 length; 05344 05345 /* 05346 Obtain response from primary selection. 05347 */ 05348 if (event.xselection.property == (Atom) None) 05349 break; 05350 status=XGetWindowProperty(display,event.xselection.requestor, 05351 event.xselection.property,0L,2047L,MagickTrue,XA_STRING,&type, 05352 &format,&length,&after,&data); 05353 if ((status != Success) || (type != XA_STRING) || (format == 32) || 05354 (length == 0)) 05355 break; 05356 if ((Extent(reply_info.text)+length) >= (MaxTextExtent-1)) 05357 (void) XBell(display,0); 05358 else 05359 { 05360 /* 05361 Insert primary selection in reply text. 05362 */ 05363 *(data+length)='\0'; 05364 XEditText(display,&reply_info,(KeySym) XK_Insert,(char *) data, 05365 state); 05366 XDrawMatteText(display,&windows->widget,&reply_info); 05367 state|=JumpListState; 05368 state|=RedrawActionState; 05369 } 05370 (void) XFree((void *) data); 05371 break; 05372 } 05373 case SelectionRequest: 05374 { 05375 XSelectionEvent 05376 notify; 05377 05378 XSelectionRequestEvent 05379 *request; 05380 05381 if (reply_info.highlight == MagickFalse) 05382 break; 05383 /* 05384 Set primary selection. 05385 */ 05386 request=(&(event.xselectionrequest)); 05387 (void) XChangeProperty(request->display,request->requestor, 05388 request->property,request->target,8,PropModeReplace, 05389 (unsigned char *) primary_selection,Extent(primary_selection)); 05390 notify.type=SelectionNotify; 05391 notify.display=request->display; 05392 notify.requestor=request->requestor; 05393 notify.selection=request->selection; 05394 notify.target=request->target; 05395 notify.time=request->time; 05396 if (request->property == None) 05397 notify.property=request->target; 05398 else 05399 notify.property=request->property; 05400 (void) XSendEvent(request->display,request->requestor,False,0, 05401 (XEvent *) ¬ify); 05402 } 05403 default: 05404 break; 05405 } 05406 } while ((state & ExitState) == 0); 05407 XSetCursorState(display,windows,MagickFalse); 05408 (void) XWithdrawWindow(display,windows->widget.id,windows->widget.screen); 05409 XCheckRefreshWindows(display,windows); 05410 /* 05411 Free file list. 05412 */ 05413 for (i=0; i < (ssize_t) files; i++) 05414 filelist[i]=DestroyString(filelist[i]); 05415 if (filelist != (char **) NULL) 05416 filelist=(char **) RelinquishMagickMemory(filelist); 05417 if (*reply != '\0') 05418 { 05419 (void) ConcatenateMagickString(working_path,DirectorySeparator, 05420 MaxTextExtent); 05421 (void) ConcatenateMagickString(working_path,reply,MaxTextExtent); 05422 } 05423 (void) CopyMagickString(reply,working_path,MaxTextExtent); 05424 if (*reply == '~') 05425 ExpandFilename(reply); 05426 } 05427 05428 /* 05429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 05430 % % 05431 % % 05432 % % 05433 % X F o n t B r o w s e r W i d g e t % 05434 % % 05435 % % 05436 % % 05437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 05438 % 05439 % XFontBrowserWidget() displays a Font Browser widget with a font query to the 05440 % user. The user keys a reply and presses the Action or Cancel button to 05441 % exit. The typed text is returned as the reply function parameter. 05442 % 05443 % The format of the XFontBrowserWidget method is: 05444 % 05445 % void XFontBrowserWidget(Display *display,XWindows *windows, 05446 % const char *action,char *reply) 05447 % 05448 % A description of each parameter follows: 05449 % 05450 % o display: Specifies a connection to an X server; returned from 05451 % XOpenDisplay. 05452 % 05453 % o window: Specifies a pointer to a XWindows structure. 05454 % 05455 % o action: Specifies a pointer to the action of this widget. 05456 % 05457 % o reply: the response from the user is returned in this parameter. 05458 % 05459 % 05460 */ 05461 05462 #if defined(__cplusplus) || defined(c_plusplus) 05463 extern "C" { 05464 #endif 05465 05466 static int FontCompare(const void *x,const void *y) 05467 { 05468 register char 05469 *p, 05470 *q; 05471 05472 p=(char *) *((char **) x); 05473 q=(char *) *((char **) y); 05474 while ((*p != '\0') && (*q != '\0') && (*p == *q)) 05475 { 05476 p++; 05477 q++; 05478 } 05479 return(*p-(*q)); 05480 } 05481 05482 #if defined(__cplusplus) || defined(c_plusplus) 05483 } 05484 #endif 05485 05486 MagickPrivate void XFontBrowserWidget(Display *display,XWindows *windows, 05487 const char *action,char *reply) 05488 { 05489 #define BackButtonText "Back" 05490 #define CancelButtonText "Cancel" 05491 #define FontnameText "Name:" 05492 #define FontPatternText "Pattern:" 05493 #define ResetButtonText "Reset" 05494 05495 char 05496 back_pattern[MaxTextExtent], 05497 **fontlist, 05498 **listhead, 05499 primary_selection[MaxTextExtent], 05500 reset_pattern[MaxTextExtent], 05501 text[MaxTextExtent]; 05502 05503 int 05504 fonts, 05505 x, 05506 y; 05507 05508 register int 05509 i; 05510 05511 static char 05512 glob_pattern[MaxTextExtent] = "*"; 05513 05514 static MagickStatusType 05515 mask = (MagickStatusType) (CWWidth | CWHeight | CWX | CWY); 05516 05517 Status 05518 status; 05519 05520 unsigned int 05521 height, 05522 text_width, 05523 visible_fonts, 05524 width; 05525 05526 size_t 05527 delay, 05528 state; 05529 05530 XEvent 05531 event; 05532 05533 XFontStruct 05534 *font_info; 05535 05536 XTextProperty 05537 window_name; 05538 05539 XWidgetInfo 05540 action_info, 05541 back_info, 05542 cancel_info, 05543 expose_info, 05544 list_info, 05545 mode_info, 05546 north_info, 05547 reply_info, 05548 reset_info, 05549 scroll_info, 05550 selection_info, 05551 slider_info, 05552 south_info, 05553 text_info; 05554 05555 XWindowChanges 05556 window_changes; 05557 05558 /* 05559 Get font list and sort in ascending order. 05560 */ 05561 assert(display != (Display *) NULL); 05562 assert(windows != (XWindows *) NULL); 05563 assert(action != (char *) NULL); 05564 assert(reply != (char *) NULL); 05565 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",action); 05566 XSetCursorState(display,windows,MagickTrue); 05567 XCheckRefreshWindows(display,windows); 05568 (void) CopyMagickString(back_pattern,glob_pattern,MaxTextExtent); 05569 (void) CopyMagickString(reset_pattern,"*",MaxTextExtent); 05570 fontlist=XListFonts(display,glob_pattern,32767,&fonts); 05571 if (fonts == 0) 05572 { 05573 /* 05574 Pattern failed, obtain all the fonts. 05575 */ 05576 XNoticeWidget(display,windows,"Unable to obtain fonts names:", 05577 glob_pattern); 05578 (void) CopyMagickString(glob_pattern,"*",MaxTextExtent); 05579 fontlist=XListFonts(display,glob_pattern,32767,&fonts); 05580 if (fontlist == (char **) NULL) 05581 { 05582 XNoticeWidget(display,windows,"Unable to obtain fonts names:", 05583 glob_pattern); 05584 return; 05585 } 05586 } 05587 /* 05588 Sort font list in ascending order. 05589 */ 05590 listhead=fontlist; 05591 fontlist=(char **) AcquireQuantumMemory((size_t) fonts,sizeof(*fontlist)); 05592 if (fontlist == (char **) NULL) 05593 { 05594 XNoticeWidget(display,windows,"MemoryAllocationFailed", 05595 "UnableToViewFonts"); 05596 return; 05597 } 05598 for (i=0; i < fonts; i++) 05599 fontlist[i]=listhead[i]; 05600 qsort((void *) fontlist,(size_t) fonts,sizeof(*fontlist),FontCompare); 05601 /* 05602 Determine Font Browser widget attributes. 05603 */ 05604 font_info=windows->widget.font_info; 05605 text_width=0; 05606 for (i=0; i < fonts; i++) 05607 if (WidgetTextWidth(font_info,fontlist[i]) > text_width) 05608 text_width=WidgetTextWidth(font_info,fontlist[i]); 05609 width=WidgetTextWidth(font_info,(char *) action); 05610 if (WidgetTextWidth(font_info,CancelButtonText) > width) 05611 width=WidgetTextWidth(font_info,CancelButtonText); 05612 if (WidgetTextWidth(font_info,ResetButtonText) > width) 05613 width=WidgetTextWidth(font_info,ResetButtonText); 05614 if (WidgetTextWidth(font_info,BackButtonText) > width) 05615 width=WidgetTextWidth(font_info,BackButtonText); 05616 width+=QuantumMargin; 05617 if (WidgetTextWidth(font_info,FontPatternText) > width) 05618 width=WidgetTextWidth(font_info,FontPatternText); 05619 if (WidgetTextWidth(font_info,FontnameText) > width) 05620 width=WidgetTextWidth(font_info,FontnameText); 05621 height=(unsigned int) (font_info->ascent+font_info->descent); 05622 /* 05623 Position Font Browser widget. 05624 */ 05625 windows->widget.width=width+MagickMin((int) text_width,(int) MaxTextWidth)+ 05626 6*QuantumMargin; 05627 windows->widget.min_width=width+MinTextWidth+4*QuantumMargin; 05628 if (windows->widget.width < windows->widget.min_width) 05629 windows->widget.width=windows->widget.min_width; 05630 windows->widget.height=(unsigned int) 05631 (((85*height) >> 2)+((13*QuantumMargin) >> 1)+4); 05632 windows->widget.min_height=(unsigned int) 05633 (((27*height) >> 1)+((13*QuantumMargin) >> 1)+4); 05634 if (windows->widget.height < windows->widget.min_height) 05635 windows->widget.height=windows->widget.min_height; 05636 XConstrainWindowPosition(display,&windows->widget); 05637 /* 05638 Map Font Browser widget. 05639 */ 05640 (void) CopyMagickString(windows->widget.name,"Browse and Select a Font", 05641 MaxTextExtent); 05642 status=XStringListToTextProperty(&windows->widget.name,1,&window_name); 05643 if (status != False) 05644 { 05645 XSetWMName(display,windows->widget.id,&window_name); 05646 XSetWMIconName(display,windows->widget.id,&window_name); 05647 (void) XFree((void *) window_name.value); 05648 } 05649 window_changes.width=(int) windows->widget.width; 05650 window_changes.height=(int) windows->widget.height; 05651 window_changes.x=windows->widget.x; 05652 window_changes.y=windows->widget.y; 05653 (void) XReconfigureWMWindow(display,windows->widget.id, 05654 windows->widget.screen,mask,&window_changes); 05655 (void) XMapRaised(display,windows->widget.id); 05656 windows->widget.mapped=MagickFalse; 05657 /* 05658 Respond to X events. 05659 */ 05660 XGetWidgetInfo((char *) NULL,&slider_info); 05661 XGetWidgetInfo((char *) NULL,&north_info); 05662 XGetWidgetInfo((char *) NULL,&south_info); 05663 XGetWidgetInfo((char *) NULL,&expose_info); 05664 visible_fonts=0; 05665 delay=SuspendTime << 2; 05666 state=UpdateConfigurationState; 05667 do 05668 { 05669 if (state & UpdateConfigurationState) 05670 { 05671 int 05672 id; 05673 05674 /* 05675 Initialize button information. 05676 */ 05677 XGetWidgetInfo(CancelButtonText,&cancel_info); 05678 cancel_info.width=width; 05679 cancel_info.height=(unsigned int) ((3*height) >> 1); 05680 cancel_info.x=(int) 05681 (windows->widget.width-cancel_info.width-QuantumMargin-2); 05682 cancel_info.y=(int) 05683 (windows->widget.height-cancel_info.height-QuantumMargin); 05684 XGetWidgetInfo(action,&action_info); 05685 action_info.width=width; 05686 action_info.height=(unsigned int) ((3*height) >> 1); 05687 action_info.x=cancel_info.x-(cancel_info.width+(QuantumMargin >> 1)+ 05688 (action_info.bevel_width << 1)); 05689 action_info.y=cancel_info.y; 05690 XGetWidgetInfo(BackButtonText,&back_info); 05691 back_info.width=width; 05692 back_info.height=(unsigned int) ((3*height) >> 1); 05693 back_info.x=QuantumMargin; 05694 back_info.y=((5*QuantumMargin) >> 1)+height; 05695 XGetWidgetInfo(ResetButtonText,&reset_info); 05696 reset_info.width=width; 05697 reset_info.height=(unsigned int) ((3*height) >> 1); 05698 reset_info.x=QuantumMargin; 05699 reset_info.y=back_info.y+back_info.height+QuantumMargin; 05700 /* 05701 Initialize reply information. 05702 */ 05703 XGetWidgetInfo(reply,&reply_info); 05704 reply_info.raised=MagickFalse; 05705 reply_info.bevel_width--; 05706 reply_info.width=windows->widget.width-width-((6*QuantumMargin) >> 1); 05707 reply_info.height=height << 1; 05708 reply_info.x=(int) (width+(QuantumMargin << 1)); 05709 reply_info.y=action_info.y-(action_info.height << 1)-QuantumMargin; 05710 /* 05711 Initialize mode information. 05712 */ 05713 XGetWidgetInfo(reply,&mode_info); 05714 mode_info.bevel_width=0; 05715 mode_info.width=(unsigned int) 05716 (action_info.x-reply_info.x-QuantumMargin); 05717 mode_info.height=action_info.height << 1; 05718 mode_info.x=reply_info.x; 05719 mode_info.y=action_info.y-action_info.height+action_info.bevel_width; 05720 /* 05721 Initialize scroll information. 05722 */ 05723 XGetWidgetInfo((char *) NULL,&scroll_info); 05724 scroll_info.bevel_width--; 05725 scroll_info.width=height; 05726 scroll_info.height=(unsigned int) 05727 (reply_info.y-back_info.y-(QuantumMargin >> 1)); 05728 scroll_info.x=reply_info.x+(reply_info.width-scroll_info.width); 05729 scroll_info.y=back_info.y-reply_info.bevel_width; 05730 scroll_info.raised=MagickFalse; 05731 scroll_info.trough=MagickTrue; 05732 north_info=scroll_info; 05733 north_info.raised=MagickTrue; 05734 north_info.width-=(north_info.bevel_width << 1); 05735 north_info.height=north_info.width-1; 05736 north_info.x+=north_info.bevel_width; 05737 north_info.y+=north_info.bevel_width; 05738 south_info=north_info; 05739 south_info.y=scroll_info.y+scroll_info.height-scroll_info.bevel_width- 05740 south_info.height; 05741 id=slider_info.id; 05742 slider_info=north_info; 05743 slider_info.id=id; 05744 slider_info.width-=2; 05745 slider_info.min_y=north_info.y+north_info.height+north_info.bevel_width+ 05746 slider_info.bevel_width+2; 05747 slider_info.height=scroll_info.height-((slider_info.min_y- 05748 scroll_info.y+1) << 1)+4; 05749 visible_fonts=scroll_info.height/(height+(height >> 3)); 05750 if (fonts > (int) visible_fonts) 05751 slider_info.height=(visible_fonts*slider_info.height)/fonts; 05752 slider_info.max_y=south_info.y-south_info.bevel_width- 05753 slider_info.bevel_width-2; 05754 slider_info.x=scroll_info.x+slider_info.bevel_width+1; 05755 slider_info.y=slider_info.min_y; 05756 expose_info=scroll_info; 05757 expose_info.y=slider_info.y; 05758 /* 05759 Initialize list information. 05760 */ 05761 XGetWidgetInfo((char *) NULL,&list_info); 05762 list_info.raised=MagickFalse; 05763 list_info.bevel_width--; 05764 list_info.width=(unsigned int) 05765 (scroll_info.x-reply_info.x-(QuantumMargin >> 1)); 05766 list_info.height=scroll_info.height; 05767 list_info.x=reply_info.x; 05768 list_info.y=scroll_info.y; 05769 if (windows->widget.mapped == MagickFalse) 05770 state|=JumpListState; 05771 /* 05772