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/choice.c,v 1.15 2011/05/16 16:21:56 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_CHOICE_C_
22 
23 #include "tgifdefs.h"
24 #include "expfdefs.h"
25 
26 #include "align.e"
27 #include "arc.e"
28 #include "auxtext.e"
29 #include "box.e"
30 #include "choice.e"
31 #include "color.e"
32 #include "cursor.e"
33 #include "dialog.e"
34 #include "drawing.e"
35 #include "edit.e"
36 #include "file.e"
37 #include "font.e"
38 #include "grid.e"
39 #include "inmethod.e"
40 #include "mainloop.e"
41 #include "mainmenu.e"
42 #include "mark.e"
43 #include "menu.e"
44 #include "menuinfo.e"
45 #include "miniline.e"
46 #include "msg.e"
47 #include "navigate.e"
48 #include "oval.e"
49 #include "page.e"
50 #include "pattern.e"
51 #include "poly.e"
52 #include "polygon.e"
53 #include "raster.e"
54 #include "rcbox.e"
55 #include "rect.e"
56 #include "select.e"
57 #include "setup.e"
58 #include "shape.e"
59 #include "special.e"
60 #include "stretch.e"
61 #include "strtbl.e"
62 #include "text.e"
63 #include "util.e"
64 #include "wb.e"
65 #include "xbitmap.e"
66 #include "xprtfltr.e"
67 
68 #define FILE_ROW 0
69 #define ZOOM_ROW 0
70 #define RADIUS_ROW 0
71 #define PAGE_ROW 0
72 #define HORI_ALIGN_ROW 0
73 #define FONT_ROW 0
74 #define VSPACE_ROW 0
75 #define SHAPE_ROW 0
76 #define DASH_ROW 0
77 #define LINE_TYPE_ROW 0
78 #define FILL_ROW 0
79 #define COLOR_ROW 0
80 
81 #define PRINT_ROW 1
82 #define MOVE_MODE_ROW 1
83 #define ROTATE_ROW 1
84 #define PAGELAYOUT_ROW 1
85 #define VERT_ALIGN_ROW 1
86 #define TEXT_SIZE_ROW 1
87 #define JUST_ROW 1
88 #define STRETCHTEXT_ROW 1
89 #define LINE_STYLE_ROW 1
90 #define LINE_WIDTH_ROW 1
91 #define PEN_ROW 1
92 #define TRANSPAT_ROW 1
93 
94 #define FILE_COL 0
95 #define ZOOM_COL 1
96 #define RADIUS_COL 2
97 #define PAGE_COL 3
98 #define HORI_ALIGN_COL 4
99 #define FONT_COL 5
100 #define VSPACE_COL 6
101 #define SHAPE_COL 7
102 #define DASH_COL 8
103 #define LINE_TYPE_COL 9
104 #define FILL_COL 10
105 #define COLOR_COL 11
106 
107 #define PRINT_COL 0
108 #define MOVE_MODE_COL 1
109 #define ROTATE_COL 2
110 #define PAGELAYOUT_COL 3
111 #define VERT_ALIGN_COL 4
112 #define TEXT_SIZE_COL 5
113 #define JUST_COL 6
114 #define STRETCHTEXT_COL 7
115 #define LINE_STYLE_COL 8
116 #define LINE_WIDTH_COL 9
117 #define PEN_COL 10
118 #define TRANSPAT_COL 11
119 
120 #define CHOICE_SHIFT 4
121 
122 #define CHOICE_COLOR ((COLOR_COL<<CHOICE_SHIFT)|COLOR_ROW)
123 #define CHOICE_FILE ((FILE_COL<<CHOICE_SHIFT)|FILE_ROW)
124 #define CHOICE_PRINT ((PRINT_COL<<CHOICE_SHIFT)|PRINT_ROW)
125 #define CHOICE_HORI_ALIGN ((HORI_ALIGN_COL<<CHOICE_SHIFT)|HORI_ALIGN_ROW)
126 #define CHOICE_VERT_ALIGN ((VERT_ALIGN_COL<<CHOICE_SHIFT)|VERT_ALIGN_ROW)
127 #define CHOICE_ROTATE ((ROTATE_COL<<CHOICE_SHIFT)|ROTATE_ROW)
128 #define CHOICE_MOVE_MODE ((MOVE_MODE_COL<<CHOICE_SHIFT)|MOVE_MODE_ROW)
129 #define CHOICE_RADIUS ((RADIUS_COL<<CHOICE_SHIFT)|RADIUS_ROW)
130 #define CHOICE_ZOOM ((ZOOM_COL<<CHOICE_SHIFT)|ZOOM_ROW)
131 #define CHOICE_FONT ((FONT_COL<<CHOICE_SHIFT)|FONT_ROW)
132 #define CHOICE_JUST ((JUST_COL<<CHOICE_SHIFT)|JUST_ROW)
133 #define CHOICE_TEXT_SIZE ((TEXT_SIZE_COL<<CHOICE_SHIFT)|TEXT_SIZE_ROW)
134 #define CHOICE_VSPACE ((VSPACE_COL<<CHOICE_SHIFT)|VSPACE_ROW)
135 #define CHOICE_SHAPE ((SHAPE_COL<<CHOICE_SHIFT)|SHAPE_ROW)
136 #define CHOICE_STRETCHTEXT ((STRETCHTEXT_COL<<CHOICE_SHIFT)|STRETCHTEXT_ROW)
137 #define CHOICE_LINE_WIDTH ((LINE_WIDTH_COL<<CHOICE_SHIFT)|LINE_WIDTH_ROW)
138 #define CHOICE_LINE_STYLE ((LINE_STYLE_COL<<CHOICE_SHIFT)|LINE_STYLE_ROW)
139 #define CHOICE_LINE_TYPE ((LINE_TYPE_COL<<CHOICE_SHIFT)|LINE_TYPE_ROW)
140 #define CHOICE_DASH ((DASH_COL<<CHOICE_SHIFT)|DASH_ROW)
141 #define CHOICE_FILL ((FILL_COL<<CHOICE_SHIFT)|FILL_ROW)
142 #define CHOICE_PEN ((PEN_COL<<CHOICE_SHIFT)|PEN_ROW)
143 #define CHOICE_TRANSPAT ((TRANSPAT_COL<<CHOICE_SHIFT)|TRANSPAT_ROW)
144 #define CHOICE_PAGE ((PAGE_COL<<CHOICE_SHIFT)|PAGE_ROW)
145 #define CHOICE_PAGELAYOUT ((PAGELAYOUT_COL<<CHOICE_SHIFT)|PAGELAYOUT_ROW)
146 
147 int	curChoice=NOTHING;
148 int	cycleThroughChoice=FALSE;
149 
150 int	setCurChoiceDontUpdateUI=FALSE;
151 
152 static int	curRaisedChoice=INVALID;
153 static int	curRaisedMode=INVALID;
154 
155 static GC	choiceGC=(GC)0;
156 
157 static Pixmap	abcBitmap=None, rotatedAbcBitmap=None;
158 static XImage	*abcImage=NULL;
159 static int	abcRotation=0, abcRotatedBitmapSize=0;
160 static struct BBRec rotatedAbcBBox;
161 
162 #include "xbm/abc.xbm"
163 
InitChoice()164 void InitChoice()
165 {
166    XGCValues values;
167 
168    values.foreground = xorOne;
169    values.background = xorZero;
170    values.fill_style = FillSolid;
171    values.font = defaultFontPtr->fid;
172    choiceGC = XCreateGC(mainDisplay, choiceWindow,
173          GCForeground | GCBackground | GCFillStyle | GCFont, &values);
174 
175    memset(&rotatedAbcBBox, 0, sizeof(struct BBRec));
176    abcBitmap = XCreateBitmapFromData(mainDisplay, choiceWindow,
177          (char *)abc_bits, abc_width, abc_height);
178    if (abcBitmap == None) FailAllocPixmapMessage(abc_width, abc_height);
179 
180    abcImage = XGetImage(mainDisplay, abcBitmap, 0, 0, abc_width, abc_height, 1,
181          ZPixmap);
182    if (abcImage == NULL) FailAllocMessage();
183 }
184 
CleanUpChoices()185 void CleanUpChoices()
186 {
187    XFreeGC(mainDisplay, choiceGC);
188    choiceGC = (GC)0;
189 
190    XFreePixmap(mainDisplay, abcBitmap);
191    XDestroyImage(abcImage);
192    abcImage = NULL;
193    if (rotatedAbcBitmap != None) XFreePixmap(mainDisplay, rotatedAbcBitmap);
194    abcBitmap = rotatedAbcBitmap = None;
195 }
196 
197 static
ShowStipple(dpy,win,gc,bitmap,col,row,w,h)198 void ShowStipple(dpy, win, gc, bitmap, col, row, w, h)
199    Display *dpy;
200    Window win;
201    GC gc;
202    Pixmap bitmap;
203    int col, row, w, h;
204 {
205    if (threeDLook) {
206       int x=1+windowPadding+col*(choiceImageW+windowPadding);
207       int y=1+windowPadding+row*(choiceImageH+windowPadding);
208       XGCValues values;
209 
210       values.stipple = bitmap;
211       values.ts_x_origin = x;
212       values.ts_y_origin = y;
213       XChangeGC(dpy, gc,
214             GCStipple | GCTileStipXOrigin | GCTileStipYOrigin, &values);
215       XFillRectangle(dpy, win, gc, x, y, w, h);
216       XSetTSOrigin(dpy, gc, 0, 0);
217    } else {
218       int x=col*choiceImageW, y=row*choiceImageH;
219 
220       XSetStipple(dpy, gc, bitmap);
221       XFillRectangle(dpy, win, gc, x, y, w, h);
222    }
223 }
224 
225 static
HighLightThreeDButton(choice,highlight)226 void HighLightThreeDButton(choice, highlight)
227    int choice, highlight;
228 {
229    struct BBRec bbox;
230    int col=0, row=0;
231 
232    if (!threeDLook) return;
233 
234    col = (choice>>CHOICE_SHIFT);
235    row = choice-(col<<CHOICE_SHIFT);
236    bbox.ltx = 1+col*(choiceImageW+windowPadding);
237    bbox.lty = 1+row*(choiceImageH+windowPadding);
238    bbox.rbx = bbox.ltx+choiceImageW+(windowPadding<<1);
239    bbox.rby = bbox.lty+choiceImageH+(windowPadding<<1);
240    if (highlight) {
241       TgDrawThreeDButton(mainDisplay, choiceWindow, textMenuGC, &bbox,
242             TGBS_RAISED, 2, FALSE);
243    } else {
244       TgClearThreeDButton(mainDisplay, choiceWindow, textMenuGC, &bbox, 2);
245    }
246 }
247 
248 static
UpdateAbcBitmap()249 void UpdateAbcBitmap()
250 {
251    XImage *image;
252    int r, ltx, lty, rbx, rby, half_sz;
253    struct XfrmMtrxRec ctm;
254    double radian, sin_val, cos_val;
255 
256    if (textRotation == 0) return;
257    if (textRotation == abcRotation && rotatedAbcBitmap != None) return;
258    if (rotatedAbcBitmap == None) {
259       double dval=(double)sqrt(
260             (double)(abc_width*abc_width+abc_height*abc_height));
261 
262       abcRotatedBitmapSize = ((round(dval)+2)<<1);
263       if ((rotatedAbcBitmap=XCreatePixmap(mainDisplay, dummyBitmap,
264             abcRotatedBitmapSize, abcRotatedBitmapSize, 1)) == None) {
265          FailAllocPixmapMessage(abcRotatedBitmapSize, abcRotatedBitmapSize);
266          return;
267       }
268    }
269    XFillRectangle(mainDisplay, rotatedAbcBitmap, xbmGC, 0, 0,
270          abcRotatedBitmapSize, abcRotatedBitmapSize);
271    image = XGetImage(mainDisplay, rotatedAbcBitmap, 0, 0, abcRotatedBitmapSize,
272          abcRotatedBitmapSize, 1, ZPixmap);
273    if (image == NULL) {
274       FailAllocMessage();
275       return;
276    }
277    radian = (((double)textRotation)*M_PI/180.0/64.0);
278    sin_val = sin(radian);
279    cos_val = cos(radian);
280 
281    memset(&ctm, 0, sizeof(struct XfrmMtrxRec));
282    ctm.m[CTM_SX] = ctm.m[CTM_SY] = ((double)1000)*cos_val;
283    ctm.m[CTM_SIN] = ((double)1000)*sin_val;
284    ctm.m[CTM_MSIN] = (-ctm.m[CTM_SIN]);
285    ctm.t[CTM_TX] = ctm.t[CTM_TY] = 0;
286    ltx = lty = abcRotatedBitmapSize+1;
287    rbx = rby = (-1);
288    half_sz = (abcRotatedBitmapSize>>1);
289    for (r=0; r < abcRotatedBitmapSize; r++) {
290       int c, y=r-half_sz;
291       double dy=((double)y)+0.5;
292 
293       for (c=0; c < abcRotatedBitmapSize; c++) {
294          int x=c-half_sz;
295          double dx=((double)x)+0.5;
296          double new_dx=(double)0, new_dy=(double)0;
297 
298          ReverseTransformDoublePointThroughCTM(dx, dy, &ctm, &new_dx, &new_dy);
299          if (new_dx >= ((double)0) && new_dx < ((double)abc_width) &&
300                new_dy >= ((double)0) && new_dy < ((double)abc_height)) {
301             int new_x=(int)new_dx, new_y=(int)new_dy;
302 
303             if (new_x < 0) new_x = 0;
304             if (new_x >= abc_width) new_x = abc_width-1;
305             if (new_y < 0) new_y = 0;
306             if (new_y >= abc_height) new_y = abc_height-1;
307             if (XGetPixel(abcImage, new_x, new_y) == 1) {
308                XPutPixel(image, c, r, 1);
309                if (c < ltx) ltx = c; if (r < lty) lty = r;
310                if (c > rbx) rbx = c; if (r > rby) rby = r;
311             }
312          }
313       }
314    }
315    XPutImage(mainDisplay, rotatedAbcBitmap, xbmGC, image, 0, 0, 0, 0,
316          abcRotatedBitmapSize, abcRotatedBitmapSize);
317    XDestroyImage(image);
318    rotatedAbcBBox.ltx = ltx; rotatedAbcBBox.lty = lty;
319    rotatedAbcBBox.rbx = rbx; rotatedAbcBBox.rby = rby;
320 }
321 
ShowWhereToPrint()322 void ShowWhereToPrint()
323 {
324    if (colorDump) {
325       XSetForeground(mainDisplay, rasterGC, colorPixels[colorIndex]);
326    }
327    ShowStipple(mainDisplay, choiceWindow, rasterGC,
328          whereToPrintPixmap[whereToPrint], PRINT_COL,
329          PRINT_ROW, choiceImageW, choiceImageH);
330    if (colorDump) XSetForeground(mainDisplay, rasterGC, myFgPixel);
331 }
332 
ShowColor(PropagateWhereToPrint)333 void ShowColor(PropagateWhereToPrint)
334    int PropagateWhereToPrint;
335 {
336    XGCValues values;
337 
338    if (colorDisplay) {
339       int x=COLOR_COL*choiceImageW, y=COLOR_ROW*choiceImageH;
340 
341       if (threeDLook) {
342          x = 1+windowPadding+COLOR_COL*(choiceImageW+windowPadding);
343          y = 1+windowPadding+COLOR_ROW*(choiceImageH+windowPadding);
344       }
345       values.foreground = colorPixels[colorIndex];
346       values.function = GXcopy;
347       values.fill_style = FillOpaqueStippled;
348       values.stipple = patPixmap[1];
349       XChangeGC(mainDisplay, patGC,
350             GCForeground | GCFunction | GCFillStyle | GCStipple, &values);
351 
352       XFillRectangle(mainDisplay, choiceWindow, patGC, x, y,
353             choiceImageW, choiceImageH);
354    }
355    if (PropagateWhereToPrint) ShowWhereToPrint();
356 }
357 
ShowHoriAlign()358 void ShowHoriAlign()
359 {
360    ShowStipple(mainDisplay, choiceWindow, rasterGC, alignHoriPixmap[horiAlign],
361          HORI_ALIGN_COL, HORI_ALIGN_ROW, choiceImageW, choiceImageH);
362 }
363 
ShowVertAlign()364 void ShowVertAlign()
365 {
366    ShowStipple(mainDisplay, choiceWindow, rasterGC, alignVertPixmap[vertAlign],
367          VERT_ALIGN_COL, VERT_ALIGN_ROW, choiceImageW, choiceImageH);
368 }
369 
ShowJust()370 void ShowJust()
371 {
372    ShowStipple(mainDisplay, choiceWindow, rasterGC, justPixmap[textJust],
373          JUST_COL, JUST_ROW, choiceImageW, choiceImageH);
374 }
375 
ShowCurFont()376 void ShowCurFont()
377 {
378    static int snPrevShowDoubleByteFont=INVALID;
379 
380    char *choice_char=GetShowFontChar(curFont);
381    int x, y, w, h, choice_len=(choice_char==NULL ? 0 : strlen(choice_char));
382    XRectangle recs[1];
383    XGCValues values;
384    int image_x=FONT_COL*choiceImageW, image_y=FONT_ROW*choiceImageH;
385    int saved_sz_unit=curSzUnit;
386 
387    if (threeDLook) {
388       image_x = 1+windowPadding+FONT_COL*(choiceImageW+windowPadding);
389       image_y = 1+windowPadding+FONT_ROW*(choiceImageH+windowPadding);
390    }
391    recs[0].x = image_x;
392    recs[0].y = image_y;
393    recs[0].width = choiceImageW;
394    recs[0].height = choiceImageH;
395 
396    if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
397       curSzUnit = GetCurSzUnit();
398       SetCanvasFont();
399    }
400    if (choice_char != NULL && canvasFontDoubleByte &&
401          canvasFontDoubleByteModBytes) {
402       choice_char[0] |= 0x80;
403       choice_char[1] |= 0x80;
404    }
405    if (choice_char == NULL) {
406       /* do not translate -- the string is used to measure things */
407       w = XTextWidth(canvasFontPtr, "W", 1);
408    } else {
409       w = MyTextWidth(canvasFontPtr, choice_char, choice_len);
410    }
411    h = canvasFontHeight;
412 
413    XClearArea(mainDisplay, choiceWindow, image_x-windowPadding,
414          image_y-windowPadding, choiceImageW+(windowPadding<<1),
415          choiceImageH+(windowPadding<<1), FALSE);
416 
417    XSetFont(mainDisplay, choiceGC, canvasFontPtr->fid);
418    XSetClipRectangles(mainDisplay, choiceGC, 0, 0, recs, 1, YXBanded);
419 
420    values.foreground = myFgPixel;
421    values.background = myBgPixel;
422    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground, &values);
423 
424    x = (w > choiceImageW) ?
425          image_x - (w-choiceImageW)/2 :
426          image_x + (choiceImageW-w)/2;
427    y = (h > choiceImageH) ?
428          image_y + (canvasFontAsc-(h-choiceImageH)/2) :
429          image_y + (canvasFontAsc+(choiceImageH-h)/2);
430    if (canvasFontDoubleByte && canvasFontDoubleByteVertical) {
431       Pixmap bitmap=None;
432       TextExtentsInfo stTextExtents;
433 
434       memset(&stTextExtents, 0, sizeof(TextExtentsInfo));
435       /* choice_char cannot be NULL */
436       stTextExtents.buf = choice_char;
437       stTextExtents.len = choice_len;
438       bitmap = PaintVertChar(&stTextExtents, ROTATE270);
439       if (bitmap == None) {
440          return;
441       }
442       x = image_x + ((choiceImageW-stTextExtents.bbox_h)>>1);
443       y = image_y + ((choiceImageH-stTextExtents.bbox_w)>>1);
444 
445       values.clip_mask = bitmap;
446       values.clip_x_origin = x;
447       values.clip_y_origin = y;
448       XChangeGC(mainDisplay, choiceGC,
449             GCClipMask | GCClipXOrigin | GCClipYOrigin, &values);
450 
451       XFillRectangle(mainDisplay, choiceWindow, choiceGC,
452             (x>image_x ? x : image_x), (y>image_y ? y: image_y),
453             (x>image_x ? stTextExtents.bbox_w : choiceImageW),
454             (y>image_y ? stTextExtents.bbox_h : choiceImageH));
455 
456       values.clip_mask = None;
457       values.clip_x_origin = 0;
458       values.clip_y_origin = 0;
459       XChangeGC(mainDisplay, choiceGC,
460             GCClipMask | GCClipXOrigin | GCClipYOrigin, &values);
461 
462       y += stTextExtents.bbox_w;
463       w = stTextExtents.bbox_h;
464    } else {
465       if (choice_char == NULL) {
466          /* do not translate -- the string is used to measure things */
467          XDrawString(mainDisplay, choiceWindow, choiceGC, x, y, "W", 1);
468       } else {
469          MyDrawString(mainDisplay, choiceWindow, choiceGC, mainDepth, x, y,
470                choice_char, choice_len);
471       }
472    }
473    if (curUnderlineOn) {
474       XDrawLine(mainDisplay, choiceWindow, choiceGC, x, y+curUnderlineYOffset,
475             x+w, y+curUnderlineYOffset);
476    }
477    if (curOverlineOn) {
478       XDrawLine(mainDisplay, choiceWindow, choiceGC,
479             x, y-canvasFontAsc-curOverlineYOffset,
480             x+w, y-canvasFontAsc-curOverlineYOffset);
481    }
482    values.foreground = xorOne;
483    values.background = xorZero;
484    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground, &values);
485 
486    recs[0].x = 0;
487    recs[0].y = 0;
488    recs[0].width = choiceWindowW;
489    recs[0].height = choiceWindowH;
490    XSetClipRectangles(mainDisplay, choiceGC, 0, 0, recs, 1, YXBanded);
491 
492    /*
493     * The following code was added so that when you move the text cursor
494     *         from a double-byte font to a single-byte font, we can close
495     *         the double-byte input method.
496     */
497    if (gnInputMethod != TGIM_NONE) {
498       if (snPrevShowDoubleByteFont != INVALID &&
499             snPrevShowDoubleByteFont && !canvasFontDoubleByte &&
500             tgIMDeactiveOnCreateText(mainDisplay, drawWindow)) {
501          if (tgIMHandleCreateText(mainDisplay, drawWindow)) {
502          }
503       }
504       snPrevShowDoubleByteFont = canvasFontDoubleByte;
505    }
506    if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
507       curSzUnit = saved_sz_unit;
508       SetCanvasFont();
509    }
510 }
511 
ShowTextVSpace()512 void ShowTextVSpace()
513 {
514    int len, x, y;
515    char s[80];
516    XGCValues values;
517    int image_x=VSPACE_COL*choiceImageW, image_y=VSPACE_ROW*choiceImageH;
518 
519    if (threeDLook) {
520       image_x = 1+windowPadding+VSPACE_COL*(choiceImageW+windowPadding);
521       image_y = 1+windowPadding+VSPACE_ROW*(choiceImageH+windowPadding);
522    }
523    ShowStipple(mainDisplay, choiceWindow, rasterGC, vspacePixmap,
524          VSPACE_COL, VSPACE_ROW, choiceImageW, choiceImageH);
525 
526    sprintf(s, "%1d", textVSpace);
527    len = strlen(s);
528    if (threeDLook) {
529       x = image_x+(choiceImageW>>1)-1;
530       y = image_y+((choiceImageH-rulerFontAsc)>>1)+rulerFontAsc;
531    } else {
532       x = (int)((VSPACE_COL+0.5)*choiceImageW-2);
533       y = VSPACE_ROW*choiceImageH+((choiceImageH-rulerFontAsc)>>1)+rulerFontAsc;
534    }
535    values.foreground = myFgPixel;
536    values.background = myBgPixel;
537    values.font = rulerFontPtr->fid;
538    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground | GCFont,
539          &values);
540 
541    XDrawString(mainDisplay, choiceWindow, choiceGC, x, y, s, len);
542 
543    values.foreground = xorOne;
544    values.background = xorZero;
545    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground, &values);
546 }
547 
ShowZoom()548 void ShowZoom()
549 {
550    int len, x, y, w, x_w, one_w;
551    char s[80];
552    XGCValues values;
553    int image_x=ZOOM_COL*choiceImageW, image_y=ZOOM_ROW*choiceImageH;
554 
555    if (threeDLook) {
556       image_x = 1+windowPadding+ZOOM_COL*(choiceImageW+windowPadding);
557       image_y = 1+windowPadding+ZOOM_ROW*(choiceImageH+windowPadding);
558    }
559    XClearArea(mainDisplay, choiceWindow, image_x-windowPadding,
560          image_y-windowPadding, choiceImageW+(windowPadding<<1),
561          choiceImageH+(windowPadding<<1), FALSE);
562 
563    sprintf(s, "x%1d", 1<<zoomScale);
564    len = strlen(s);
565 
566    w = XTextWidth(rulerFontPtr, s, len)+1;
567    x_w = XTextWidth(rulerFontPtr, "x", 1)+1;
568    one_w = XTextWidth(rulerFontPtr, "1", 1);
569    x = image_x+((choiceImageW-w)>>1);
570    y = image_y+((choiceImageH-rulerFontAsc)>>1)+rulerFontAsc;
571    values.foreground = myFgPixel;
572    values.background = myBgPixel;
573    values.font = rulerFontPtr->fid;
574    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground | GCFont,
575          &values);
576 
577    /* do not translate -- program constants */
578    XDrawString(mainDisplay, choiceWindow, choiceGC, x, y, "x", 1);
579 
580    x += x_w;
581    sprintf(s, "%1d", 1<<zoomScale);
582    len--;
583    if (zoomedIn || zoomScale==0) {
584       XDrawString(mainDisplay, choiceWindow, choiceGC, x, y, s, len);
585    } else {
586       y = ZOOM_ROW*choiceImageH + (choiceImageH>>1) + windowPadding + 1;
587       /* do not translate -- program constants */
588       XDrawString(mainDisplay, choiceWindow, choiceGC, x+((w-x_w-one_w)>>1),
589             y-2, "1", 1);
590       XDrawLine(mainDisplay, choiceWindow, choiceGC, x, y, x+(w-x_w-1), y);
591       XDrawString(mainDisplay, choiceWindow, choiceGC, x, y+rulerFontAsc,
592             s, len);
593    }
594    values.foreground = xorOne;
595    values.background = xorZero;
596    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground, &values);
597 }
598 
ShowTextSize()599 void ShowTextSize()
600 {
601    int len, x, y, w;
602    char s[80];
603    XGCValues values;
604    int image_x=TEXT_SIZE_COL*choiceImageW, image_y=TEXT_SIZE_ROW*choiceImageH;
605    int sz_unit=GetCurSzUnit();
606 
607    if (threeDLook) {
608       image_x = 1+windowPadding+TEXT_SIZE_COL*(choiceImageW+windowPadding);
609       image_y = 1+windowPadding+TEXT_SIZE_ROW*(choiceImageH+windowPadding);
610    }
611    XClearArea(mainDisplay, choiceWindow, image_x-windowPadding,
612          image_y-windowPadding, choiceImageW+(windowPadding<<1),
613          choiceImageH+(windowPadding<<1), FALSE);
614 
615    if (showFontSizeInPoints) {
616       sprintf(s, "%1dpt", SzUnitToPointSize(sz_unit));
617    } else {
618       sprintf(s, "%1d", SzUnitToFontSize(sz_unit));
619    }
620    len = strlen(s);
621    w = XTextWidth(defaultFontPtr, s, len);
622    x = image_x + ((choiceImageW-w)>>1);
623    y = image_y + ((choiceImageH-defaultFontAsc)>>1) + defaultFontAsc;
624 
625    values.foreground = myFgPixel;
626    values.background = myBgPixel;
627    values.font = defaultFontPtr->fid;
628    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground | GCFont,
629          &values);
630 
631    XDrawString(mainDisplay, choiceWindow, choiceGC, x, y, s, len);
632 
633    values.foreground = xorOne;
634    values.background = xorZero;
635    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground, &values);
636 }
637 
ShowRotate()638 void ShowRotate()
639 {
640    int ltx, lty, w, h, rbx, rby, x, y;
641    XGCValues values;
642    Pixmap bitmap=None;
643    int image_x=ROTATE_COL*choiceImageW, image_y=ROTATE_ROW*choiceImageH;
644 
645    if (threeDLook) {
646       image_x = 1+windowPadding+ROTATE_COL*(choiceImageW+windowPadding);
647       image_y = 1+windowPadding+ROTATE_ROW*(choiceImageH+windowPadding);
648    }
649    UpdateAbcBitmap();
650    XClearArea(mainDisplay, choiceWindow, image_x-windowPadding,
651          image_y-windowPadding, choiceImageW+(windowPadding<<1),
652          choiceImageH+(windowPadding<<1), FALSE);
653 
654    if (textRotation == 0) {
655       bitmap = abcBitmap;
656       x = 0;
657       y = 0;
658       w = abc_width;
659       h = abc_height;
660    } else {
661       bitmap = rotatedAbcBitmap;
662       x = rotatedAbcBBox.ltx;
663       y = rotatedAbcBBox.lty;
664       w = rotatedAbcBBox.rbx-x;
665       h = rotatedAbcBBox.rby-y;
666    }
667    ltx = ((choiceImageW-w)>>1);
668    lty = ((choiceImageH-h)>>1);
669    rbx = ltx + w;
670    rby = lty + h;
671    if (ltx < 0) {
672       x = (-ltx);
673       w -= x;
674       ltx = 0;
675    }
676    if (lty < 0) {
677       y = (-lty);
678       h -= y;
679       lty = 0;
680    }
681    if (rbx > choiceImageW) {
682       w -= (rbx-choiceImageW);
683       rbx = choiceImageW;
684    }
685    if (rby > choiceImageH) {
686       h -= (rbx-choiceImageH);
687       rby = choiceImageH;
688    }
689    values.foreground = myFgPixel;
690    values.background = myBgPixel;
691    values.function = GXcopy;
692    values.fill_style = FillStippled;
693    values.ts_x_origin = image_x+ltx-x;
694    values.ts_y_origin = image_y+lty-y;
695    values.stipple = bitmap;
696    XChangeGC(mainDisplay, patGC,
697          GCForeground | GCBackground | GCFunction | GCFillStyle | GCStipple |
698          GCTileStipXOrigin | GCTileStipYOrigin, &values);
699    XFillRectangle(mainDisplay, choiceWindow, patGC, image_x+ltx, image_y+lty,
700          rbx-ltx, rby-lty);
701    XSetTSOrigin(mainDisplay, patGC, 0, 0);
702 }
703 
ShowLineWidth()704 void ShowLineWidth()
705 {
706    char s[40];
707    int x, y, len, w;
708    XGCValues values;
709    int image_x=LINE_WIDTH_COL*choiceImageW, image_y=LINE_WIDTH_ROW*choiceImageH;
710 
711    if (threeDLook) {
712       image_x = 1+windowPadding+LINE_WIDTH_COL*(choiceImageW+windowPadding);
713       image_y = 1+windowPadding+LINE_WIDTH_ROW*(choiceImageH+windowPadding);
714    }
715    ShowStipple(mainDisplay, choiceWindow, rasterGC,
716          shortLineWidthPixmap[lineWidth], LINE_WIDTH_COL, LINE_WIDTH_ROW,
717          choiceImageW, choiceImageH);
718 
719    UtilStrCpyN(s, sizeof(s), curWidthOfLineSpec[lineWidth]);
720    len = strlen(s);
721    w = rulerFontWidth * len;
722    x = image_x+((choiceImageW-w)>>1);
723    y = image_y+((choiceImageH-rulerFontAsc)>>1) + rulerFontAsc;
724    values.foreground = (threeDLook ? myLtGryPixel : myBgPixel);
725    values.background = (threeDLook ? myLtGryPixel : myBgPixel);
726    values.font = rulerFontPtr->fid;
727    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground | GCFont,
728          &values);
729    XFillRectangle(mainDisplay, choiceWindow, choiceGC,
730          x-2, y-rulerFontAsc-2, w+4, rulerFontAsc+4);
731    XSetForeground(mainDisplay, choiceGC, myFgPixel);
732    XDrawString(mainDisplay, choiceWindow, choiceGC, x, y, s, len);
733    values.foreground = xorOne;
734    values.background = xorZero;
735    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground, &values);
736 }
737 
ShowLineStyle()738 void ShowLineStyle()
739 {
740    ShowStipple(mainDisplay, choiceWindow, rasterGC,
741          shortLineStylePixmap[lineStyle], LINE_STYLE_COL, LINE_STYLE_ROW,
742          choiceImageW, choiceImageH);
743 }
744 
ShowLineType()745 void ShowLineType()
746 {
747    ShowStipple(mainDisplay, choiceWindow, rasterGC,
748          shortLineTypePixmap[curSpline], LINE_TYPE_COL, LINE_TYPE_ROW,
749          choiceImageW, choiceImageH);
750 }
751 
ShowDash()752 void ShowDash()
753 {
754    ShowStipple(mainDisplay, choiceWindow, rasterGC, shortDashPixmap[curDash],
755          DASH_COL, DASH_ROW, choiceImageW, choiceImageH);
756 }
757 
ShowFile()758 void ShowFile()
759 {
760    switch (pageStyle) {
761    case PORTRAIT:
762       ShowStipple(mainDisplay, choiceWindow, rasterGC, filePixmap,
763             FILE_COL, FILE_ROW, choiceImageW, choiceImageH);
764       break;
765    case LANDSCAPE:
766       ShowStipple(mainDisplay, choiceWindow, rasterGC, landscapePixmap,
767             FILE_COL, FILE_ROW, choiceImageW, choiceImageH);
768       break;
769    }
770 }
771 
ShowRCBRadius()772 void ShowRCBRadius()
773 {
774    int len, x, y;
775    char s[80];
776    XGCValues values;
777    int image_x=RADIUS_COL*choiceImageW, image_y=RADIUS_ROW*choiceImageH;
778 
779    if (threeDLook) {
780       image_x = 1+windowPadding+RADIUS_COL*(choiceImageW+windowPadding);
781       image_y = 1+windowPadding+RADIUS_ROW*(choiceImageH+windowPadding);
782    }
783    ShowStipple(mainDisplay, choiceWindow, rasterGC, rcbRadiusPixmap,
784          RADIUS_COL, RADIUS_ROW, choiceImageW, choiceImageH);
785 
786    sprintf(s, "%1d", rcbRadius);
787    len = strlen(s);
788    if (threeDLook) {
789       x = image_x+(choiceImageW>>1)-1;
790       y = image_y+((choiceImageH-rulerFontAsc)>>1)+rulerFontAsc;
791    } else {
792       x = (int)((RADIUS_COL+0.5)*choiceImageW-2);
793       y = (((RADIUS_ROW+1)*choiceImageH-rulerFontAsc)>>1)+rulerFontAsc;
794    }
795    values.foreground = myFgPixel;
796    values.background = myBgPixel;
797    values.font = rulerFontPtr->fid;
798    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground | GCFont,
799          &values);
800 
801    XDrawString(mainDisplay, choiceWindow, choiceGC, x, y, s, len);
802 
803    values.foreground = xorOne;
804    values.background = xorZero;
805    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground, &values);
806 }
807 
ShowMoveMode()808 void ShowMoveMode()
809 {
810    ShowStipple(mainDisplay, choiceWindow, rasterGC, moveModePixmap[moveMode],
811          MOVE_MODE_COL, MOVE_MODE_ROW, choiceImageW, choiceImageH);
812 }
813 
ShowShape()814 void ShowShape()
815 {
816    ShowStipple(mainDisplay, choiceWindow, rasterGC, shapePixmap[SHAPE_STAR],
817          SHAPE_COL, SHAPE_ROW, choiceImageW, choiceImageH);
818 }
819 
ShowStretchableTextMode()820 void ShowStretchableTextMode()
821 {
822    ShowStipple(mainDisplay, choiceWindow, rasterGC,
823          stretchableModePixmap[stretchableText], STRETCHTEXT_COL,
824          STRETCHTEXT_ROW, choiceImageW, choiceImageH);
825 }
826 
ShowFill()827 void ShowFill()
828 {
829    XGCValues values;
830    int image_x=FILL_COL*choiceImageW, image_y=FILL_ROW*choiceImageH;
831 
832    if (threeDLook) {
833       image_x = 1+windowPadding+FILL_COL*(choiceImageW+windowPadding);
834       image_y = 1+windowPadding+FILL_ROW*(choiceImageH+windowPadding);
835    }
836    values.foreground = myFgPixel;
837    values.background = (threeDLook ? myLtGryPixel : myBgPixel);
838    values.function = GXcopy;
839    values.fill_style = FillOpaqueStippled;
840    values.stipple = patPixmap[objFill];
841    values.ts_x_origin = image_x;
842    values.ts_y_origin = image_y;
843    XChangeGC(mainDisplay, patGC,
844          GCForeground | GCBackground | GCFunction | GCFillStyle | GCStipple |
845          GCTileStipXOrigin | GCTileStipYOrigin, &values);
846 
847    XFillRectangle(mainDisplay, choiceWindow, patGC, image_x, image_y,
848          choiceImageW, choiceImageH);
849    XSetTSOrigin(mainDisplay, patGC, 0, 0);
850 }
851 
ShowTransPatMode()852 void ShowTransPatMode()
853 {
854    ShowStipple(mainDisplay, choiceWindow, rasterGC, transPatPixmap[transPat],
855          TRANSPAT_COL, TRANSPAT_ROW, choiceImageW, choiceImageH);
856 }
857 
ShowPen()858 void ShowPen()
859 {
860    XGCValues values;
861    int image_x=PEN_COL*choiceImageW, image_y=PEN_ROW*choiceImageH;
862 
863    if (threeDLook) {
864       image_x = 1+windowPadding+PEN_COL*(choiceImageW+windowPadding);
865       image_y = 1+windowPadding+PEN_ROW*(choiceImageH+windowPadding);
866    }
867    values.foreground = myFgPixel;
868    values.background = (threeDLook ? myLtGryPixel : myBgPixel);
869    values.function = GXcopy;
870    values.fill_style = FillOpaqueStippled;
871    values.stipple = patPixmap[penPat];
872    values.ts_x_origin = image_x;
873    values.ts_y_origin = image_y;
874    XChangeGC(mainDisplay, patGC,
875          GCForeground | GCBackground | GCFunction | GCFillStyle | GCStipple |
876          GCTileStipXOrigin | GCTileStipYOrigin, &values);
877 
878    XFillRectangle(mainDisplay, choiceWindow, patGC, image_x, image_y,
879          choiceImageW, choiceImageH);
880    XSetTSOrigin(mainDisplay, patGC, 0, 0);
881    if (penPat != NONEPAT) {
882       XClearArea(mainDisplay, choiceWindow,
883             image_x+(choiceImageW>>2), image_y+(choiceImageH>>2),
884             (choiceImageW>>1), (choiceImageH>>1), FALSE);
885    }
886 }
887 
ShowPage()888 void ShowPage()
889 {
890    int len, x, y, w;
891    char s[80];
892    XGCValues values;
893    int image_x=PAGE_COL*choiceImageW, image_y=PAGE_ROW*choiceImageH;
894 
895    if (threeDLook) {
896       image_x = 1+windowPadding+PAGE_COL*(choiceImageW+windowPadding);
897       image_y = 1+windowPadding+PAGE_ROW*(choiceImageH+windowPadding);
898    }
899    XClearArea(mainDisplay, choiceWindow, image_x-windowPadding,
900          image_y-windowPadding, choiceImageW+(windowPadding<<1),
901          choiceImageH+(windowPadding<<1), FALSE);
902 
903    switch (pageLayoutMode) {
904    case PAGE_STACK: sprintf(s, "%1d/%1d", curPageNum, lastPageNum); break;
905    case PAGE_TILE: sprintf(s, "%1dx%1d", paperCol, paperRow); break;
906    }
907    len = strlen(s);
908    w = XTextWidth(rulerFontPtr, s, len);
909    x = image_x+((choiceImageW-w)>>1);
910    y = image_y+((choiceImageH-rulerFontAsc)>>1) + rulerFontAsc;
911 
912    values.foreground = myFgPixel;
913    values.background = myBgPixel;
914    values.font = rulerFontPtr->fid;
915    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground | GCFont,
916          &values);
917 
918    XDrawString(mainDisplay, choiceWindow, choiceGC, x, y, s, len);
919 
920    values.foreground = xorOne;
921    values.background = xorZero;
922    XChangeGC(mainDisplay, choiceGC, GCForeground | GCBackground,
923          &values);
924 
925    RedrawPageWindow();
926 }
927 
ShowPageLayout()928 void ShowPageLayout()
929 {
930    int image_x=PAGELAYOUT_COL*choiceImageW, image_y=PAGELAYOUT_ROW*choiceImageH;
931 
932    if (threeDLook) {
933       image_x = 1+windowPadding+PAGELAYOUT_COL*(choiceImageW+windowPadding);
934       image_y = 1+windowPadding+PAGELAYOUT_ROW*(choiceImageH+windowPadding);
935    }
936    XClearArea(mainDisplay, choiceWindow, image_x-windowPadding,
937          image_y-windowPadding, choiceImageW+(windowPadding<<1),
938          choiceImageH+(windowPadding<<1), FALSE);
939    ShowStipple(mainDisplay, choiceWindow, rasterGC,
940          pageLayoutPixmap[pageLayoutMode], PAGELAYOUT_COL, PAGELAYOUT_ROW,
941          choiceImageW, choiceImageH);
942 }
943 
944 static
NeedSelectTopObject(Choice,VertexTypeObj)945 int NeedSelectTopObject(Choice, VertexTypeObj)
946    int Choice, VertexTypeObj;
947 {
948    if (VertexTypeObj) {
949       return (Choice==NOTHING || Choice==VERTEXMODE || Choice==ROTATEMODE);
950    } else {
951       return (Choice==NOTHING || Choice==ROTATEMODE);
952    }
953 }
954 
ShowCurChoiceMouseStatus(choice,state,cur_text_under_mouse)955 void ShowCurChoiceMouseStatus(choice, state, cur_text_under_mouse)
956    int choice, cur_text_under_mouse;
957    unsigned int state; /* 0 or ControlMask */
958 {
959    if (choice == INVALID) {
960       SetMouseStatus(TgLoadCachedString(CSTID_PARANED_NONE),
961             TgLoadCachedString(CSTID_MAIN_MENU),
962             TgLoadCachedString(CSTID_PARANED_NONE));
963    } else if (choice == NOTHING && inHyperSpace) {
964       SetCurChoiceMouseStatusStrings(choice, TRUE, NULL, cur_text_under_mouse,
965             state);
966    } else {
967       SetCurChoiceMouseStatusStrings(choice, FALSE, NULL, cur_text_under_mouse,
968             state);
969    }
970 }
971 
SetCurChoice(NewChoice)972 void SetCurChoice(NewChoice)
973    int NewChoice;
974 {
975    struct ObjRec *selected_single_text_obj=NULL;
976    int old_choice=curChoice, sel_top_obj=FALSE;
977 
978    if (curChoice == NewChoice) return;
979    if (gstWBInfo.do_whiteboard && (serializingFile || deserializingFile)) {
980       return;
981    }
982    if (inSlideShow) {
983       if (NewChoice == NOTHING || NewChoice == DRAWTEXT ||
984             NewChoice == VERTEXMODE || NewChoice == ROTATEMODE) {
985          /* these modes are not allowed in slideshow */
986          return;
987       }
988    }
989    switch (curChoice) {
990    case NOTHING:
991       if (topSel != NULL) {
992          if (NewChoice == VERTEXMODE) {
993             UnSelNonVertexObjs(TRUE, TRUE); /* with highlight */
994             UpdSelBBox();
995          } else if (NewChoice != ROTATEMODE) {
996             if (NewChoice == DRAWTEXT && topSel != NULL && topSel == botSel &&
997                   topSel->obj->type == OBJ_TEXT) {
998                selected_single_text_obj = topSel->obj;
999             }
1000             HighLightReverse();
1001             RemoveAllSel();
1002          } else {
1003             HighLightReverse();
1004          }
1005       }
1006       break;
1007    case DRAWTEXT:
1008       CreateTextObj(TRUE, TRUE);
1009       if (NeedSelectTopObject(NewChoice, FALSE) && textDrawn) {
1010          HighLightJustDrawnText();
1011          sel_top_obj = TRUE;
1012       }
1013       textDrawn = FALSE;
1014       textCursorShown = FALSE;
1015       break;
1016    case DRAWBOX:
1017       if (NeedSelectTopObject(NewChoice, FALSE) && boxDrawn) {
1018          SelectTopObj();
1019          sel_top_obj = TRUE;
1020       }
1021       boxDrawn = FALSE;
1022       break;
1023    case DRAWCORNEROVAL:
1024    case DRAWCENTEROVAL:
1025    case DRAWEDGECIRCLE:
1026       if (NeedSelectTopObject(NewChoice, FALSE) && ovalDrawn) {
1027          SelectTopObj();
1028          sel_top_obj = TRUE;
1029       }
1030       ovalDrawn = FALSE;
1031       break;
1032    case DRAWPOLY:
1033       if (NeedSelectTopObject(NewChoice, TRUE) && polyDrawn) {
1034          SelectTopObj();
1035          sel_top_obj = TRUE;
1036       }
1037       polyDrawn = FALSE;
1038       break;
1039    case DRAWPOLYGON:
1040       if (NeedSelectTopObject(NewChoice, TRUE) && polygonDrawn) {
1041          SelectTopObj();
1042          sel_top_obj = TRUE;
1043       }
1044       polygonDrawn = FALSE;
1045       break;
1046    case DRAWARC:
1047    case DRAWEDGEARC:
1048       if (NeedSelectTopObject(NewChoice, FALSE) && arcDrawn) {
1049          SelectTopObj();
1050          sel_top_obj = TRUE;
1051       }
1052       arcDrawn = FALSE;
1053       break;
1054    case DRAWRCBOX:
1055       if (NeedSelectTopObject(NewChoice, FALSE) && rcBoxDrawn) {
1056          SelectTopObj();
1057          sel_top_obj = TRUE;
1058       }
1059       rcBoxDrawn = FALSE;
1060       break;
1061    case FREEHAND:
1062       if (NeedSelectTopObject(NewChoice, TRUE) && polyDrawn) {
1063          SelectTopObj();
1064          sel_top_obj = TRUE;
1065       }
1066       polyDrawn = FALSE;
1067       break;
1068    case VERTEXMODE:
1069       if (NewChoice == NOTHING) {
1070          HighLightReverse();
1071          JustRemoveAllVSel();
1072          HighLightForward();
1073       } else if (NewChoice == ROTATEMODE) {
1074          HighLightReverse();
1075          JustRemoveAllVSel();
1076       } else {
1077          HighLightReverse();
1078          RemoveAllSel();
1079       }
1080       break;
1081    case ROTATEMODE:
1082       if (topSel != NULL) {
1083          if (NewChoice == VERTEXMODE) {
1084             UnSelNonVertexObjs(TRUE, TRUE); /* with highlight */
1085             UpdSelBBox();
1086             HighLightReverse();
1087          } else if (NewChoice != NOTHING) {
1088             if (NewChoice == DRAWTEXT && topSel != NULL && topSel == botSel &&
1089                   topSel->obj->type == OBJ_TEXT) {
1090                selected_single_text_obj = topSel->obj;
1091             }
1092             HighLightReverse();
1093             RemoveAllSel();
1094          } else {
1095             HighLightReverse();
1096          }
1097       }
1098       break;
1099    }
1100 
1101    curChoice = NewChoice;
1102 
1103    switch (curChoice) {
1104    case DRAWTEXT:
1105    case DRAWBOX:
1106    case DRAWCORNEROVAL:
1107    case DRAWCENTEROVAL:
1108    case DRAWEDGECIRCLE:
1109    case DRAWPOLY:
1110    case DRAWPOLYGON:
1111    case DRAWARC:
1112    case DRAWEDGEARC:
1113    case DRAWRCBOX:
1114    case FREEHAND:
1115       if (colorLayers && !colorLayerOn[colorIndex]) {
1116          sprintf(gszMsgBox, TgLoadString(STID_INVISIBLE_COLOR_SELECTED_YNC),
1117                colorIndex, colorMenuItems[colorIndex]);
1118          if (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB) == MB_ID_YES) {
1119             colorLayerOn[colorIndex] = TRUE;
1120             RedrawColorWindow();
1121             ClearAndRedrawDrawWindow();
1122          }
1123       }
1124       break;
1125    case NOTHING:
1126       if (old_choice != VERTEXMODE && !sel_top_obj) {
1127          HighLightForward();
1128       }
1129       break;
1130    case VERTEXMODE:
1131       if (old_choice == ROTATEMODE) {
1132          HighLightForward();
1133       }
1134       break;
1135    case ROTATEMODE:
1136       if (sel_top_obj) {
1137          curChoice = old_choice;
1138          HighLightReverse();
1139          curChoice = ROTATEMODE;
1140          HighLightForward();
1141       } else if (old_choice == NOTHING) {
1142          HighLightForward();
1143       } else if (old_choice == VERTEXMODE) {
1144          HighLightForward();
1145       }
1146       break;
1147    }
1148    if (!setCurChoiceDontUpdateUI) {
1149       ShowCursor();
1150 
1151       RedrawModeWindow();
1152       UpdatePinnedMenu(MENU_MODE);
1153 
1154       ShowCurChoiceMouseStatus(curChoice, 0, FALSE);
1155    }
1156    textCursorShown = FALSE;
1157 
1158    if (inHyperSpace && curChoice != NOTHING) {
1159       ToggleHyperSpace(FALSE);
1160    } else if (!inHyperSpace && selected_single_text_obj != NULL) {
1161       CleanOuterInnerSel();
1162       CleanOuterInnerSelForFind();
1163       HighLightText(selected_single_text_obj, NULL, INVALID, NULL, INVALID);
1164    }
1165 }
1166 
1167 static int prevChoice=NOTHING;
1168 
PushCurChoice()1169 void PushCurChoice()
1170    /* Kouichi Matsuda's modification */
1171 {
1172    if (curChoice == NOTHING) {
1173       SetCurChoice(prevChoice);
1174    } else {
1175       prevChoice = curChoice;
1176       SetCurChoice(NOTHING);
1177    }
1178 }
1179 
1180 static
TextVSpaceLoop(button_ev)1181 void TextVSpaceLoop(button_ev)
1182    XButtonEvent *button_ev;
1183 {
1184    int saved_text_vspace=textVSpace, res=8, done=FALSE, need_to_restore=FALSE;
1185    int orig_x=button_ev->x, orig_y=button_ev->y, saved_change=0;
1186    XEvent ev;
1187 
1188    if (!debugNoPointerGrab) {
1189       XGrabPointer(mainDisplay, choiceWindow, False,
1190             PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
1191             GrabModeAsync, None, handCursor, CurrentTime);
1192    }
1193    while (!done) {
1194       XNextEvent(mainDisplay, &ev);
1195 
1196       if (ev.type == Expose || ev.type == VisibilityNotify) {
1197          ExposeEventHandler(&ev, TRUE);
1198       } else if (ev.type == ButtonRelease) {
1199          XUngrabPointer(mainDisplay, CurrentTime);
1200          done = TRUE;
1201       } else if (ev.type == MotionNotify) {
1202          int dx=ev.xmotion.x-orig_x, dy=ev.xmotion.y-orig_y;
1203          int change=((abs(dx)>abs(dy)) ? (int)(dx/res) : (int)(dy/res));
1204 
1205          if (change != saved_change) {
1206             textVSpace = saved_text_vspace+change;
1207             ShowTextVSpace();
1208             saved_change = change;
1209          }
1210          while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1211       }
1212    }
1213    ShowTextVSpace();
1214    if ((topSel == NULL || stickyMenuSelection) &&
1215          (textCursorH+textVSpace <= 0)) {
1216       need_to_restore = TRUE;
1217    }
1218    ChangeVSpace(textVSpace);
1219    if (need_to_restore) {
1220       textVSpace = saved_text_vspace;
1221       ShowTextVSpace();
1222    }
1223 }
1224 
1225 static
RCBRadiusLoop(button_ev)1226 void RCBRadiusLoop(button_ev)
1227    XButtonEvent *button_ev;
1228 {
1229    int saved_rcb_radius = rcbRadius, res=8, done=FALSE;
1230    int orig_x=button_ev->x, orig_y=button_ev->y, saved_change=0;
1231    XEvent ev;
1232 
1233    if (!debugNoPointerGrab) {
1234       XGrabPointer(mainDisplay, choiceWindow, False,
1235             PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
1236             GrabModeAsync, None, handCursor, CurrentTime);
1237    }
1238    while (!done) {
1239       XNextEvent(mainDisplay, &ev);
1240 
1241       if (ev.type == Expose || ev.type == VisibilityNotify) {
1242          ExposeEventHandler(&ev, TRUE);
1243       } else if (ev.type == ButtonRelease) {
1244          XUngrabPointer(mainDisplay, CurrentTime);
1245          done = TRUE;
1246       } else if (ev.type == MotionNotify) {
1247          int dx=ev.xmotion.x-orig_x, dy=ev.xmotion.y-orig_y;
1248          int change=((abs(dx)>abs(dy)) ? (int)(dx/res) : (int)(dy/res));
1249 
1250          if (change != saved_change) {
1251             rcbRadius = max(MIN_RCB_RADIUS, saved_rcb_radius+change);
1252             ShowRCBRadius();
1253             saved_change = change;
1254          }
1255          while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1256       }
1257    }
1258    if (topSel != NULL) ChangeAllSelRCBRadius(rcbRadius);
1259 }
1260 
1261 static
ZoomLoop(button_ev)1262 void ZoomLoop(button_ev)
1263    XButtonEvent *button_ev;
1264 {
1265    int saved_zoomed_in=zoomedIn, saved_zoom_scale=zoomScale, res=8;
1266    int new_zoomed_in, new_zoom_scale, done=FALSE, saved_change=0;
1267    int initial_zoom, zoom, max_zoom, win_w, win_h;
1268    int orig_x=button_ev->x, orig_y=button_ev->y;
1269    XEvent ev;
1270 
1271    initial_zoom = (zoomedIn) ? (MAX_ZOOMED_IN-zoomScale) :
1272          (MAX_ZOOMED_IN+zoomScale);
1273 
1274    win_w = drawWinW;
1275    win_h = drawWinH;
1276    new_zoomed_in = zoomedIn;
1277    new_zoom_scale = zoomScale;
1278    while ((win_w>>1) >= paperWidth && (win_h>>1) >= paperHeight) {
1279       if (new_zoomed_in) {
1280          new_zoom_scale++;
1281       } else if (new_zoom_scale == 0) {
1282          new_zoomed_in = TRUE;
1283          new_zoom_scale++;
1284       } else {
1285          new_zoom_scale--;
1286       }
1287       win_w >>= 1;
1288       win_h >>= 1;
1289    }
1290    while (win_w < paperWidth || win_h < paperHeight) {
1291       if (!new_zoomed_in) {
1292          new_zoom_scale++;
1293       } else if (new_zoom_scale == 1) {
1294          new_zoomed_in = FALSE;
1295          new_zoom_scale--;
1296       } else {
1297          new_zoom_scale--;
1298       }
1299       win_w <<= 1;
1300       win_h <<= 1;
1301    }
1302    max_zoom = (new_zoomed_in) ? (MAX_ZOOMED_IN-new_zoom_scale) :
1303          (MAX_ZOOMED_IN+new_zoom_scale);
1304 
1305    if (!debugNoPointerGrab) {
1306       XGrabPointer(mainDisplay, choiceWindow, False,
1307             PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
1308             GrabModeAsync, None, handCursor, CurrentTime);
1309    }
1310    while (!done) {
1311       XNextEvent(mainDisplay, &ev);
1312 
1313       if (ev.type == Expose || ev.type == VisibilityNotify) {
1314          ExposeEventHandler(&ev, TRUE);
1315       } else if (ev.type == ButtonRelease) {
1316          XUngrabPointer(mainDisplay, CurrentTime);
1317          done = TRUE;
1318       } else if (ev.type == MotionNotify) {
1319          int dx=ev.xmotion.x-orig_x, dy=ev.xmotion.y-orig_y;
1320          int change=((abs(dx)>abs(dy)) ? (int)(dx/res) : (int)(dy/res));
1321 
1322          if (change != saved_change) {
1323             zoom = initial_zoom+change;
1324             if (zoom < 0) zoom = 0;
1325             if (zoom > max_zoom) zoom = max_zoom;
1326             zoomedIn = (zoom < MAX_ZOOMED_IN);
1327             zoomScale = (zoomedIn) ? (MAX_ZOOMED_IN-zoom) :
1328                   (zoom-MAX_ZOOMED_IN);
1329             ShowZoom();
1330             saved_change = change;
1331          }
1332          while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1333       }
1334    }
1335    if (saved_zoomed_in==zoomedIn && saved_zoom_scale==zoomScale) return;
1336    new_zoomed_in = zoomedIn;
1337    new_zoom_scale = zoomScale;
1338    zoomedIn = saved_zoomed_in;
1339    zoomScale = saved_zoom_scale;
1340    PreciseZoom(new_zoomed_in, new_zoom_scale, FALSE);
1341 }
1342 
FormatFloat(pfval,buf)1343 void FormatFloat(pfval, buf)
1344    float *pfval;
1345    char *buf;
1346 {
1347    char int_buf[80], frac_buf[4];
1348    float fval=((*pfval)*1000.0);
1349    int ival=round(fval), len;
1350 
1351    *buf = '\0';
1352    if (ival == 0) {
1353       strcpy(buf, "0");
1354       return;
1355    }
1356    sprintf(int_buf, "%04d", ival);
1357    len = strlen(int_buf);
1358    if (strcmp(&int_buf[len-3], "000") == 0) {
1359       *frac_buf = '\0';
1360    } else if (strcmp(&int_buf[len-2], "00") == 0) {
1361       int_buf[len-2] = '\0';
1362       strcpy(frac_buf, &int_buf[len-3]);
1363    } else if (strcmp(&int_buf[len-1], "0") == 0) {
1364       int_buf[len-1] = '\0';
1365       strcpy(frac_buf, &int_buf[len-3]);
1366    } else {
1367       strcpy(frac_buf, &int_buf[len-3]);
1368    }
1369    int_buf[len-3] = '\0';
1370    if (*frac_buf == '\0') {
1371       strcpy(buf, int_buf);
1372    } else {
1373       sprintf(buf, "%s.%s", int_buf, frac_buf);
1374    }
1375 }
1376 
FormatAngle(angle,buf)1377 void FormatAngle(angle, buf)
1378    int angle; /* degrees*64 */
1379    char *buf;
1380 {
1381    float fval=(((float)angle)/64.0);
1382 
1383    FormatFloat(&fval, buf);
1384 }
1385 
1386 static
ShowRotateMouseStatus()1387 void ShowRotateMouseStatus()
1388 {
1389    char left_buf[MAXSTRING], right_buf[MAXSTRING], tmp_buf[MAXSTRING];
1390 
1391    if (rotationIncrement == 0) {
1392       SetMouseStatus(TgLoadCachedString(CSTID_PARANED_NONE),
1393             TgLoadCachedString(CSTID_PARANED_NONE),
1394             TgLoadCachedString(CSTID_PARANED_NONE));
1395       return;
1396    }
1397    FormatAngle(rotationIncrement, tmp_buf);
1398    sprintf(left_buf, TgLoadCachedString(CSTID_ROTATE_DEGREES_CW), tmp_buf);
1399    sprintf(right_buf, TgLoadCachedString(CSTID_ROTATE_DEGREES_CCW), tmp_buf);
1400    SetMouseStatus(left_buf, TgLoadCachedString(CSTID_PARANED_NONE), right_buf);
1401 }
1402 
1403 static
ValidChoice(choice)1404 int ValidChoice(choice)
1405    int choice;
1406 {
1407    switch (choice) {
1408    case CHOICE_COLOR:
1409    case CHOICE_HORI_ALIGN:
1410    case CHOICE_VERT_ALIGN:
1411    case CHOICE_PAGE:
1412    case CHOICE_PAGELAYOUT:
1413    case CHOICE_JUST:
1414    case CHOICE_FONT:
1415    case CHOICE_VSPACE:
1416    case CHOICE_TEXT_SIZE:
1417    case CHOICE_ROTATE:
1418    case CHOICE_LINE_WIDTH:
1419    case CHOICE_LINE_STYLE:
1420    case CHOICE_LINE_TYPE:
1421    case CHOICE_DASH:
1422    case CHOICE_RADIUS:
1423    case CHOICE_ZOOM:
1424    case CHOICE_MOVE_MODE:
1425    case CHOICE_SHAPE:
1426    case CHOICE_STRETCHTEXT:
1427    case CHOICE_TRANSPAT:
1428    case CHOICE_PRINT:
1429    case CHOICE_FILE:
1430    case CHOICE_FILL:
1431    case CHOICE_PEN:
1432       return TRUE;
1433    }
1434    return FALSE;
1435 }
1436 
ChoiceEventHandler(input)1437 int ChoiceEventHandler(input)
1438    XEvent *input;
1439 {
1440    XEvent ev;
1441    int xindex, yindex, x=0, y=0, choice;
1442 
1443    if (input->type == Expose) {
1444       XSync(mainDisplay, False);
1445       while (XCheckWindowEvent(mainDisplay, choiceWindow, ExposureMask, &ev)) ;
1446       RedrawChoiceWindow();
1447    } else if (input->type == EnterNotify || input->type == LeaveNotify) {
1448       SetMouseStatus("", "", "");
1449       if (curRaisedChoice != INVALID) {
1450          HighLightThreeDButton(curRaisedChoice, FALSE);
1451          curRaisedChoice = INVALID;
1452       }
1453    } else if (input->type == MotionNotify) {
1454       int nIndex=0;
1455       char szLeft[MAXSTRING], szRight[MAXSTRING];
1456 
1457       if (threeDLook) {
1458          xindex = (int)((input->xmotion.x-1) / (choiceImageW+windowPadding));
1459          yindex = (int)((input->xmotion.y-1) / (choiceImageH+windowPadding));
1460          choice = (xindex<<CHOICE_SHIFT)|yindex;
1461          if (choice != curRaisedChoice) {
1462             if (curRaisedChoice != INVALID) {
1463                HighLightThreeDButton(curRaisedChoice, FALSE);
1464                curRaisedChoice = INVALID;
1465             }
1466             if (ValidChoice(choice)) {
1467                HighLightThreeDButton(choice, TRUE);
1468                curRaisedChoice = choice;
1469             }
1470          }
1471       } else {
1472          xindex = (int)(input->xmotion.x / choiceImageW);
1473          yindex = (int)(input->xmotion.y / choiceImageH);
1474          choice = (xindex<<CHOICE_SHIFT)|yindex;
1475       }
1476       switch (choice) {
1477       case CHOICE_COLOR: QuickSetMouseStatus(colorMouseStatus, 0); break;
1478       case CHOICE_HORI_ALIGN: QuickSetMouseStatus(hAlignMouseStatus, 0); break;
1479       case CHOICE_VERT_ALIGN: QuickSetMouseStatus(vAlignMouseStatus, 0); break;
1480       case CHOICE_PAGE:
1481          QuickSetMouseStatus(pageMouseStatus, pageLayoutMode);
1482          break;
1483       case CHOICE_PAGELAYOUT:
1484          QuickSetMouseStatus(pageLayoutMouseStatus, pageLayoutMode);
1485          break;
1486       case CHOICE_JUST: QuickSetMouseStatus(justMouseStatus, textJust); break;
1487       case CHOICE_FONT: QuickSetMouseStatus(fontMouseStatus, 0); break;
1488       case CHOICE_VSPACE: QuickSetMouseStatus(vspaceMouseStatus, 0); break;
1489       case CHOICE_TEXT_SIZE: QuickSetMouseStatus(textSizeMouseStatus, 0); break;
1490       case CHOICE_ROTATE: ShowRotateMouseStatus(); break;
1491       case CHOICE_LINE_WIDTH:
1492          QuickSetMouseStatus(lineWidthMouseStatus, 0);
1493          break;
1494       case CHOICE_LINE_STYLE:
1495          QuickSetMouseStatus(lineStyleMouseStatus, 0);
1496          break;
1497       case CHOICE_LINE_TYPE: QuickSetMouseStatus(lineTypeMouseStatus, 0); break;
1498       case CHOICE_DASH: QuickSetMouseStatus(lineDashMouseStatus, 0); break;
1499       case CHOICE_RADIUS: QuickSetMouseStatus(rcbRadiusMouseStatus, 0); break;
1500       case CHOICE_ZOOM: QuickSetMouseStatus(zoomMouseStatus, 0); break;
1501       case CHOICE_MOVE_MODE:
1502          QuickSetMouseStatus(moveModeMouseStatus, moveMode);
1503          break;
1504       case CHOICE_SHAPE: QuickSetMouseStatus(shapeMouseStatus, 0); break;
1505       case CHOICE_STRETCHTEXT:
1506          QuickSetMouseStatus(stretchableTextModeMouseStatus, stretchableText);
1507          break;
1508       case CHOICE_TRANSPAT:
1509          QuickSetMouseStatus(transPatMouseStatus, transPat);
1510          break;
1511       case CHOICE_PRINT:
1512          nIndex = GetExportIndex(whereToPrint, EXPORT_NEXT);
1513          if (nIndex == PRINTER) {
1514             sprintf(szLeft, TgLoadCachedString(CSTID_PRINT_MODE),
1515                   GetExportName(whereToPrint, EXPORT_NEXT));
1516          } else {
1517             sprintf(szLeft, TgLoadCachedString(CSTID_EXPORT_MODE),
1518                   GetExportName(whereToPrint, EXPORT_NEXT));
1519          }
1520          nIndex = GetExportIndex(whereToPrint, EXPORT_PREV);
1521          if (nIndex == PRINTER) {
1522             sprintf(szRight, TgLoadCachedString(CSTID_PRINT_MODE),
1523                   GetExportName(whereToPrint, EXPORT_PREV));
1524          } else {
1525             sprintf(szRight, TgLoadCachedString(CSTID_EXPORT_MODE),
1526                   GetExportName(whereToPrint, EXPORT_PREV));
1527          }
1528          SetMouseStatus(szLeft, TgLoadCachedString(CSTID_PRINT_EXPORT_MENU),
1529                szRight);
1530          break;
1531       case CHOICE_FILE: QuickSetMouseStatus(fileMouseStatus, pageStyle); break;
1532       case CHOICE_FILL: QuickSetMouseStatus(fillMouseStatus, 0); break;
1533       case CHOICE_PEN: QuickSetMouseStatus(penMouseStatus, 0); break;
1534       }
1535    } else if (input->type == ButtonPress) {
1536       XButtonEvent *button_ev=(&(input->xbutton));
1537       int delta=0, root_x, root_y;
1538       Window root_win, child_win;
1539       unsigned int status;
1540 
1541       Msg("");
1542       switch (button_ev->button) {
1543       case Button1: delta = 1; break;
1544       case Button2:
1545          XQueryPointer(mainDisplay, rootWindow, &root_win, &child_win,
1546                &root_x, &root_y, &x, &y, &status);
1547          break;
1548       case Button3: delta = -1; break;
1549       default: return INVALID;
1550       }
1551       if (threeDLook) {
1552          xindex = (int)((input->xmotion.x-1) / (choiceImageW+windowPadding));
1553          yindex = (int)((input->xmotion.y-1) / (choiceImageH+windowPadding));
1554          choice = (xindex<<CHOICE_SHIFT)|yindex;
1555          if (choice != curRaisedChoice) {
1556             if (curRaisedChoice != INVALID) {
1557                HighLightThreeDButton(curRaisedChoice, FALSE);
1558                curRaisedChoice = INVALID;
1559             }
1560             if (ValidChoice(choice)) {
1561                HighLightThreeDButton(choice, TRUE);
1562                curRaisedChoice = choice;
1563             }
1564          }
1565       } else {
1566          xindex = (int)(input->xmotion.x / choiceImageW);
1567          yindex = (int)(input->xmotion.y / choiceImageH);
1568          choice = (xindex<<CHOICE_SHIFT)|yindex;
1569       }
1570       if (delta != 0) {
1571          cycleThroughChoice = TRUE;
1572       }
1573       switch (choice) {
1574       case CHOICE_COLOR:
1575          if (colorDisplay) {
1576             if (delta == 0) {
1577                ColorMenu(x, y, FALSE);
1578             } else {
1579                if (curChoice != NOTHING &&
1580                      !(curChoice == DRAWTEXT && textCursorShown)) {
1581                   SetCurChoice(NOTHING);
1582                }
1583                colorIndex = (colorIndex+maxColors+delta) % maxColors;
1584                if (colorLayers && !colorLayerOn[colorIndex]) {
1585                   sprintf(gszMsgBox,
1586                         TgLoadString(STID_COLOR_IS_CURRENTLY_INVISIBLE),
1587                         colorIndex, colorMenuItems[colorIndex]);
1588                   Msg(gszMsgBox);
1589                }
1590                ShowColor(TRUE);
1591                UpdatePinnedMenu(MENU_COLOR);
1592                if (topSel != NULL) {
1593                   ChangeAllSelColor(colorIndex, TRUE);
1594                } else if (curChoice == DRAWTEXT && textCursorShown) {
1595                   ChangeAllSelColor(colorIndex, FALSE);
1596                } else {
1597                   sprintf(gszMsgBox, TgLoadString(STID_COLOR_SET_TO),
1598                         colorMenuItems[colorIndex]);
1599                   Msg(gszMsgBox);
1600                }
1601                QuickSetMouseStatus(colorMouseStatus, 0);
1602             }
1603          }
1604          break;
1605       case CHOICE_HORI_ALIGN:
1606          if (delta == 0) {
1607             HoriAlignMenu(x, y, FALSE);
1608          } else {
1609             HoriAlignSubMenu((horiAlign+MAXALIGNS+delta) % MAXALIGNS);
1610             QuickSetMouseStatus(hAlignMouseStatus, 0);
1611          }
1612          break;
1613       case CHOICE_VERT_ALIGN:
1614          if (delta == 0) {
1615             VertAlignMenu(x, y, FALSE);
1616          } else {
1617             VertAlignSubMenu((vertAlign+MAXALIGNS+delta) % MAXALIGNS);
1618             QuickSetMouseStatus(vAlignMouseStatus, 0);
1619          }
1620          break;
1621       case CHOICE_PAGE:
1622          if (delta == 0) {
1623             PageMenu(x, y, FALSE);
1624          } else if (pageLayoutMode == PAGE_STACK) {
1625             if (delta == 1) {
1626                NextPage();
1627             } else {
1628                PrevPage();
1629             }
1630             QuickSetMouseStatus(pageMouseStatus, pageLayoutMode);
1631          } else {
1632             SpecifyDrawingSize();
1633             QuickSetMouseStatus(pageMouseStatus, pageLayoutMode);
1634          }
1635          break;
1636       case CHOICE_PAGELAYOUT:
1637          if (delta == 0) {
1638             PageLayoutMenu(x, y, FALSE);
1639          } else {
1640             PageLayoutSubMenu(!pageLayoutMode);
1641             QuickSetMouseStatus(pageLayoutMouseStatus, pageLayoutMode);
1642          }
1643          break;
1644       case CHOICE_JUST:
1645          if (delta == 0) {
1646             StyleMenu(x, y, FALSE);
1647          } else {
1648             if (curChoice == DRAWTEXT && !textCursorShown) {
1649                if (TieLooseEnds()) {
1650                   SetCurChoice(NOTHING);
1651                   HighLightReverse();
1652                } else {
1653                   SetCurChoice(NOTHING);
1654                }
1655                RemoveAllSel();
1656             }
1657             textJust = (textJust+MAXJUSTS+delta) % MAXJUSTS;
1658             ShowJust();
1659             UpdatePinnedMenu(MENU_STYLE);
1660             if (topSel != NULL) {
1661                ChangeFontJust(textJust);
1662             } else if (curChoice == DRAWTEXT && textCursorShown) {
1663                ChangeFontJust(textJust);
1664             }
1665             QuickSetMouseStatus(justMouseStatus, textJust);
1666          }
1667          break;
1668       case CHOICE_FONT:
1669          if (delta == 0) {
1670             FontMenu(x, y, FALSE);
1671          } else {
1672             if (curChoice == DRAWTEXT && !textCursorShown) {
1673                if (TieLooseEnds()) {
1674                   SetCurChoice(NOTHING);
1675                   HighLightReverse();
1676                } else {
1677                   SetCurChoice(NOTHING);
1678                }
1679                RemoveAllSel();
1680             }
1681             ChangeFont((curFont+numFonts+delta)%numFonts, TRUE);
1682             QuickSetMouseStatus(fontMouseStatus, 0);
1683          }
1684          break;
1685       case CHOICE_VSPACE:
1686          if (delta == 0) {
1687             TextVSpaceLoop(button_ev);
1688          } else {
1689             if (curChoice == DRAWTEXT && !textCursorShown) {
1690                if (TieLooseEnds()) {
1691                   SetCurChoice(NOTHING);
1692                   HighLightReverse();
1693                } else {
1694                   SetCurChoice(NOTHING);
1695                }
1696                RemoveAllSel();
1697             }
1698             if (topSel == NULL && delta < 0 &&
1699                   textCursorH+textVSpace+delta <= 0) {
1700                Msg(TgLoadString(STID_VSPACE_TOO_SMALL_NOT_CHANGED));
1701             } else {
1702                textVSpace += delta;
1703                ShowTextVSpace();
1704                if (topSel != NULL) {
1705                   ChangeVSpace(textVSpace);
1706                } else if (curChoice == DRAWTEXT && textCursorShown) {
1707                   ChangeVSpace(textVSpace);
1708                }
1709             }
1710             QuickSetMouseStatus(vspaceMouseStatus, 0);
1711          }
1712          break;
1713       case CHOICE_TEXT_SIZE:
1714          if (delta == 0) {
1715             SizeMenu(x, y, FALSE);
1716          } else {
1717             int cur_index=INVALID, saved_index=INVALID;
1718 
1719             if (curChoice == DRAWTEXT && !textCursorShown) {
1720                if (TieLooseEnds()) {
1721                   SetCurChoice(NOTHING);
1722                   HighLightReverse();
1723                } else {
1724                   SetCurChoice(NOTHING);
1725                }
1726                RemoveAllSel();
1727             }
1728             cur_index = saved_index = GetSizeMenuIndex();
1729             if (cur_index == INVALID) {
1730                cur_index = 0;
1731             } else {
1732                cur_index = (cur_index+numFontSizes+delta) % numFontSizes;
1733             }
1734             if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
1735                if (RestoreEditTextSize(curTextObj, TRUE)) {
1736                   UpdTextBBox(curTextObj);
1737                }
1738             }
1739             curSzUnit = fontSzUnits[cur_index];
1740             allowFontFaceSubstitution = FALSE;
1741             SetCanvasFont();
1742             allowFontFaceSubstitution = TRUE;
1743             if (canvasFontSize == INVALID) {
1744                sprintf(gszMsgBox,
1745                      TgLoadString(STID_FONT_AND_SIZE_NOT_AVAILABLE),
1746                      fontMenuStr[curFont], SzUnitToFontSize(curSzUnit));
1747                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1748                cur_index = saved_index;
1749                curSzUnit = fontSzUnits[cur_index];
1750                SetCanvasFont();
1751             }
1752             PutCurSzUnit(curSzUnit);
1753             if (curChoice == DRAWTEXT && textCursorShown && editTextSize != 0) {
1754                if (RestoreEditTextSize(curTextObj, FALSE)) {
1755                   UpdTextBBox(curTextObj);
1756                }
1757             }
1758             ShowCurFont();
1759             ShowTextSize();
1760 
1761             UpdatePinnedMenu(MENU_SIZE);
1762             if (topSel != NULL) {
1763                ChangeFontSize(cur_index);
1764             } else if (curChoice == DRAWTEXT && textCursorShown) {
1765                ChangeFontSize(cur_index);
1766             }
1767             QuickSetMouseStatus(textSizeMouseStatus, 0);
1768          }
1769          break;
1770       case CHOICE_ROTATE:
1771          if (delta != 0) {
1772             if (curChoice == DRAWTEXT) {
1773                if (TieLooseEnds()) {
1774                   SetCurChoice(NOTHING);
1775                   HighLightReverse();
1776                } else {
1777                   SetCurChoice(NOTHING);
1778                }
1779                RemoveAllSel();
1780             }
1781             textRotation += delta*rotationIncrement;
1782             while (textRotation < 0) textRotation += (360<<6);
1783             while (textRotation >= (360<<6)) textRotation -= (360<<6);
1784             ShowRotate();
1785             if (topSel != NULL) {
1786                if (delta == 1) {
1787                   RotateClockWise();
1788                } else {
1789                   RotateCounter();
1790                }
1791             }
1792          }
1793          ShowRotateMouseStatus();
1794          break;
1795       case CHOICE_LINE_WIDTH:
1796          if (delta == 0) {
1797             LineWidthMenu(x, y, FALSE);
1798          } else {
1799             lineWidth = (lineWidth+maxLineWidths+delta) % maxLineWidths;
1800             ShowLineWidth();
1801             UpdatePinnedMenu(MENU_LINEWIDTH);
1802             if (topSel != NULL) {
1803                ChangeAllSelLineWidth(lineWidth, TRUE);
1804             } else {
1805                sprintf(gszMsgBox, TgLoadString(STID_LINE_WIDTH_SET_TO),
1806                      curWidthOfLineSpec[lineWidth]);
1807                Msg(gszMsgBox);
1808             }
1809             QuickSetMouseStatus(lineWidthMouseStatus, 0);
1810          }
1811          break;
1812       case CHOICE_LINE_STYLE:
1813          if (delta == 0) {
1814             LineStyleMenu(x, y, FALSE);
1815          } else {
1816             lineStyle = (lineStyle+MAXLINESTYLES+delta) % MAXLINESTYLES;
1817             ShowLineStyle();
1818             UpdatePinnedMenu(MENU_LINESTYLE);
1819             if (topSel != NULL) ChangeAllSelLineStyle(lineStyle, TRUE);
1820             QuickSetMouseStatus(lineStyleMouseStatus, 0);
1821          }
1822          break;
1823       case CHOICE_LINE_TYPE:
1824          if (delta == 0) {
1825             LineTypeMenu(x, y, FALSE);
1826          } else {
1827             curSpline = (curSpline+MAXLINETYPES+delta) % MAXLINETYPES;
1828             ShowLineType();
1829             UpdatePinnedMenu(MENU_LINETYPE);
1830             if (topSel != NULL) {
1831                ChangeAllSelLineType(curSpline, TRUE);
1832             } else {
1833                *gszMsgBox = '\0';
1834                switch (curSpline) {
1835                case LT_STRAIGHT:
1836                   Msg(TgLoadString(STID_LINE_TYPE_IS_STRAIGHT));
1837                   break;
1838                case LT_SPLINE:
1839                   Msg(TgLoadString(STID_LINE_TYPE_IS_SPLINE));
1840                   break;
1841                case LT_INTSPLINE:
1842                   Msg(TgLoadString(STID_LINE_TYPE_IS_INTSPLINE));
1843                   break;
1844                case LT_STRUCT_SPLINE:
1845                   Msg(TgLoadString(STID_LINE_TYPE_IS_STRUCT_SPLINE));
1846                   break;
1847                }
1848             }
1849             QuickSetMouseStatus(lineTypeMouseStatus, 0);
1850          }
1851          break;
1852       case CHOICE_DASH:
1853          if (delta == 0) {
1854             LineDashMenu(x, y, FALSE);
1855          } else {
1856             curDash = (curDash+MAXDASHES+delta) % MAXDASHES;
1857             ShowDash();
1858             UpdatePinnedMenu(MENU_LINEDASH);
1859             if (topSel != NULL) ChangeAllSelLineDash(curDash, TRUE);
1860             QuickSetMouseStatus(lineDashMouseStatus, 0);
1861          }
1862          break;
1863       case CHOICE_RADIUS:
1864          if (delta == 0) {
1865             RCBRadiusLoop(button_ev);
1866          } else {
1867             if (rcbRadius+delta >= MIN_RCB_RADIUS) {
1868                rcbRadius += delta;
1869                ShowRCBRadius();
1870                if (topSel != NULL) ChangeAllSelRCBRadius(rcbRadius);
1871             }
1872             QuickSetMouseStatus(rcbRadiusMouseStatus, 0);
1873          }
1874          break;
1875       case CHOICE_ZOOM:
1876          switch (delta) {
1877          case -1: ZoomOut(); QuickSetMouseStatus(zoomMouseStatus, 0); break;
1878          case 0: ZoomLoop(button_ev); break;
1879          case 1: ZoomIn(); break;
1880          }
1881          break;
1882       case CHOICE_MOVE_MODE:
1883          if (delta == 0) {
1884             MoveModeMenu(x, y, FALSE);
1885          } else {
1886             ToggleMoveMode();
1887             QuickSetMouseStatus(moveModeMouseStatus, moveMode);
1888          }
1889          break;
1890       case CHOICE_SHAPE:
1891          if (delta == 0) ShapeMenu(x, y, FALSE);
1892          break;
1893       case CHOICE_STRETCHTEXT:
1894          if (delta == 0) {
1895             StretchableTextModeMenu(x, y, FALSE);
1896          } else {
1897             ToggleStretchableText();
1898             QuickSetMouseStatus(stretchableTextModeMouseStatus,
1899                   stretchableText);
1900          }
1901          break;
1902       case CHOICE_TRANSPAT:
1903          if (delta == 0) {
1904             TransPatModeMenu(x, y, FALSE);
1905          } else {
1906             transPat = !transPat;
1907             ShowTransPatMode();
1908             UpdatePinnedMenu(MENU_TRANSPAT);
1909             if (topSel != NULL) ChangeAllSelTransPat(transPat, TRUE);
1910             QuickSetMouseStatus(transPatMouseStatus, transPat);
1911          }
1912          break;
1913       case CHOICE_PRINT:
1914          if (delta == 0) {
1915             ExportFormatMenu(x, y, FALSE);
1916          } else {
1917             whereToPrint = (whereToPrint+maxWhereToPrint+delta) %
1918                   maxWhereToPrint-1;
1919             ToggleWhereToPrint();
1920          }
1921          break;
1922       case CHOICE_FILE:
1923          if (delta == 0) {
1924             PageStyleMenu(x, y, FALSE);
1925          } else {
1926             switch (pageStyle) {
1927             case PORTRAIT: ChangePageStyle(LANDSCAPE); break;
1928             case LANDSCAPE: ChangePageStyle(PORTRAIT); break;
1929             }
1930             QuickSetMouseStatus(fileMouseStatus, pageStyle);
1931          }
1932          break;
1933       case CHOICE_FILL:
1934          if (delta == 0) {
1935             FillMenu(x, y, FALSE);
1936          } else {
1937             if (curChoice == DRAWTEXT && !textCursorShown) {
1938                if (TieLooseEnds()) {
1939                   SetCurChoice(NOTHING);
1940                   HighLightReverse();
1941                } else {
1942                   SetCurChoice(NOTHING);
1943                }
1944                RemoveAllSel();
1945             }
1946             objFill = (objFill+MAXPATTERNS+delta) % MAXPATTERNS;
1947             ShowFill();
1948             UpdatePinnedMenu(MENU_FILL);
1949             if (topSel != NULL) {
1950                ChangeAllSelFill(objFill, TRUE);
1951             } else if (curChoice == DRAWTEXT && textCursorShown) {
1952                ChangeAllSelFill(objFill, FALSE);
1953             }
1954             QuickSetMouseStatus(fillMouseStatus, 0);
1955          }
1956          break;
1957       case CHOICE_PEN:
1958          if (delta == 0) {
1959             PenMenu(x, y, FALSE);
1960          } else {
1961             if (curChoice == DRAWTEXT && !textCursorShown) {
1962                if (TieLooseEnds()) {
1963                   SetCurChoice(NOTHING);
1964                   HighLightReverse();
1965                } else {
1966                   SetCurChoice(NOTHING);
1967                }
1968                RemoveAllSel();
1969             }
1970             penPat = (penPat+MAXPATTERNS+delta) % MAXPATTERNS;
1971             ShowPen();
1972             UpdatePinnedMenu(MENU_PEN);
1973             if (topSel != NULL) {
1974                ChangeAllSelPen(penPat, TRUE);
1975             } else if (curChoice == DRAWTEXT && textCursorShown) {
1976                ChangeAllSelPen(penPat, FALSE);
1977             }
1978             QuickSetMouseStatus(penMouseStatus, 0);
1979          }
1980          break;
1981       }
1982       cycleThroughChoice = FALSE;
1983    }
1984    return INVALID;
1985 }
1986 
1987 static
HighLightModeThreeDButton(mode,highlight)1988 void HighLightModeThreeDButton(mode, highlight)
1989    int mode, highlight;
1990 {
1991    struct BBRec bbox;
1992 
1993    if (!threeDLook) return;
1994 
1995    bbox.ltx = (windowPadding>>1);
1996    bbox.lty = (windowPadding>>1)+mode*(choiceImageH+(windowPadding<<1));
1997    bbox.rbx = bbox.ltx+choiceImageW+(windowPadding<<1);
1998    bbox.rby = bbox.lty+choiceImageH+(windowPadding<<1);
1999    if (highlight) {
2000       TgDrawThreeDButton(mainDisplay, modeWindow, textMenuGC, &bbox,
2001             TGBS_RAISED, 2, FALSE);
2002    } else if (mode == curChoice) {
2003       TgDrawThreeDButton(mainDisplay, modeWindow, textMenuGC, &bbox,
2004             TGBS_LOWRED, 2, FALSE);
2005    } else {
2006       TgClearThreeDButton(mainDisplay, modeWindow, textMenuGC, &bbox, 2);
2007    }
2008 }
2009 
RedrawModeWindow()2010 void RedrawModeWindow()
2011 {
2012    int i, x=(windowPadding>>1), y=(windowPadding>>1);
2013    XGCValues values;
2014 
2015    XClearWindow(mainDisplay, modeWindow);
2016 
2017    for (i=0; i < MAXCHOICES; i++) {
2018       Pixmap bitmap=((i==DRAWPOLY && connectingPortsByWire) ? wireBitmap :
2019             choicePixmap[i]);
2020 
2021       if (threeDLook) {
2022          values.stipple = bitmap;
2023          values.ts_x_origin = x+windowPadding;
2024          values.ts_y_origin = y+windowPadding;
2025          XChangeGC(mainDisplay, rasterGC,
2026                GCStipple | GCTileStipXOrigin | GCTileStipYOrigin, &values);
2027          XFillRectangle(mainDisplay, modeWindow, rasterGC, values.ts_x_origin,
2028                values.ts_y_origin, choiceImageW, choiceImageH);
2029          XSetTSOrigin(mainDisplay, rasterGC, 0, 0);
2030          if (i == curChoice) {
2031             struct BBRec bbox;
2032 
2033             SetBBRec(&bbox, x, y, x+choiceImageW+(windowPadding<<1),
2034                   y+choiceImageH+(windowPadding<<1));
2035             TgDrawThreeDButton(mainDisplay, modeWindow, textMenuGC, &bbox,
2036                   TGBS_LOWRED, 2, FALSE);
2037          }
2038       } else {
2039          if (i == curChoice) {
2040             XSetForeground(mainDisplay, textMenuGC, myFgPixel);
2041             XFillRectangle(mainDisplay, modeWindow, textMenuGC,
2042                   x+windowPadding, y+windowPadding, choiceImageW, choiceImageH);
2043             XSetStipple(mainDisplay, rvPixmapMenuGC, bitmap);
2044             XFillRectangle(mainDisplay, modeWindow, rvPixmapMenuGC,
2045                   x+windowPadding, y+windowPadding, choiceImageW, choiceImageH);
2046          } else {
2047             XSetStipple(mainDisplay, rasterGC, bitmap);
2048             XFillRectangle(mainDisplay, modeWindow, rasterGC, x+windowPadding,
2049                   y+windowPadding, choiceImageW, choiceImageH);
2050          }
2051       }
2052       y += choiceImageH+(windowPadding<<1);
2053    }
2054    if (threeDLook) {
2055       struct BBRec bbox;
2056 
2057       SetBBRec(&bbox, 0, 0, modeWindowW, modeWindowH);
2058       TgDrawThreeDButton(mainDisplay, modeWindow, textMenuGC, &bbox,
2059             TGBS_RAISED, 1, FALSE);
2060    }
2061 }
2062 
ModeEventHandler(input)2063 int ModeEventHandler(input)
2064    XEvent *input;
2065 {
2066    XEvent ev;
2067    int mode=INVALID;
2068 
2069    if (noModeWindow) return INVALID;
2070 
2071    if (input->type == Expose) {
2072       XSync(mainDisplay, False);
2073       while (XCheckWindowEvent(mainDisplay, modeWindow, ExposureMask, &ev)) ;
2074       RedrawModeWindow();
2075    } else if (input->type == EnterNotify || input->type == LeaveNotify) {
2076       if (input->type == EnterNotify) {
2077          SetStringStatus("");
2078       } else {
2079          SetMouseStatus("", "", "");
2080       }
2081       if (curRaisedMode != INVALID) {
2082          HighLightModeThreeDButton(curRaisedMode, FALSE);
2083          curRaisedMode = INVALID;
2084       }
2085    } else if (input->type == MotionNotify) {
2086       mode = (int)((input->xmotion.y-(windowPadding>>1)) /
2087             (choiceImageH+(windowPadding<<1)));
2088       if (threeDLook) {
2089          if (mode != curRaisedMode) {
2090             if (curRaisedMode != INVALID) {
2091                HighLightModeThreeDButton(curRaisedMode, FALSE);
2092                curRaisedMode = INVALID;
2093             }
2094             if (mode >= 0 && mode < MAXCHOICES) {
2095                HighLightModeThreeDButton(mode, TRUE);
2096                curRaisedMode = mode;
2097             }
2098          }
2099       }
2100       if (mode >=0 && mode < MAXCHOICES) {
2101          TgMenuItemInfo *menu_iteminfos=modeMenuInfo.items;
2102 
2103          if (mode == ROTATEMODE) {
2104             QuickSetMouseStatus(autoRotatePivotMouseStatus, 0);
2105          } else {
2106             /* the raw status_str is English */
2107             SetStringStatus(_(menu_iteminfos[mode].status_str));
2108          }
2109       } else {
2110          SetStringStatus("");
2111       }
2112    } else if (input->type == ButtonPress) {
2113       XButtonEvent *button_ev=(&(input->xbutton));
2114 
2115       mode = (int)((input->xbutton.y-(windowPadding>>1)) /
2116             (choiceImageH+(windowPadding<<1)));
2117       if (mode >=0 && mode < MAXCHOICES) {
2118          if (button_ev->button == Button2 && mode == ROTATEMODE) {
2119             int x=0, y=0, root_x=0, root_y=0;
2120             Window root_win=None, child_win=None;
2121             unsigned int status=0;
2122 
2123             XQueryPointer(mainDisplay, rootWindow, &root_win, &child_win,
2124                   &root_x, &root_y, &x, &y, &status);
2125             AutoRotatePivotMenu(x, y, FALSE);
2126          } else {
2127             TgMenuItemInfo *menu_iteminfos=modeMenuInfo.items;
2128 
2129             SetCurChoice(mode);
2130             /* the raw status_str is English */
2131             SetStringStatus(_(menu_iteminfos[mode].status_str));
2132          }
2133       } else if (button_ev->button == Button2 && mode >= MAXCHOICES) {
2134          return MainMenu();
2135       }
2136    }
2137    return INVALID;
2138 }
2139