1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/dialog.c,v 1.10 2011/05/16 16:21:57 william Exp $
19 */
20
21 #define _INCLUDE_FROM_DIALOG_C_
22
23 #include "tgifdefs.h"
24
25 #include "auxtext.e"
26 #include "box.e"
27 #include "button.e"
28 #include "cutpaste.e"
29 #include "cursor.e"
30 #include "dialog.e"
31 #include "drawing.e"
32 #include "file.e"
33 #include "font.e"
34 #include "grid.e"
35 #include "mainloop.e"
36 #include "mainmenu.e"
37 #include "menu.e"
38 #include "msg.e"
39 #include "raster.e"
40 #include "rect.e"
41 #include "ruler.e"
42 #include "setup.e"
43 #include "strtbl.e"
44 #include "text.e"
45 #include "util.e"
46
47 int doPassword=FALSE;
48 char gszMsgBox[2048];
49
50 int dialogboxUse3DBorder=TRUE;
51
CornerLoop(OrigX,OrigY)52 unsigned int CornerLoop(OrigX, OrigY)
53 int *OrigX, *OrigY;
54 {
55 XEvent input;
56
57 XGrabPointer(mainDisplay, rootWindow, False, ButtonPressMask,
58 GrabModeAsync, GrabModeAsync, None, cornerCursor, CurrentTime);
59
60 for (;;) {
61 XNextEvent(mainDisplay, &input);
62
63 if (input.type == Expose || input.type == VisibilityNotify) {
64 ExposeEventHandler(&input, TRUE);
65 } else if (input.type == ButtonPress) {
66 XUngrabPointer(mainDisplay, CurrentTime);
67 XSync(mainDisplay, False);
68 *OrigX = input.xbutton.x;
69 *OrigY = input.xbutton.y;
70 return input.xbutton.button;
71 }
72 }
73 }
74
75 static XComposeStatus c_stat;
76
DrawWindowLoop(OrigX,OrigY,cursor,snap_to_grid)77 unsigned int DrawWindowLoop(OrigX, OrigY, cursor, snap_to_grid)
78 int *OrigX, *OrigY, snap_to_grid;
79 Cursor cursor;
80 {
81 Window focus_win=None;
82 int revert_to=0;
83
84 XGetInputFocus(mainDisplay, &focus_win, &revert_to);
85 XGrabPointer(mainDisplay, drawWindow, False,
86 PointerMotionMask | ButtonPressMask,
87 GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
88
89 for (;;) {
90 XEvent input;
91
92 XNextEvent(mainDisplay, &input);
93
94 if (input.type == Expose || input.type == VisibilityNotify) {
95 ExposeEventHandler(&input, TRUE);
96 } else if (input.type == ButtonPress) {
97 XUngrabPointer(mainDisplay, CurrentTime);
98 if (focus_win != mainWindow) {
99 XSetInputFocus(mainDisplay, mainWindow, RevertToPointerRoot,
100 CurrentTime);
101 }
102 XSync(mainDisplay, False);
103 *OrigX = input.xbutton.x;
104 *OrigY = input.xbutton.y;
105 return input.xbutton.button;
106 } else if (input.type == KeyPress) {
107 if (KeyPressEventIsEscape(&input.xkey)) {
108 XUngrabPointer(mainDisplay, CurrentTime);
109 if (focus_win != mainWindow) {
110 XSetInputFocus(mainDisplay, mainWindow, RevertToPointerRoot,
111 CurrentTime);
112 }
113 XSync(mainDisplay, False);
114 return (unsigned int)(-1);
115 }
116 } else if (input.type == MotionNotify) {
117 if (snap_to_grid) {
118 int grid_x, grid_y;
119
120 GridXY(input.xmotion.x, input.xmotion.y, &grid_x, &grid_y);
121 MarkRulers(grid_x, grid_y);
122 } else {
123 MarkRulers(input.xmotion.x, input.xmotion.y);
124 }
125 }
126 }
127 }
128
PickAPoint(OrigX,OrigY,cursor)129 unsigned int PickAPoint(OrigX, OrigY, cursor)
130 int *OrigX, *OrigY;
131 Cursor cursor;
132 {
133 XEvent input;
134
135 #ifdef _TGIF_DBG
136 if (!debugNoPointerGrab) {
137 #endif /* _TGIF_DBG */
138 XGrabPointer(mainDisplay, drawWindow, False, ButtonPressMask,
139 GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
140 #ifdef _TGIF_DBG
141 }
142 #endif /* _TGIF_DBG */
143 for (;;) {
144 XNextEvent(mainDisplay, &input);
145
146 if (input.type == Expose || input.type == VisibilityNotify) {
147 ExposeEventHandler(&input, TRUE);
148 } else if (input.type == ButtonPress) {
149 XUngrabPointer(mainDisplay, CurrentTime);
150 XSync(mainDisplay, False);
151 *OrigX = input.xbutton.x;
152 *OrigY = input.xbutton.y;
153 return input.xbutton.button;
154 } else if (input.type == KeyPress) {
155 if (KeyPressEventIsEscape(&input.xkey)) {
156 XUngrabPointer(mainDisplay, CurrentTime);
157 XSync(mainDisplay, False);
158 return (unsigned int)(-1);
159 }
160 }
161 }
162 }
163
164 #include "xbm/info.xbm"
165
166 #define ICON_W (info_width)
167 #define ICON_H (info_height)
168
169 #define X_MARGIN 20
170 #define Y_MARGIN 16
171 #define X_GAP 20
172 #define Y_GAP 20
173
174 #define SPACING 0
175
176 #define BTN_X_MARGIN 8
177 #define BTN_Y_MARGIN 2
178 #define BTN_XY_EXTRA 2
179 #define BTN_MIN_X_GAP 8
180
181 #define MAX_KEYSYMS 10
182
183 #define LF_BUTTON 0x01
184 #define MD_BUTTON 0x02
185 #define RT_BUTTON 0x03
186 #define XT_BUTTON 0x04
187
188 #define DEF_BUTTON 0x10
189
190 #define MAX_BUTTONS 3
191 #define MAX_BTN_STR_LEN 10
192
193 typedef struct BtnInfoRec {
194 char * str;
195 struct BBRec bbox;
196 int id, highlight;
197 KeySym key_sym[MAX_KEYSYMS];
198 } * BtnInfoRecPtr;
199
200 typedef struct MBRec {
201 Window main_win, root_win, icon_win, msg_win, btn_win;
202
203 int main_win_x, main_win_y, main_win_w, main_win_h;
204 int icon_win_w, icon_win_h, msg_win_w, msg_win_h;
205 int btn_win_w, btn_win_h, max_msg_win_w;
206 int max_msg_str_len, max_msg_str_total;
207 int exposed;
208
209 char * msg_copy;
210
211 Pixmap cur_bitmap;
212
213 struct BtnInfoRec btn_info[MAX_BUTTONS+1];
214
215 /* dialog specific */
216 int is_dialog;
217 int cur_x, cur_y, cursor_x, cursor_y, index, str_w;
218 char *return_str;
219 } * MBRecPtr;
220
221 static struct MBRec mbInfo;
222
223 static int numButtons=MAX_BUTTONS;
224 static char extraBtnChar='q';
225
226 static
SetupMBButton(MBInfoPtr,BtnDesc,BtnCh,BtnID)227 void SetupMBButton(MBInfoPtr, BtnDesc, BtnCh, BtnID)
228 struct MBRec *MBInfoPtr;
229 int BtnDesc, BtnID;
230 char BtnCh;
231 {
232 char *psz=NULL;
233 int btn_index=(BtnDesc & 0x0f)-1, i=0;
234
235 switch (BtnID) {
236 case MB_ID_FAILED: psz = NULL; break;
237 case MB_ID_OK: psz = TgLoadCachedString(CSTID_OK); break;
238 case MB_ID_CANCEL: psz = TgLoadCachedString(CSTID_CANCEL); break;
239 case MB_ID_YES: psz = TgLoadCachedString(CSTID_YES); break;
240 case MB_ID_NO: psz = TgLoadCachedString(CSTID_NO); break;
241 case MB_ID_EXTRA: psz = TgLoadCachedString(CSTID_EXTRA); break;
242 }
243 MBInfoPtr->btn_info[btn_index].str = psz;
244
245 MBInfoPtr->btn_info[btn_index].id = BtnID;
246 switch (BtnCh) {
247 case 'o':
248 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_o;
249 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_O;
250 break;
251 case 'y':
252 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_y;
253 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_Y;
254 break;
255 case 'n':
256 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_n;
257 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_N;
258 break;
259 case 'c':
260 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_c;
261 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_C;
262 break;
263 }
264 if (BtnDesc & DEF_BUTTON) {
265 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_Return;
266 MBInfoPtr->btn_info[btn_index].key_sym[i++] = XK_Linefeed;
267 MBInfoPtr->btn_info[btn_index].highlight = TRUE;
268 } else {
269 MBInfoPtr->btn_info[btn_index].highlight = FALSE;
270 }
271 MBInfoPtr->btn_info[btn_index].key_sym[i] = (KeySym)0;
272 }
273
CalcFormatStringInBox(buf,xfs,font_height,format_box_w,pn_num_lines,pn_max_w,pn_max_h,ppsz_formated_buf)274 void CalcFormatStringInBox(buf, xfs, font_height, format_box_w, pn_num_lines,
275 pn_max_w, pn_max_h, ppsz_formated_buf)
276 char *buf, **ppsz_formated_buf;
277 XFontStruct *xfs;
278 int font_height, format_box_w, *pn_num_lines, *pn_max_w, *pn_max_h;
279 {
280 char *dest_ptr=NULL, *c_ptr=NULL, *msg_copy=NULL;
281 int len=strlen(buf), max_len=0, max_w=0, max_h=0, total=0;
282 int num_lines=1, spacing=SPACING, sz=((((len+10)<<1)+1)*sizeof(char));
283
284 total = BoldMsgTextWidth(xfs, buf, len);
285
286 msg_copy = (char*)malloc(sz);
287 if (msg_copy == NULL) FailAllocMessage();
288 memset(msg_copy, 0, sz);
289
290 dest_ptr = msg_copy;
291 *dest_ptr = '\0';
292 c_ptr = buf;
293 while (c_ptr != NULL) {
294 /* a line at a time */
295 char *lf_ptr=BoldMsgStrChr(c_ptr, '\n');
296 int full_str_len, full_str_total;
297
298 if (lf_ptr != NULL) *lf_ptr = '\0';
299 full_str_len = strlen(c_ptr);
300 full_str_total = BoldMsgTextWidth(xfs, c_ptr, full_str_len);
301 if (full_str_total > max_w) {
302 if (full_str_total > format_box_w) {
303 /* line too long for the message box */
304 char *line=c_ptr;
305
306 max_w = format_box_w;
307 while (line != NULL && *line != '\0') {
308 int line_len, line_total;
309
310 while (*line == ' ') line++;
311 line_len = strlen(line);
312 line_total = BoldMsgTextWidth(xfs, line, line_len);
313 if (line_total > format_box_w) {
314 char *lead_ptr=line, *last_ptr=NULL, saved_last_ch='\0';
315 int lead_index=0, last_index=0, still_going=TRUE;
316
317 while (still_going && *lead_ptr != '\0') {
318 char saved_ch='\0';
319 int w=0;
320
321 while (*lead_ptr != ' ' && *lead_ptr != '\0') {
322 if (BoldMsgCharBytes(lead_ptr) == 2) {
323 /* for double-byte chars, one can break anywhere */
324 break;
325 }
326 lead_ptr++;
327 lead_index++;
328 }
329 saved_ch = (*lead_ptr);
330 *lead_ptr = '\0';
331 w = BoldMsgTextWidth(xfs, line, lead_index);
332 if (w > format_box_w) {
333 if (last_ptr == NULL) {
334 /* very long word */
335 sprintf(dest_ptr, "%s\n", line);
336 dest_ptr = &dest_ptr[strlen(dest_ptr)];
337 max_h += font_height+spacing;
338 num_lines++;
339 line = &line[lead_index];
340 } else {
341 /* find a good space */
342 saved_last_ch = (*last_ptr);
343 *last_ptr = '\0';
344 sprintf(dest_ptr, "%s\n", line);
345 *last_ptr = saved_last_ch;
346 dest_ptr = &dest_ptr[strlen(dest_ptr)];
347 max_h += font_height+spacing;
348 num_lines++;
349 line = BoldMsgNextChar(&line[last_index]);
350 }
351 still_going = FALSE;
352 } else {
353 last_ptr = lead_ptr;
354 last_index = lead_index;
355 }
356 *lead_ptr++ = saved_ch;
357 lead_index++;
358 }
359 if (still_going && *lead_ptr == '\0') {
360 if (last_ptr == NULL) {
361 /* very long word */
362 sprintf(dest_ptr, "%s\n", line);
363 dest_ptr = &dest_ptr[strlen(dest_ptr)];
364 max_h += font_height+spacing;
365 num_lines++;
366 line = &line[lead_index];
367 } else {
368 /* find a good space */
369 saved_last_ch = (*last_ptr);
370 *last_ptr = '\0';
371 sprintf(dest_ptr, "%s\n", line);
372 *last_ptr = saved_last_ch;
373 dest_ptr = &dest_ptr[strlen(dest_ptr)];
374 max_h += font_height+spacing;
375 num_lines++;
376 line = BoldMsgNextChar(&line[last_index]);
377 }
378 }
379 } else if (line_len > 0) {
380 sprintf(dest_ptr, "%s\n", line);
381 dest_ptr = &dest_ptr[strlen(dest_ptr)];
382 max_h += font_height+spacing;
383 break;
384 }
385 }
386 } else {
387 max_len = full_str_len;
388 max_w = full_str_total;
389 sprintf(dest_ptr, "%s\n", c_ptr);
390 dest_ptr = &dest_ptr[strlen(dest_ptr)];
391 max_h += font_height+spacing;
392 if (lf_ptr != NULL) num_lines++;
393 }
394 } else {
395 sprintf(dest_ptr, "%s\n", c_ptr);
396 dest_ptr = &dest_ptr[strlen(dest_ptr)];
397 max_h += font_height+spacing;
398 if (lf_ptr != NULL) num_lines++;
399 }
400 max_h -= spacing;
401 if (lf_ptr != NULL) {
402 *lf_ptr = '\n';
403 c_ptr = &lf_ptr[1];
404 } else {
405 break;
406 }
407 }
408 if (pn_num_lines != NULL) *pn_num_lines = num_lines;
409 if (pn_max_w != NULL) *pn_max_w = max_w;
410 if (pn_max_h != NULL) *pn_max_h = max_h;
411 if (ppsz_formated_buf == NULL) {
412 free(msg_copy);
413 } else {
414 *ppsz_formated_buf = msg_copy;
415 }
416 }
417
418 static
CalcSimpleGeometry(MBInfoPtr,Message)419 void CalcSimpleGeometry(MBInfoPtr, Message)
420 struct MBRec *MBInfoPtr;
421 char *Message;
422 {
423 int i=0, max_h=0, left=0, inc=0, a_btn_w=0, a_btn_h=0, y=0, max_w=0;;
424
425 CalcFormatStringInBox(Message, defaultFontPtr, defaultFontHeight,
426 MBInfoPtr->max_msg_str_total, NULL, &max_w, &max_h,
427 &MBInfoPtr->msg_copy);
428
429 if (MBInfoPtr->is_dialog) {
430 MBInfoPtr->msg_win_w = MBInfoPtr->max_msg_str_total;
431 } else {
432 MBInfoPtr->msg_win_w = max_w;
433 }
434 MBInfoPtr->msg_win_h = max_h;
435 MBInfoPtr->icon_win_w = ICON_W;
436 MBInfoPtr->icon_win_h = ICON_H;
437 if (info_bits == NULL) { }
438 if (MBInfoPtr->msg_win_h > MBInfoPtr->icon_win_h) {
439 MBInfoPtr->icon_win_h = MBInfoPtr->msg_win_h;
440 } else {
441 MBInfoPtr->msg_win_h = MBInfoPtr->icon_win_h;
442 }
443 a_btn_w = MAX_BTN_STR_LEN*defaultFontWidth + (BTN_XY_EXTRA<<1);
444 if (MBInfoPtr->is_dialog) {
445 if (msgFontSet == NULL && msgFontPtr == NULL) {
446 a_btn_h = defaultFontHeight + (BTN_Y_MARGIN<<1) + (BTN_XY_EXTRA<<1);
447 } else {
448 a_btn_h = msgFontHeight + (BTN_Y_MARGIN<<1) + (BTN_XY_EXTRA<<1);
449 }
450 } else {
451 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
452 a_btn_h = defaultFontHeight + (BTN_Y_MARGIN<<1) + (BTN_XY_EXTRA<<1);
453 } else {
454 a_btn_h = boldMsgFontHeight + (BTN_Y_MARGIN<<1) + (BTN_XY_EXTRA<<1);
455 }
456 }
457
458 MBInfoPtr->btn_win_w = numButtons*a_btn_w+BTN_MIN_X_GAP*(numButtons-1)+2;
459 MBInfoPtr->btn_win_h = a_btn_h+2+(windowPadding<<2);
460
461 if (MBInfoPtr->btn_win_w >
462 MBInfoPtr->msg_win_w+MBInfoPtr->icon_win_w+X_GAP) {
463 MBInfoPtr->msg_win_w =
464 MBInfoPtr->btn_win_w-MBInfoPtr->icon_win_w-X_GAP;
465 } else {
466 MBInfoPtr->btn_win_w =
467 MBInfoPtr->msg_win_w+MBInfoPtr->icon_win_w+X_GAP;
468 }
469 MBInfoPtr->main_win_w = MBInfoPtr->btn_win_w + (X_MARGIN<<1) +
470 (brdrW<<1);
471 MBInfoPtr->main_win_h = MBInfoPtr->icon_win_h + MBInfoPtr->btn_win_h +
472 (Y_MARGIN<<1) + Y_GAP + (brdrW<<1);
473 left = ((MBInfoPtr->btn_win_w - numButtons*a_btn_w -
474 BTN_MIN_X_GAP*(numButtons-1))>>1);
475 inc = a_btn_w + ((MBInfoPtr->btn_win_w-(left<<1)-numButtons*a_btn_w) /
476 (numButtons-1));
477 y = ((MBInfoPtr->btn_win_h - ((BTN_Y_MARGIN<<1) +
478 ((boldMsgFontSet==NULL && boldMsgFontPtr==NULL) ? defaultFontHeight :
479 boldMsgFontHeight))) >> 1);
480 for (i=0; i < numButtons; i++) {
481 MBInfoPtr->btn_info[i].bbox.ltx = left+BTN_XY_EXTRA;
482 MBInfoPtr->btn_info[i].bbox.lty = y;
483 MBInfoPtr->btn_info[i].bbox.rbx = left +
484 MAX_BTN_STR_LEN*defaultFontWidth + BTN_XY_EXTRA;
485 MBInfoPtr->btn_info[i].bbox.rby = y + (BTN_Y_MARGIN<<1) +
486 ((boldMsgFontSet==NULL && boldMsgFontPtr==NULL) ?
487 defaultFontHeight : boldMsgFontHeight);
488 left += inc;
489 }
490 MBInfoPtr->main_win_x = ((DisplayWidth(mainDisplay, mainScreen) -
491 MBInfoPtr->main_win_w)>>1);
492 MBInfoPtr->main_win_y = ((DisplayHeight(mainDisplay, mainScreen) -
493 MBInfoPtr->main_win_h)/3);
494 if (MBInfoPtr->main_win_x < 0) MBInfoPtr->main_win_x = 0;
495 if (MBInfoPtr->main_win_y < 0) MBInfoPtr->main_win_y = 0;
496 }
497
498 static
CalcGeometry(MBInfoPtr,Message)499 void CalcGeometry(MBInfoPtr, Message)
500 struct MBRec *MBInfoPtr;
501 char *Message;
502 {
503 int i=0, max_h=0, left=0, inc=0, a_btn_w=0, a_btn_h=0;
504 int font_height=boldMsgFontHeight, y=0, max_w=0;
505
506 CalcFormatStringInBox(Message, boldMsgFontPtr, boldMsgFontHeight,
507 MBInfoPtr->max_msg_str_total, NULL, &max_w, &max_h,
508 &MBInfoPtr->msg_copy);
509
510 if (MBInfoPtr->is_dialog) {
511 MBInfoPtr->msg_win_w = MBInfoPtr->max_msg_str_total;
512 } else {
513 MBInfoPtr->msg_win_w = max_w;
514 }
515 MBInfoPtr->msg_win_h = max_h;
516 MBInfoPtr->icon_win_w = ICON_W;
517 MBInfoPtr->icon_win_h = ICON_H;
518 if (MBInfoPtr->msg_win_h > MBInfoPtr->icon_win_h) {
519 MBInfoPtr->icon_win_h = MBInfoPtr->msg_win_h;
520 } else {
521 MBInfoPtr->msg_win_h = MBInfoPtr->icon_win_h;
522 }
523 /* do not translate -- the string is used to measure things */
524 a_btn_w = BoldMsgTextWidth(boldMsgFontPtr, " CANCEL ", 10) +
525 (BTN_XY_EXTRA<<1);
526 if (MBInfoPtr->is_dialog) {
527 a_btn_h = (BTN_Y_MARGIN<<1) + (BTN_XY_EXTRA<<1) +
528 ((msgFontSet==NULL && msgFontPtr==NULL) ? defaultFontHeight :
529 msgFontHeight);
530 } else {
531 a_btn_h = (BTN_Y_MARGIN<<1) + (BTN_XY_EXTRA<<1) +
532 ((boldMsgFontSet==NULL && boldMsgFontPtr==NULL) ?
533 defaultFontHeight : boldMsgFontHeight);
534 }
535 MBInfoPtr->btn_win_w = numButtons*a_btn_w+BTN_MIN_X_GAP*(numButtons-1)+2;
536 MBInfoPtr->btn_win_h = a_btn_h+2+(windowPadding<<1);
537
538 if (MBInfoPtr->btn_win_w >
539 MBInfoPtr->msg_win_w+MBInfoPtr->icon_win_w+X_GAP) {
540 MBInfoPtr->msg_win_w =
541 MBInfoPtr->btn_win_w-MBInfoPtr->icon_win_w-X_GAP;
542 } else {
543 MBInfoPtr->btn_win_w =
544 MBInfoPtr->msg_win_w+MBInfoPtr->icon_win_w+X_GAP;
545 }
546 MBInfoPtr->main_win_w = MBInfoPtr->btn_win_w + (X_MARGIN<<1) +
547 (brdrW<<1);
548 MBInfoPtr->main_win_h = MBInfoPtr->icon_win_h + MBInfoPtr->btn_win_h +
549 (Y_MARGIN<<1) + Y_GAP + (brdrW<<1);
550 left = ((MBInfoPtr->btn_win_w - numButtons*a_btn_w -
551 BTN_MIN_X_GAP*(numButtons-1))>>1);
552 inc = a_btn_w + ((MBInfoPtr->btn_win_w-(left<<1)-numButtons*a_btn_w) /
553 (numButtons-1));
554 y = ((MBInfoPtr->btn_win_h - ((BTN_Y_MARGIN<<1) + font_height)) >> 1);
555 for (i=0; i < numButtons; i++) {
556 MBInfoPtr->btn_info[i].bbox.ltx = left+BTN_XY_EXTRA;
557 MBInfoPtr->btn_info[i].bbox.lty = y;
558 MBInfoPtr->btn_info[i].bbox.rbx = left +
559 (a_btn_w-(BTN_XY_EXTRA<<1)) + BTN_XY_EXTRA;
560 MBInfoPtr->btn_info[i].bbox.rby = y + font_height + (BTN_Y_MARGIN<<1);
561 left += inc;
562 }
563 MBInfoPtr->main_win_x = ((DisplayWidth(mainDisplay, mainScreen) -
564 MBInfoPtr->main_win_w)>>1);
565 MBInfoPtr->main_win_y = ((DisplayHeight(mainDisplay, mainScreen) -
566 MBInfoPtr->main_win_h)/3);
567 if (MBInfoPtr->main_win_x < 0) MBInfoPtr->main_win_x = 0;
568 if (MBInfoPtr->main_win_y < 0) MBInfoPtr->main_win_y = 0;
569 }
570
571 static
SetupMBWindow(MBInfoPtr,Message,Title,IconAndBtns,IsDialog)572 int SetupMBWindow(MBInfoPtr, Message, Title, IconAndBtns, IsDialog)
573 struct MBRec *MBInfoPtr;
574 char *Message, *Title;
575 int IconAndBtns, IsDialog;
576 {
577 int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
578 XWMHints wmhints;
579 XSizeHints sizehints;
580 XSetWindowAttributes win_attrs;
581
582 memset(MBInfoPtr, 0, sizeof(struct MBRec));
583 MBInfoPtr->is_dialog = IsDialog;
584 MBInfoPtr->msg_copy = NULL;
585 MBInfoPtr->max_msg_win_w = (DisplayWidth(mainDisplay,mainScreen)>>1);
586 MBInfoPtr->max_msg_str_len = MBInfoPtr->max_msg_win_w / defaultFontWidth;
587 MBInfoPtr->max_msg_str_total = MBInfoPtr->max_msg_win_w;
588
589 numButtons = MAX_BUTTONS;
590 if (IconAndBtns & MB_BTN_EXTRA) numButtons++;
591 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
592 CalcSimpleGeometry(MBInfoPtr, Message);
593 } else {
594 CalcGeometry(MBInfoPtr, Message);
595 }
596 switch (IconAndBtns & MB_BTNMASK) {
597 case MB_BTN_NONE:
598 break;
599 case MB_BTN_OK:
600 SetupMBButton(MBInfoPtr, LF_BUTTON, '\0', MB_ID_FAILED);
601 SetupMBButton(MBInfoPtr, MD_BUTTON | DEF_BUTTON, 'o', MB_ID_OK);
602 SetupMBButton(MBInfoPtr, RT_BUTTON, '\0', MB_ID_FAILED);
603 break;
604 case MB_BTN_YESNOCANCEL:
605 SetupMBButton(MBInfoPtr, LF_BUTTON | DEF_BUTTON, 'y', MB_ID_YES);
606 SetupMBButton(MBInfoPtr, MD_BUTTON, 'n', MB_ID_NO);
607 SetupMBButton(MBInfoPtr, RT_BUTTON, 'c', MB_ID_CANCEL);
608 break;
609 case MB_BTN_OKCANCEL:
610 SetupMBButton(MBInfoPtr, LF_BUTTON | DEF_BUTTON, 'o', MB_ID_OK);
611 SetupMBButton(MBInfoPtr, MD_BUTTON, '\0', MB_ID_FAILED);
612 SetupMBButton(MBInfoPtr, RT_BUTTON, 'c', MB_ID_CANCEL);
613 break;
614 case MB_BTN_YESNO:
615 SetupMBButton(MBInfoPtr, LF_BUTTON | DEF_BUTTON, 'y', MB_ID_YES);
616 SetupMBButton(MBInfoPtr, MD_BUTTON, '\0', MB_ID_FAILED);
617 SetupMBButton(MBInfoPtr, RT_BUTTON, 'n', MB_ID_NO);
618 break;
619 default:
620 SetupMBButton(MBInfoPtr, LF_BUTTON, '\0', MB_ID_FAILED);
621 SetupMBButton(MBInfoPtr, MD_BUTTON, '\0', MB_ID_FAILED);
622 SetupMBButton(MBInfoPtr, RT_BUTTON, '\0', MB_ID_FAILED);
623 break;
624 }
625 if (IconAndBtns & MB_BTN_EXTRA) {
626 if ((IconAndBtns & MB_BTNMASK) != 0) {
627 SetupMBButton(MBInfoPtr, XT_BUTTON, extraBtnChar, MB_ID_EXTRA);
628 } else {
629 SetupMBButton(MBInfoPtr, XT_BUTTON | DEF_BUTTON, extraBtnChar,
630 MB_ID_EXTRA);
631 }
632 } else {
633 SetupMBButton(MBInfoPtr, XT_BUTTON, '\0', MB_ID_FAILED);
634 }
635
636 switch (IconAndBtns & MB_ICONMASK) {
637 case MB_ICON_STOP:
638 MBInfoPtr->cur_bitmap = msgBoxPixmap[MB_PIXMAP_STOP];
639 break;
640 case MB_ICON_QUESTION:
641 MBInfoPtr->cur_bitmap = msgBoxPixmap[MB_PIXMAP_QUESTION];
642 break;
643 case MB_ICON_INFORMATION:
644 MBInfoPtr->cur_bitmap = msgBoxPixmap[MB_PIXMAP_INFORMATION];
645 break;
646 case MB_ICON_DIALOG:
647 MBInfoPtr->cur_bitmap = msgBoxPixmap[MB_PIXMAP_DIALOG];
648 break;
649 default: MBInfoPtr->cur_bitmap = None; break;
650 }
651
652 if ((MBInfoPtr->main_win=XCreateSimpleWindow(mainDisplay, rootWindow,
653 MBInfoPtr->main_win_x, MBInfoPtr->main_win_y,
654 MBInfoPtr->main_win_w, MBInfoPtr->main_win_h, brdrW,
655 myBorderPixel, bg_pixel)) == 0) {
656 fprintf(stderr, "%s\n", TgLoadString(STID_FAIL_TO_CREATE_WINDOW));
657 return FALSE;
658 }
659 if ((MBInfoPtr->icon_win=XCreateSimpleWindow(mainDisplay,
660 MBInfoPtr->main_win, X_MARGIN, Y_MARGIN,
661 MBInfoPtr->icon_win_w, MBInfoPtr->icon_win_h, 0,
662 myBorderPixel, bg_pixel)) == 0) {
663 fprintf(stderr, "%s\n", TgLoadString(STID_FAIL_TO_CREATE_WINDOW));
664 return FALSE;
665 }
666 if ((MBInfoPtr->msg_win=XCreateSimpleWindow(mainDisplay,
667 MBInfoPtr->main_win, X_MARGIN+MBInfoPtr->icon_win_w+X_GAP, Y_MARGIN,
668 MBInfoPtr->msg_win_w, MBInfoPtr->msg_win_h, 0,
669 myBorderPixel, bg_pixel)) == 0) {
670 fprintf(stderr, "%s\n", TgLoadString(STID_FAIL_TO_CREATE_WINDOW));
671 return FALSE;
672 }
673 if ((MBInfoPtr->btn_win=XCreateSimpleWindow(mainDisplay,
674 MBInfoPtr->main_win, X_MARGIN, Y_MARGIN+Y_GAP+MBInfoPtr->icon_win_h,
675 MBInfoPtr->btn_win_w, MBInfoPtr->btn_win_h, 0,
676 myBorderPixel, bg_pixel)) == 0) {
677 fprintf(stderr, "%s\n", TgLoadString(STID_FAIL_TO_CREATE_WINDOW));
678 return FALSE;
679 }
680 win_attrs.save_under = True;
681 win_attrs.colormap = mainColormap;
682 XChangeWindowAttributes(mainDisplay, MBInfoPtr->main_win,
683 CWSaveUnder | CWColormap, &win_attrs);
684
685 wmhints.flags = InputHint | StateHint;
686 wmhints.input = True;
687 wmhints.initial_state = NormalState;
688 XSetWMHints(mainDisplay, MBInfoPtr->main_win, &wmhints);
689 wmhints.flags = InputHint;
690 XSetWMHints(mainDisplay, MBInfoPtr->icon_win, &wmhints);
691 XSetWMHints(mainDisplay, MBInfoPtr->msg_win, &wmhints);
692 XSetWMHints(mainDisplay, MBInfoPtr->btn_win, &wmhints);
693
694 sizehints.flags = PPosition | PSize | USPosition | PMinSize | PMaxSize;
695 sizehints.x = MBInfoPtr->main_win_x;
696 sizehints.y = MBInfoPtr->main_win_y;
697 sizehints.width = sizehints.max_width = sizehints.min_width =
698 MBInfoPtr->main_win_w;
699 sizehints.height = sizehints.max_height = sizehints.min_height =
700 MBInfoPtr->main_win_h;
701 #ifdef NOTR4MODE
702 XSetNormalHints(mainDisplay, MBInfoPtr->main_win, &sizehints);
703 #else
704 XSetWMNormalHints(mainDisplay, MBInfoPtr->main_win, &sizehints);
705 #endif /* NOTR4MODE */
706 RegisterWM_DELETE_WINDOW(MBInfoPtr->main_win);
707 XStoreName(mainDisplay, MBInfoPtr->main_win, Title);
708 /* so that MessageBox() and Dialog() window stays on top of tgif's window */
709 XSetTransientForHint(mainDisplay, MBInfoPtr->main_win, mainWindow);
710
711 #ifdef MAPBEFORESELECT
712 XMapWindow(mainDisplay, MBInfoPtr->main_win);
713 XMapWindow(mainDisplay, MBInfoPtr->icon_win);
714 XMapWindow(mainDisplay, MBInfoPtr->msg_win);
715 XMapWindow(mainDisplay, MBInfoPtr->btn_win);
716 XSelectInput(mainDisplay, MBInfoPtr->main_win, ButtonPressMask |
717 KeyPressMask | StructureNotifyMask | VisibilityChangeMask);
718 XSelectInput(mainDisplay, MBInfoPtr->icon_win,
719 ButtonPressMask | KeyPressMask | ExposureMask);
720 XSelectInput(mainDisplay, MBInfoPtr->msg_win,
721 ButtonPressMask | KeyPressMask | ExposureMask);
722 XSelectInput(mainDisplay, MBInfoPtr->btn_win, ButtonReleaseMask |
723 ButtonPressMask | PointerMotionMask | KeyPressMask | ExposureMask);
724 #else /* !MAPBEFORESELECT */
725 XSelectInput(mainDisplay, MBInfoPtr->main_win, ButtonPressMask |
726 KeyPressMask | StructureNotifyMask | VisibilityChangeMask);
727 XSelectInput(mainDisplay, MBInfoPtr->icon_win,
728 ButtonPressMask | KeyPressMask | ExposureMask);
729 XSelectInput(mainDisplay, MBInfoPtr->msg_win,
730 ButtonPressMask | KeyPressMask | ExposureMask);
731 XSelectInput(mainDisplay, MBInfoPtr->btn_win, ButtonReleaseMask |
732 ButtonPressMask | PointerMotionMask | KeyPressMask | ExposureMask);
733 XMapWindow(mainDisplay, MBInfoPtr->main_win);
734 XMapWindow(mainDisplay, MBInfoPtr->icon_win);
735 XMapWindow(mainDisplay, MBInfoPtr->msg_win);
736 XMapWindow(mainDisplay, MBInfoPtr->btn_win);
737 #endif /* !MAPBEFORESELECT */
738 if (warpToWinCenter) {
739 XWarpPointer(mainDisplay, None, MBInfoPtr->main_win, 0, 0, 0, 0,
740 (MBInfoPtr->main_win_w>>1), (MBInfoPtr->main_win_h>>1));
741 }
742 XSync(mainDisplay, False);
743 return TRUE;
744 }
745
746 static
DisplayInput(MBInfoPtr)747 void DisplayInput(MBInfoPtr)
748 struct MBRec *MBInfoPtr;
749 {
750 Window win=MBInfoPtr->btn_win;
751 char *buf=MBInfoPtr->return_str, *dup_buf=NULL, *msg=NULL;
752 int buf_len;
753
754 MBInfoPtr->str_w = 0;
755 MBInfoPtr->cur_x = (MBInfoPtr->btn_win_w>>1);
756 if (buf == NULL) return;
757
758 buf_len = strlen(buf);
759 if (msgFontSet == NULL && msgFontPtr == NULL) {
760 MBInfoPtr->str_w = defaultFontWidth*strlen(buf);
761 } else {
762 MBInfoPtr->str_w = MsgTextWidth(msgFontPtr, buf, buf_len);
763 }
764 MBInfoPtr->cur_x = ((MBInfoPtr->btn_win_w-MBInfoPtr->str_w)>>1);
765 MBInfoPtr->cursor_x = MBInfoPtr->cur_x+MBInfoPtr->str_w+1;
766 if (doPassword) {
767 int i;
768
769 dup_buf = (char*)malloc((buf_len+1)*sizeof(char));
770 if (dup_buf == NULL) FailAllocMessage();
771 for (i=0; i < buf_len; i++) dup_buf[i] = '*';
772 msg = dup_buf;
773 } else {
774 msg = buf;
775 }
776 if (msgFontPtr != NULL) {
777 XSetFont(mainDisplay, defaultGC, msgFontPtr->fid);
778 }
779 DrawMsgString(mainDisplay, win, defaultGC, MBInfoPtr->cur_x,
780 MBInfoPtr->cur_y, msg, buf_len);
781 if (msgFontSet != NULL || msgFontPtr != NULL) {
782 XSetFont(mainDisplay, defaultGC, defaultFontPtr->fid);
783 }
784 if (dup_buf != NULL) free(dup_buf);
785 }
786
787 static
HandleMsgBoxKeyEvent(MBInfoPtr,input)788 int HandleMsgBoxKeyEvent(MBInfoPtr, input)
789 struct MBRec *MBInfoPtr;
790 XEvent *input;
791 {
792 XKeyEvent *key_ev=(&(input->xkey));
793 KeySym key_sym;
794 char buf[80];
795 int i, j, has_ch;
796 int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
797
798 has_ch = XLookupString(key_ev, buf, sizeof(buf), &key_sym, &c_stat);
799 TranslateKeys(buf, &key_sym);
800 if (MBInfoPtr->is_dialog) {
801 /* for Dialog(), return INVALID for <ESC> */
802 /* return FALSE for a normal character, including <BS> */
803 /* return TRUE for <CR> or <LF> */
804 if (MBInfoPtr->exposed) {
805 /* erase the old cursor */
806 PutCursor(MBInfoPtr->btn_win, MBInfoPtr->cursor_x, MBInfoPtr->cursor_y,
807 bg_pixel);
808 }
809 if (CharIsESC(key_ev, buf, key_sym, &has_ch)) {
810 if (MBInfoPtr->return_str != NULL) *MBInfoPtr->return_str = '\0';
811 return INVALID;
812 } else if (CharIsCRorLF(key_ev, buf, key_sym, &has_ch)) {
813 if (MBInfoPtr->return_str == NULL) {
814 return INVALID;
815 }
816 return TRUE;
817 } else if (CharIsBSorDEL(key_ev, buf, key_sym, &has_ch, FALSE)) {
818 if (MBInfoPtr->return_str == NULL) {
819 return INVALID;
820 }
821 if (MBInfoPtr->index > 0) {
822 if (MBInfoPtr->exposed) {
823 XClearWindow(mainDisplay, MBInfoPtr->btn_win);
824 }
825 MBInfoPtr->return_str[--MBInfoPtr->index] = '\0';
826 DisplayInput(MBInfoPtr);
827 }
828 } else if ((key_ev->state & ControlMask)==0 &&
829 key_sym>='\040' && key_sym<='\177') {
830 if (MBInfoPtr->return_str == NULL) {
831 return INVALID;
832 }
833 if (buf[0] >= '\040' && MBInfoPtr->index < 80) {
834 if (MBInfoPtr->exposed) {
835 XClearWindow(mainDisplay, MBInfoPtr->btn_win);
836 }
837 MBInfoPtr->return_str[MBInfoPtr->index++] = buf[0];
838 MBInfoPtr->return_str[MBInfoPtr->index] = '\0';
839 DisplayInput(MBInfoPtr);
840 }
841 }
842 if (MBInfoPtr->exposed) {
843 PutCursor(MBInfoPtr->btn_win, MBInfoPtr->cursor_x, MBInfoPtr->cursor_y,
844 myFgPixel);
845 }
846 return FALSE;
847 } else {
848 /* for MsgBox(), return a button id */
849 if (CharIsESC(key_ev, buf, key_sym, &has_ch)) {
850 return (MB_ID_CANCEL);
851 }
852 for (i=0; i < numButtons; i++) {
853 if (MBInfoPtr->btn_info[i].str != NULL) {
854 for (j=0; MBInfoPtr->btn_info[i].key_sym[j] != (KeySym)0; j++) {
855 if (MBInfoPtr->btn_info[i].key_sym[j] == key_sym) {
856 DisplayButtonInBBox(MBInfoPtr->btn_win,
857 MBInfoPtr->btn_info[i].str,
858 strlen(MBInfoPtr->btn_info[i].str),
859 &MBInfoPtr->btn_info[i].bbox, BUTTON_INVERT,
860 MBInfoPtr->btn_info[i].highlight, BTN_XY_EXTRA, NULL);
861 XSync(mainDisplay, False);
862 return MBInfoPtr->btn_info[i].id;
863 }
864 }
865 }
866 }
867 }
868 return INVALID;
869 }
870
871 static
HandleDeleteMsgBox(MBInfoPtr)872 int HandleDeleteMsgBox(MBInfoPtr)
873 struct MBRec *MBInfoPtr;
874 {
875 int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
876
877 if (MBInfoPtr->is_dialog) {
878 /* for Dialog(), same as <ESC> is pressed */
879 if (MBInfoPtr->exposed) {
880 /* erase the old cursor */
881 PutCursor(MBInfoPtr->btn_win, MBInfoPtr->cursor_x, MBInfoPtr->cursor_y,
882 bg_pixel);
883 }
884 if (MBInfoPtr->return_str != NULL) *MBInfoPtr->return_str = '\0';
885 return INVALID;
886 }
887 /* for MsgBox(), return a button id */
888 return MB_ID_CANCEL;
889 }
890
891 static
HandlePasteInDialog(MBInfoPtr,input)892 void HandlePasteInDialog(MBInfoPtr, input)
893 struct MBRec *MBInfoPtr;
894 XEvent *input;
895 {
896 XButtonEvent *button_ev=(&(input->xbutton));
897 int buf_len=0, from_selection=FALSE;
898 char *cut_buffer=NULL;
899
900 if (button_ev->button != Button2) return;
901
902 cut_buffer = FetchSelectionOrCutBuffer(&buf_len, &from_selection);
903 if (cut_buffer == NULL) return;
904 if ((unsigned char)(*cut_buffer) != TGIF_HEADER &&
905 MBInfoPtr->return_str != NULL) {
906 unsigned char *c_ptr=(unsigned char *)cut_buffer;
907
908 if (MBInfoPtr->exposed) {
909 XClearWindow(mainDisplay, MBInfoPtr->btn_win);
910 }
911 for ( ; buf_len > 0 && MBInfoPtr->index < 80 && *c_ptr != '\0';
912 c_ptr++, buf_len--) {
913 if (*c_ptr >= (unsigned char)('\040') &&
914 *c_ptr < (unsigned char)('\377')) {
915 MBInfoPtr->return_str[MBInfoPtr->index++] = (char)(*c_ptr);
916 } else {
917 break;
918 }
919 }
920 MBInfoPtr->return_str[MBInfoPtr->index] = '\0';
921 if (MBInfoPtr->exposed) {
922 DisplayInput(MBInfoPtr);
923 PutCursor(MBInfoPtr->btn_win, MBInfoPtr->cursor_x, MBInfoPtr->cursor_y,
924 myFgPixel);
925 }
926 }
927 FreeSelectionOrCutBuffer(cut_buffer, from_selection);
928 }
929
930 static
HandleMsgBoxBtnEvent(MBInfoPtr,input)931 int HandleMsgBoxBtnEvent(MBInfoPtr, input)
932 struct MBRec *MBInfoPtr;
933 XEvent *input;
934 {
935 XButtonEvent *button_ev=(&(input->xbutton));
936 int i, x=button_ev->x, y=button_ev->y;
937
938 for (i=0; i < numButtons; i++) {
939 if (MBInfoPtr->btn_info[i].str != NULL) {
940 if (x >= MBInfoPtr->btn_info[i].bbox.ltx &&
941 x < MBInfoPtr->btn_info[i].bbox.rbx &&
942 y >= MBInfoPtr->btn_info[i].bbox.lty &&
943 y < MBInfoPtr->btn_info[i].bbox.rby) {
944 int inside=TRUE;
945
946 DisplayButtonInBBox(MBInfoPtr->btn_win, MBInfoPtr->btn_info[i].str,
947 strlen(MBInfoPtr->btn_info[i].str),
948 &MBInfoPtr->btn_info[i].bbox, BUTTON_INVERT,
949 MBInfoPtr->btn_info[i].highlight, BTN_XY_EXTRA, NULL);
950 if (!debugNoPointerGrab) {
951 XGrabPointer(mainDisplay, MBInfoPtr->btn_win, FALSE,
952 PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
953 GrabModeAsync, None, defaultCursor, CurrentTime);
954 }
955 while (TRUE) {
956 XEvent ev;
957
958 XNextEvent(mainDisplay, &ev);
959 if (ev.type == ButtonRelease) {
960 XUngrabPointer(mainDisplay, CurrentTime);
961 XSync(mainDisplay, False);
962 button_ev = &(ev.xbutton);
963 x = button_ev->x;
964 y = button_ev->y;
965 if (x >= MBInfoPtr->btn_info[i].bbox.ltx &&
966 x < MBInfoPtr->btn_info[i].bbox.rbx &&
967 y >= MBInfoPtr->btn_info[i].bbox.lty &&
968 y < MBInfoPtr->btn_info[i].bbox.rby) {
969 DisplayButtonInBBox(MBInfoPtr->btn_win,
970 MBInfoPtr->btn_info[i].str,
971 strlen(MBInfoPtr->btn_info[i].str),
972 &MBInfoPtr->btn_info[i].bbox,
973 BUTTON_NORMAL,
974 MBInfoPtr->btn_info[i].highlight, BTN_XY_EXTRA,
975 NULL);
976 return MBInfoPtr->btn_info[i].id;
977 }
978 break;
979 } else if (ev.type == MotionNotify) {
980 XEvent tmp_ev;
981 XMotionEvent *motion_ev=(&(ev.xmotion));
982
983 while (XCheckMaskEvent(mainDisplay, PointerMotionMask,
984 &tmp_ev)) ;
985 x = motion_ev->x;
986 y = motion_ev->y;
987 if (inside) {
988 if (!(x >= MBInfoPtr->btn_info[i].bbox.ltx &&
989 x < MBInfoPtr->btn_info[i].bbox.rbx &&
990 y >= MBInfoPtr->btn_info[i].bbox.lty &&
991 y < MBInfoPtr->btn_info[i].bbox.rby)) {
992 DisplayButtonInBBox(MBInfoPtr->btn_win,
993 MBInfoPtr->btn_info[i].str,
994 strlen(MBInfoPtr->btn_info[i].str),
995 &MBInfoPtr->btn_info[i].bbox, BUTTON_NORMAL,
996 MBInfoPtr->btn_info[i].highlight, BTN_XY_EXTRA,
997 NULL);
998 inside = FALSE;
999 }
1000 } else {
1001 if (x >= MBInfoPtr->btn_info[i].bbox.ltx &&
1002 x < MBInfoPtr->btn_info[i].bbox.rbx &&
1003 y >= MBInfoPtr->btn_info[i].bbox.lty &&
1004 y < MBInfoPtr->btn_info[i].bbox.rby) {
1005 DisplayButtonInBBox(MBInfoPtr->btn_win,
1006 MBInfoPtr->btn_info[i].str,
1007 strlen(MBInfoPtr->btn_info[i].str),
1008 &MBInfoPtr->btn_info[i].bbox, BUTTON_INVERT,
1009 MBInfoPtr->btn_info[i].highlight, BTN_XY_EXTRA,
1010 NULL);
1011 inside = TRUE;
1012 }
1013 }
1014 }
1015 }
1016 return INVALID;
1017 }
1018 }
1019 }
1020 return INVALID;
1021 }
1022
1023 static
RefreshMsgBox(MBInfoPtr)1024 void RefreshMsgBox(MBInfoPtr)
1025 struct MBRec *MBInfoPtr;
1026 {
1027 int i;
1028 XEvent ev;
1029
1030 if (MBInfoPtr->msg_copy != NULL && *MBInfoPtr->msg_copy != '\0') {
1031 int y=0;
1032 char *c_ptr=MBInfoPtr->msg_copy;
1033
1034 if (boldMsgFontPtr != NULL) {
1035 XSetFont(mainDisplay, defaultGC, boldMsgFontPtr->fid);
1036 }
1037 while (c_ptr != NULL) {
1038 char *c_ptr1=BoldMsgStrChr(c_ptr, '\n');
1039 int len, w;
1040
1041 if (c_ptr1 != NULL) *c_ptr1 = '\0';
1042 len = strlen(c_ptr);
1043 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
1044 if (MBInfoPtr->is_dialog) {
1045 w = len * defaultFontWidth;
1046 DrawBoldMsgString(mainDisplay, MBInfoPtr->msg_win, defaultGC,
1047 (MBInfoPtr->msg_win_w-w)>>1, y+defaultFontAsc, c_ptr, len);
1048 } else {
1049 DrawBoldMsgString(mainDisplay, MBInfoPtr->msg_win, defaultGC,
1050 0, y+defaultFontAsc, c_ptr, len);
1051 }
1052 y += defaultFontHeight+SPACING;
1053 } else {
1054 if (MBInfoPtr->is_dialog) {
1055 w = BoldMsgTextWidth(boldMsgFontPtr, c_ptr, len);
1056 DrawBoldMsgString(mainDisplay, MBInfoPtr->msg_win, defaultGC,
1057 (MBInfoPtr->msg_win_w-w)>>1, y+boldMsgFontAsc, c_ptr, len);
1058 } else {
1059 DrawBoldMsgString(mainDisplay, MBInfoPtr->msg_win, defaultGC,
1060 0, y+boldMsgFontAsc, c_ptr, len);
1061 }
1062 y += boldMsgFontHeight+SPACING;
1063 }
1064 if (c_ptr1 != NULL) {
1065 *c_ptr1 = '\n';
1066 c_ptr = &c_ptr1[1];
1067 } else {
1068 break;
1069 }
1070 }
1071 if (boldMsgFontSet != NULL || boldMsgFontPtr != NULL) {
1072 XSetFont(mainDisplay, defaultGC, defaultFontPtr->fid);
1073 }
1074 }
1075 if (MBInfoPtr->is_dialog) {
1076 DisplayInput(MBInfoPtr);
1077 PutCursor(MBInfoPtr->btn_win, MBInfoPtr->cursor_x, MBInfoPtr->cursor_y,
1078 myFgPixel);
1079 } else {
1080 for (i=0; i < numButtons; i++) {
1081 if (MBInfoPtr->btn_info[i].str != NULL) {
1082 DisplayButtonInBBox(MBInfoPtr->btn_win, MBInfoPtr->btn_info[i].str,
1083 strlen(MBInfoPtr->btn_info[i].str),
1084 &MBInfoPtr->btn_info[i].bbox, BUTTON_NORMAL,
1085 MBInfoPtr->btn_info[i].highlight, BTN_XY_EXTRA,
1086 NULL);
1087 }
1088 }
1089 }
1090 if (MBInfoPtr->cur_bitmap != None) {
1091 int y=((MBInfoPtr->icon_win_h-ICON_H)>>1);
1092
1093 XSetTSOrigin(mainDisplay, defaultGC, 0, y);
1094 XSetFillStyle(mainDisplay, defaultGC, FillOpaqueStippled);
1095 XSetStipple(mainDisplay, defaultGC, MBInfoPtr->cur_bitmap);
1096 XFillRectangle(mainDisplay, MBInfoPtr->icon_win, defaultGC, 0, y,
1097 ICON_W, ICON_H);
1098 XSetFillStyle(mainDisplay, defaultGC, FillSolid);
1099 XSetTSOrigin(mainDisplay, defaultGC, 0, 0);
1100 }
1101 while (XCheckWindowEvent(mainDisplay,MBInfoPtr->main_win,ExposureMask,&ev)) ;
1102 while (XCheckWindowEvent(mainDisplay,MBInfoPtr->icon_win,ExposureMask,&ev)) ;
1103 while (XCheckWindowEvent(mainDisplay,MBInfoPtr->msg_win,ExposureMask,&ev)) ;
1104 while (XCheckWindowEvent(mainDisplay,MBInfoPtr->btn_win,ExposureMask,&ev)) ;
1105
1106 if (threeDLook && dialogboxUse3DBorder) {
1107 struct BBRec bbox;
1108
1109 SetBBRec(&bbox, 0, 0, MBInfoPtr->main_win_w, MBInfoPtr->main_win_h);
1110 TgDrawThreeDButton(mainDisplay, MBInfoPtr->main_win, textMenuGC, &bbox,
1111 TGBS_RAISED, 2, FALSE);
1112 }
1113 }
1114
MsgBox(Message,Title,IconAndBtns)1115 int MsgBox(Message, Title, IconAndBtns)
1116 char *Message, *Title;
1117 int IconAndBtns;
1118 {
1119 static int stShowing=FALSE;
1120 char *dup_msg=NULL;
1121 int rc=MB_ID_FAILED, looping=TRUE;
1122
1123 if (PRTGIF) {
1124 fprintf(stderr, "%s\n", Message);
1125 return rc;
1126 }
1127 dup_msg = UtilStrDup(Message);
1128 if (dup_msg == NULL) {
1129 FailAllocMessage();
1130 return rc;
1131 }
1132 if (stShowing) return rc;
1133
1134 stShowing = TRUE;
1135 if (!SetupMBWindow(&mbInfo, dup_msg, Title, IconAndBtns, FALSE)) {
1136 char msg[MAXSTRING];
1137
1138 sprintf(msg, TgLoadString(STID_INVALID_PARAM_PASSED_TO_FUNC), "MsgBox()");
1139 fprintf(stderr, "%s\n", msg);
1140 Msg(msg);
1141 if (mbInfo.msg_copy != NULL) {
1142 free(mbInfo.msg_copy);
1143 mbInfo.msg_copy = NULL;
1144 }
1145 free(dup_msg);
1146 stShowing = FALSE;
1147 return rc;
1148 }
1149 EndMeasureTooltip(FALSE);
1150 while (looping) {
1151 XEvent input, ev;
1152
1153 XNextEvent(mainDisplay, &input);
1154 if ((input.type==MapNotify && input.xany.window==mbInfo.main_win) ||
1155 (input.type==Expose && (input.xany.window==mbInfo.main_win ||
1156 input.xany.window==mbInfo.icon_win ||
1157 input.xany.window==mbInfo.msg_win ||
1158 input.xany.window==mbInfo.btn_win)) ||
1159 (!mbInfo.exposed &&
1160 (XCheckWindowEvent(mainDisplay,mbInfo.main_win,ExposureMask,&ev) ||
1161 XCheckWindowEvent(mainDisplay,mbInfo.main_win,StructureNotifyMask,
1162 &ev)))) {
1163 RefreshMsgBox(&mbInfo);
1164 mbInfo.exposed = TRUE;
1165 XSync(mainDisplay, False);
1166 if (input.xany.window==mbInfo.main_win ||
1167 input.xany.window==mbInfo.icon_win ||
1168 input.xany.window==mbInfo.msg_win ||
1169 input.xany.window==mbInfo.btn_win) {
1170 continue;
1171 }
1172 }
1173 if (input.type == Expose) {
1174 ExposeEventHandler(&input, FALSE);
1175 } else if (input.type == ConfigureNotify &&
1176 input.xany.window == mainWindow) {
1177 Reconfigure(FALSE);
1178 } else if (input.type == VisibilityNotify &&
1179 input.xany.window==mainWindow &&
1180 input.xvisibility.state==VisibilityUnobscured) {
1181 int i;
1182
1183 while (XCheckWindowEvent(mainDisplay, mainWindow,
1184 VisibilityChangeMask, &ev)) ;
1185 if (pinnedMainMenu) XMapRaised(mainDisplay, mainMenuWindow);
1186 for (i = 0; i < numExtraWins; i++) {
1187 if (extraWinInfo[i].mapped && extraWinInfo[i].raise &&
1188 extraWinInfo[i].window != None) {
1189 XMapRaised(mainDisplay, extraWinInfo[i].window);
1190 }
1191 }
1192 XMapRaised(mainDisplay, mbInfo.main_win);
1193 } else if (input.type == KeyPress) {
1194 if ((rc=HandleMsgBoxKeyEvent(&mbInfo, &input)) != INVALID) {
1195 break;
1196 }
1197 } else if (input.type==ButtonPress && input.xany.window==mbInfo.btn_win) {
1198 if ((rc=HandleMsgBoxBtnEvent(&mbInfo, &input)) != INVALID) {
1199 break;
1200 }
1201 } else if (IsWM_DELETE_WINDOW(&input)) {
1202 rc = HandleDeleteMsgBox(&mbInfo);
1203 break;
1204 }
1205 }
1206 if (mbInfo.msg_copy != NULL) {
1207 free(mbInfo.msg_copy);
1208 mbInfo.msg_copy = NULL;
1209 }
1210 free(dup_msg);
1211
1212 XDestroyWindow(mainDisplay, mbInfo.main_win);
1213 if (warpToWinCenter) {
1214 XWarpPointer(mainDisplay, None, drawWindow, 0, 0, 0, 0,
1215 (int)(ZOOMED_SIZE(drawWinW)>>1), (int)(ZOOMED_SIZE(drawWinH)>>1));
1216 }
1217 stShowing = FALSE;
1218 return rc;
1219 }
1220
1221 static
DoDialog(Message,ReturnStr)1222 int DoDialog(Message, ReturnStr)
1223 char *Message, *ReturnStr;
1224 {
1225 char *dup_msg=UtilStrDup(Message), szTitle[80];
1226 int rc=FALSE, looping=TRUE;
1227
1228 if (dup_msg == NULL) {
1229 FailAllocMessage();
1230 return INVALID;
1231 }
1232 sprintf(szTitle, TgLoadString(STID_TOOL_INPUT), TOOL_NAME);
1233 if (!SetupMBWindow(&mbInfo, dup_msg, szTitle, MB_ICON_DIALOG, TRUE)) {
1234 char msg[MAXSTRING];
1235
1236 sprintf(msg, TgLoadString(STID_INVALID_PARAM_PASSED_TO_FUNC), "MsgBox()");
1237 fprintf(stderr, "%s\n", msg);
1238 Msg(msg);
1239 if (mbInfo.msg_copy != NULL) {
1240 free(mbInfo.msg_copy);
1241 mbInfo.msg_copy = NULL;
1242 }
1243 free(dup_msg);
1244 return INVALID;
1245 }
1246 if (ReturnStr != NULL) {
1247 /* Use as is. */
1248 /* *ReturnStr = '\0'; */
1249 }
1250 mbInfo.cur_x = ((mbInfo.btn_win_w)>>1);
1251 mbInfo.cursor_x = mbInfo.cur_x + 1;
1252 if (msgFontSet == NULL && msgFontPtr == NULL) {
1253 mbInfo.cur_y = ((mbInfo.btn_win_h-defaultFontHeight)>>1)+defaultFontAsc;
1254 mbInfo.cursor_y = mbInfo.cur_y - defaultFontAsc +
1255 ((defaultFontAsc-16)>>1);
1256 } else {
1257 mbInfo.cur_y = ((mbInfo.btn_win_h-msgFontHeight)>>1)+msgFontAsc;
1258 mbInfo.cursor_y = mbInfo.cur_y - msgFontAsc +
1259 ((msgFontAsc-16)>>1);
1260 }
1261 mbInfo.index = 0;
1262 if (ReturnStr != NULL) {
1263 mbInfo.index = strlen(ReturnStr);
1264 }
1265 mbInfo.return_str = ReturnStr;
1266
1267 while (looping) {
1268 XEvent input, ev;
1269
1270 XNextEvent(mainDisplay, &input);
1271 if ((input.type==MapNotify && input.xany.window==mbInfo.main_win) ||
1272 (input.type==Expose && (input.xany.window==mbInfo.main_win ||
1273 input.xany.window==mbInfo.icon_win ||
1274 input.xany.window==mbInfo.msg_win ||
1275 input.xany.window==mbInfo.btn_win)) ||
1276 (!mbInfo.exposed &&
1277 (XCheckWindowEvent(mainDisplay,mbInfo.main_win,ExposureMask,&ev) ||
1278 XCheckWindowEvent(mainDisplay,mbInfo.main_win,StructureNotifyMask,
1279 &ev)))) {
1280 RefreshMsgBox(&mbInfo);
1281 mbInfo.exposed = TRUE;
1282 XSync(mainDisplay, False);
1283 if (input.xany.window==mbInfo.main_win ||
1284 input.xany.window==mbInfo.icon_win ||
1285 input.xany.window==mbInfo.msg_win ||
1286 input.xany.window==mbInfo.btn_win) {
1287 continue;
1288 }
1289 }
1290 if (input.type == Expose) {
1291 ExposeEventHandler(&input, FALSE);
1292 } else if (input.type == ConfigureNotify &&
1293 input.xany.window == mainWindow) {
1294 Reconfigure(FALSE);
1295 } else if (input.type == VisibilityNotify &&
1296 input.xany.window==mainWindow &&
1297 input.xvisibility.state==VisibilityUnobscured) {
1298 int i;
1299
1300 while (XCheckWindowEvent(mainDisplay, mainWindow,
1301 VisibilityChangeMask, &ev)) ;
1302 if (pinnedMainMenu) XMapRaised(mainDisplay, mainMenuWindow);
1303 for (i = 0; i < numExtraWins; i++) {
1304 if (extraWinInfo[i].mapped && extraWinInfo[i].raise &&
1305 extraWinInfo[i].window != None) {
1306 XMapRaised(mainDisplay, extraWinInfo[i].window);
1307 }
1308 }
1309 XMapRaised(mainDisplay, mbInfo.main_win);
1310 } else if (input.type == KeyPress) {
1311 switch (HandleMsgBoxKeyEvent(&mbInfo, &input)) {
1312 case INVALID: looping = FALSE; rc = INVALID; break;
1313 case TRUE: looping = FALSE; rc = TRUE; break;
1314 case FALSE: break;
1315 }
1316 } else if (input.type==ButtonPress && input.xany.window==mbInfo.btn_win) {
1317 HandlePasteInDialog(&mbInfo, &input);
1318 } else if (IsWM_DELETE_WINDOW(&input)) {
1319 looping = FALSE;
1320 rc = INVALID;
1321 break;
1322 }
1323 }
1324 if (mbInfo.msg_copy != NULL) {
1325 free(mbInfo.msg_copy);
1326 mbInfo.msg_copy = NULL;
1327 }
1328 free(dup_msg);
1329
1330 XDestroyWindow(mainDisplay, mbInfo.main_win);
1331 if (warpToWinCenter) {
1332 XWarpPointer(mainDisplay, None, drawWindow, 0, 0, 0, 0,
1333 (int)(ZOOMED_SIZE(drawWinW)>>1), (int)(ZOOMED_SIZE(drawWinH)>>1));
1334 }
1335 return rc;
1336 }
1337
Dialog(Message,Comment,ReturnStr)1338 int Dialog(Message, Comment, ReturnStr)
1339 char *Message, *Comment, *ReturnStr;
1340 /* returns INVALID if <ESC> is types */
1341 /* returns FALSE otherwise */
1342 /* if Comment is NULL, "( <CR> or <ESC> to continue )" is assumed */
1343 /* if ReturnStr is NULL, hitting any key will return INVALID */
1344 {
1345 static int stDialoging=FALSE;
1346 char *real_msg=NULL, def_comment[MAXSTRING+1];
1347 int real_len=strlen(Message), rc;
1348
1349 if (Comment == NULL) {
1350 strcpy(def_comment, TgLoadCachedString(CSTID_DLG_DEF_CONTINUE));
1351 real_len += strlen(def_comment)+2;
1352 } else {
1353 real_len += strlen(Comment)+2;
1354 }
1355 real_msg = (char*)malloc((real_len+1)*sizeof(char));
1356 if (real_msg == NULL) {
1357 FailAllocMessage();
1358 return INVALID;
1359 }
1360 if (stDialoging) return INVALID;
1361
1362 stDialoging = TRUE;
1363 if (Comment == NULL) {
1364 sprintf(real_msg, "%s\n\n%s", Message, def_comment);
1365 } else {
1366 sprintf(real_msg, "%s\n\n%s", Message, Comment);
1367 }
1368 EndMeasureTooltip(FALSE);
1369 rc = DoDialog(real_msg, ReturnStr);
1370 free(real_msg);
1371 stDialoging = FALSE;
1372 return rc;
1373 }
1374