1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design Systems
4  *
5  * File: graphqt.cpp
6  * Qt Window System interface
7  * Written by: Dmitry Nadezhin, Instutute for Design Problems in Microelectronics, Russian Academy of Sciences
8  *
9  * Copyright (c) 2001 Static Free Software.
10  *
11  * Electric(tm) is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * Electric(tm) is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Electric(tm); see the file COPYING.  If not, write to
23  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24  * Boston, Mass 02111-1307, USA.
25  *
26  * Static Free Software
27  * 4119 Alpine Road
28  * Portola Valley, California 94028
29  * info@staticfreesoft.com
30  */
31 
32 #include "global.h"
33 #include "database.h"
34 #include "egraphics.h"
35 #include "eio.h"
36 #include "usr.h"
37 #include "usrtrack.h"
38 #include "edialogs.h"
39 
40 #ifdef MACOSX
41 #  include <Carbon/Carbon.h>
42 #endif
43 
44 #include "graphqt.h"
45 
46 #include <qclipboard.h>
47 #include <qdir.h>
48 #include <qfile.h>
49 #include <qfiledialog.h>
50 #include <qfileinfo.h>
51 #include <qfontdatabase.h>
52 #include <qfontdialog.h>
53 #include <qhbox.h>
54 #include <qlabel.h>
55 #include <qlayout.h>
56 #include <qlineedit.h>
57 #include <qmenubar.h>
58 #include <qtextedit.h>
59 #include <qpaintdevicemetrics.h>
60 #include <qpainter.h>
61 #include <qpixmap.h>
62 #include <qpopupmenu.h>
63 #include <qnamespace.h>
64 #include <qprinter.h>
65 #include <qsettings.h>
66 #include <qsound.h>
67 #include <qstatusbar.h>
68 #include <qtimer.h>
69 #include <qvbox.h>
70 #ifdef USEMDI
71 #  include <qdockwindow.h>
72 #  include <qworkspace.h>
73 #endif
74 
75 #include <signal.h>
76 #include <errno.h>
77 #include <sys/stat.h>
78 #if defined(ONUNIX) || defined(MACOSX)
79 #  include <pwd.h>
80 #endif
81 
82 #ifdef HAVE_SYS_TYPES_H
83 #  include <sys/types.h>
84 #endif
85 
86 #ifdef HAVE_UNISTD_H
87 #  include <unistd.h>
88 #endif
89 
90 #ifdef HAVE_FCNTL_H
91 #  include <fcntl.h>
92 #endif
93 
94 #ifdef HAVE_PTHREAD
95 #  include <pthread.h>
96 #else
97 #  include <thread.h>
98 #  include <synch.h>
99 #endif
100 
101 #ifdef WIN32
102 #  include <io.h>
103 #endif
104 
105 #if LANGTCL
106 #  include "dblang.h"
107   Tcl_Interp *gra_tclinterp;
108   INTBIG gra_initializetcl(void);
109 #endif
110 
111 /****** windows ******/
112 
113 #define WMLEFTBORDER          8					/* size of left border for windows */
114 #define WMTOPBORDER          30					/* size of top border for windows */
115 #define WMTOPBORDERMAC       44					/* size of menu border of Macintosh */
116 #define FLUSHTICKS          120					/* ticks between display flushes */
117 #define EPROCESSWAIT        100                 /* maximal time (in ms) to wait in EProcess.wait() */
118 #define SBARWIDTH            15					/* size of text-edit scroll bars */
119 #define PALETTEWIDTH        110
120 #define MAXLOCALSTRING      256					/* size of "gra_localstring" */
121 
122 #ifdef __cplusplus
123 #  define VisualClass(v) v->c_class
124 #else
125 #  define VisualClass(v) v->class
126 #endif
127 
128 EApplication        *gra = 0;
129 static INTBIG        gra_editposx;
130 static INTBIG        gra_editposy;
131 static INTBIG        gra_editsizex;
132 static INTBIG        gra_editsizey;
133 static UINTBIG       gra_internalchange;
134 static INTSML        gra_windowframeindex = 0;
135 static INTSML        gra_windownumber;			/* number of the window that was created */
136 static WINDOWFRAME  *gra_deletethisframe = 0;	/* window that is to be deleted */
137 static char          gra_localstring[MAXLOCALSTRING];
138 extern GRAPHICS      us_box, us_ebox, us_menutext;
139 static BOOLEAN       gra_noflush = FALSE;		/* TRUE to supress display flushing */
140 
141 static QRgb gra_colortable[256];
142 static INTBIG        gra_windowbeingdeleted = 0;
143 
144 static void       gra_adjustwindowframeon(INTSML how);
145 static BOOLEAN    gra_onthiswindow(QWidget *wnd, RECTAREA *r);
146 static INTSML     gra_buildwindow(QWidget *desktop, WINDOWFRAME *wf, BOOLEAN floating);
147 static void       gra_getsensiblescreensize(INTBIG *screensizex, INTBIG *screensizey);
148 static void       gra_reloadmap(void);
149 static void       gra_removewindowextent(RECTAREA *r, QWidget *wnd);
150 static void       gra_handlequeuedframedeletion(void);
151 static INTSML     gra_graphicshas(INTSML want);
152 static char     **gra_eprinterlist(void);
153 
154 /****** the messages window ******/
155 static INTSML        gra_messages_typingin;		/* nonzero if typing into messages window */
156 
157 /****** the status bar ******/
158 #define MAXSTATUSLINES  1						/* number of status lines */
159 
160 static STATUSFIELD *gra_statusfields[100];
161 static char *gra_statusfieldtext[100];
162 static INTSML gra_indicatorcount = 0;
163 
164 /****** the menus ******/
165 static INTSML      gra_pulldownmenucount_ = 0;	/* number of top-level pulldown menus */
166 static POPUPMENU  *gra_pulldowns_[50];			/* the current top-level pulldown menus */
167 
168 /****** events ******/
169 typedef RETSIGTYPE (*SIGNALCAST)(int);
170 
171 static INTSML        gra_doublethresh;			/* threshold of double-click */
172 static INTBIG        gra_cursorx, gra_cursory;	/* current position of mouse */
173 static QSound       *gra_clicksound;
174 static Qt::ButtonState   gra_lastbuttonstate = Qt::NoButton; /* last button state (for getbuckybits) */
175 
176 #define TIME_SLICE_DELAY        50              /* time ( in ms ) to postpone timeslice */
177 
178 static INTSML gra_stop_dowork = 0;
179 RETSIGTYPE gra_sigill_trap(void);
180 RETSIGTYPE gra_sigfpe_trap(void);
181 RETSIGTYPE gra_sigbus_trap(void);
182 RETSIGTYPE gra_sigsegv_trap(void);
183 static BOOLEAN gra_setcurrentwindowframe(WINDOWFRAME *wf);
184 
185 static INTSML gra_nxtchar;
186 static INTBIG gra_nxtcharspecial;
187 static BOOLEAN gra_nxtcharhandler(INTSML chr, INTBIG special);
188 static BOOLEAN gra_nullbuttonhandler(INTBIG x, INTBIG y, INTBIG but);
189 
190 typedef enum
191 {
192 	S_STARTUP, S_USER, S_TOOL, S_TRACK, S_MODAL, S_CHECKINT
193 } GRAPHSTATE;
194 
195 #ifdef ETRACE
196 static char *stateNames[] =
197 {
198 	"STARTUP", "USER", "TOOL", "TRACK", "MODAL", "CHECKINT"
199 };
200 #endif
201 
202 GRAPHSTATE gra_state;
203 
204 /****** mouse buttons ******/
205 
206 typedef struct
207 {
208 	char  *name;				/* button name */
209 	INTSML unique;				/* number of letters that make it unique */
210 } MOUSEBUTTONS;
211 
212 #ifdef MACOS
213 #  define BUTTONS     17		/* cannot exceed NUMBUTS in "usr.h" */
214 #  define REALBUTS    5			/* actual number of buttons */
215 MOUSEBUTTONS gra_buttonname[BUTTONS] =
216 {						/* Shift Command Option Control */
217 	"Button",      1,   /*                              */
218 	"SButton",     2,	/* Shift                        */
219 	"MButton",     2,	/*       Command                */
220 	"SMButton",    3,	/* Shift Command                */
221 	"OButton",     2,	/*               Option         */
222 	"SOButton",    3,	/* Shift         Option         */
223 	"MOButton",    3,	/*       Command Option         */
224 	"SMOButton",   4,	/* Shift Command Option         */
225 	"CButton",     2,	/*                      Control */
226 	"SCButton",    3,	/* Shift                Control */
227 	"CMButton",    3,	/*       Command        Control */
228 	"SCMButton",   4,	/* Shift Command        Control */
229 	"COButton",    3,	/*               Option Control */
230 	"SCOButton",   4,	/* Shift         Option Control */
231 	"CMOButton",   4,	/*       Command Option Control */
232 	"SCMOButton",  5,	/* Shift Command Option Control */
233 	"DButton",     2
234 };
235 #else
236 #  define BUTTONS     45		/* cannot exceed NUMBUTS in "usr.h" */
237 #  define REALBUTS    5			/* actual number of buttons */
238 MOUSEBUTTONS gra_buttonname[BUTTONS] =
239 {
240 	{"LEFT",1},   {"MIDDLE",2},   {"RIGHT",1},   {"FORWARD",1},   {"BACKWARD",1},	/* unshifted */
241 	{"SLEFT",2},  {"SMIDDLE",3},  {"SRIGHT",2},  {"SFORWARD",2},  {"SBACKWARD",2},	/* shift held down */
242 	{"CLEFT",2},  {"CMIDDLE",3},  {"CRIGHT",2},  {"CFORWARD",2},  {"CBACKWARD",2},	/* control held down */
243 	{"MLEFT",2},  {"MMIDDLE",3},  {"MRIGHT",2},  {"MFORWARD",2},  {"MBACKWARD",2},	/* meta held down */
244 	{"SCLEFT",3}, {"SCMIDDLE",4}, {"SCRIGHT",3}, {"SCFORWARD",3}, {"SCBACKWARD",3},	/* shift and control held down*/
245 	{"SMLEFT",3}, {"SMMIDDLE",4}, {"SMRIGHT",3}, {"SMFORWARD",3}, {"SMBACKWARD",3},	/* shift and meta held down */
246 	{"CMLEFT",3}, {"CMMIDDLE",4}, {"CMRIGHT",3}, {"CMFORWARD",3}, {"CMBACKWARD",3},	/* control and meta held down */
247 	{"SCMLEFT",4},{"SCMMIDDLE",4},{"SCMRIGHT",4},{"SCMFORWARD",4},{"SCMBACKWARD",4},/* shift, control, and meta */
248 	{"DLEFT",2},  {"DMIDDLE",2},  {"DRIGHT",2},  {"DFORWARD",2},  {"DBACKWARD",2}	/* double-click */
249 };
250 #endif
251 
252 /* SWAPPED means that the bytes are MSB first */
253 #if defined(sparc) || defined(__APPLE__)
254 #  define SWAPPED 1
255 #endif
256 
257 /* the icon for Electric  */
258 #ifdef sun
259 #  define PROGICONSIZE 32
260   static UINTSML gra_icon[64] =
261   {
262 	0x0000, 0x0000, /*                                  */
263 	0x0000, 0x0000, /*                                  */
264 	0xFF80, 0x01FF, /*        XXXXXXXXXXXXXXXXXX        */
265 	0x0040, 0x0200, /*       X                  X       */
266 	0x0020, 0x0400, /*      X                    X      */
267 	0x0010, 0x0800, /*     X                      X     */
268 	0x0008, 0x1000, /*    X                        X    */
269 	0x0008, 0x1000, /*    X                        X    */
270 	0x0004, 0x2000, /*   X                          X   */
271 	0x0784, 0x21E0, /*   X    XXXX          XXXX    X   */
272 	0x0782, 0x41E0, /*  X     XXXX          XXXX     X  */
273 	0x0782, 0x41E0, /*  X     XXXX          XXXX     X  */
274 	0x0781, 0x81E0, /* X      XXXX          XXXX      X */
275 	0x0781, 0x81E0, /* X      XXXX          XXXX      X */
276 	0x0781, 0x81E0, /* X      XXXX          XXXX      X */
277 	0x0781, 0x81E0, /* X      XXXX          XXXX      X */
278 	0x0781, 0x81E0, /* X      XXXX          XXXX      X */
279 	0x0781, 0x81E0, /* X      XXXX          XXXX      X */
280 	0x0781, 0x8000, /* X      XXXX                    X */
281 	0x0001, 0x8000, /* X                              X */
282 	0x8002, 0x4001, /*  X             XX             X  */
283 	0xC002, 0x4003, /*  X            XXXX            X  */
284 	0xE004, 0x2007, /*   X          XXXXXX          X   */
285 	0xE004, 0x2007, /*   X          XXXXXX          X   */
286 	0xE008, 0x1007, /*    X         XXXXXX         X    */
287 	0xE008, 0x1007, /*    X         XXXXXX         X    */
288 	0x0010, 0x0800, /*     X                      X     */
289 	0x0020, 0x0400, /*      X                    X      */
290 	0x0040, 0x0200, /*       X                  X       */
291 	0xFF80, 0x01FF, /*        XXXXXXXXXXXXXXXXXX        */
292 	0x0000, 0x0000, /*                                  */
293 	0x0000, 0x0000  /*                                  */
294   };
295 #else
296 #  define PROGICONSIZE 64
297   static UINTSML gra_icon[256] =
298   {
299 	0x0000, 0x0000, 0x0000, 0x0000, /*                                                                  */
300 	0x0000, 0x0000, 0x0000, 0x0000, /*                                                                  */
301 	0x0000, 0x0000, 0x0000, 0x0000, /*                                                                  */
302 	0x0000, 0x0000, 0x0000, 0x0000, /*                                                                  */
303 	0xF800, 0xFFFF, 0xFFFF, 0x001F, /*            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX            */
304 	0x0400, 0x0000, 0x0000, 0x0020, /*           X                                          X           */
305 	0x0200, 0x0000, 0x0000, 0x0040, /*          X                                            X          */
306 	0x0100, 0x0000, 0x0000, 0x0080, /*         X                                              X         */
307 	0x0080, 0x0000, 0x0000, 0x0100, /*        X                                                X        */
308 	0x0080, 0x0000, 0x0000, 0x0100, /*        X                                                X        */
309 	0x0040, 0x0000, 0x0000, 0x0200, /*       X                                                  X       */
310 	0x0040, 0x0000, 0x0000, 0x0200, /*       X                                                  X       */
311 	0x0020, 0x0000, 0x0000, 0x0400, /*      X                                                    X      */
312 	0x0020, 0x0000, 0x0000, 0x0400, /*      X                                                    X      */
313 	0x8010, 0x001F, 0xFC00, 0x0800, /*     X          XXXXXX                     XXXXXX           X     */
314 	0x8010, 0x001F, 0xFC00, 0x0800, /*     X          XXXXXX                     XXXXXX           X     */
315 	0x8008, 0x001F, 0xFC00, 0x1000, /*    X           XXXXXX                     XXXXXX            X    */
316 	0x8008, 0x001F, 0xFC00, 0x1000, /*    X           XXXXXX                     XXXXXX            X    */
317 	0x8004, 0x001F, 0xFC00, 0x2000, /*   X            XXXXXX                     XXXXXX             X   */
318 	0x8004, 0x001F, 0xFC00, 0x2000, /*   X            XXXXXX                     XXXXXX             X   */
319 	0x8004, 0x001F, 0xFC00, 0x2000, /*   X            XXXXXX                     XXXXXX             X   */
320 	0x8002, 0x001F, 0xFC00, 0x4000, /*  X             XXXXXX                     XXXXXX              X  */
321 	0x8002, 0x001F, 0xFC00, 0x4000, /*  X             XXXXXX                     XXXXXX              X  */
322 	0x8002, 0x001F, 0xFC00, 0x4000, /*  X             XXXXXX                     XXXXXX              X  */
323 	0x8002, 0x001F, 0xFC00, 0x4000, /*  X             XXXXXX                     XXXXXX              X  */
324 	0x8002, 0x001F, 0xFC00, 0x4000, /*  X             XXXXXX                     XXXXXX              X  */
325 	0x8001, 0x001F, 0xFC00, 0x8000, /* X              XXXXXX                     XXXXXX               X */
326 	0x8001, 0x001F, 0xFC00, 0x8000, /* X              XXXXXX                     XXXXXX               X */
327 	0x8001, 0x001F, 0xFC00, 0x8000, /* X              XXXXXX                     XXXXXX               X */
328 	0x8001, 0x001F, 0xFC00, 0x8000, /* X              XXXXXX                     XXXXXX               X */
329 	0x8001, 0x001F, 0xFC00, 0x8000, /* X              XXXXXX                     XXXXXX               X */
330 	0x8001, 0x001F, 0xFC00, 0x8000, /* X              XXXXXX                     XXXXXX               X */
331 	0x0001, 0x0000, 0x0000, 0x8000, /* X                                                              X */
332 	0x0001, 0x0000, 0x0000, 0x8000, /* X                                                              X */
333 	0x0001, 0x0000, 0x0000, 0x8000, /* X                                                              X */
334 	0x0001, 0x0000, 0x0000, 0x8000, /* X                                                              X */
335 	0x0001, 0x0000, 0x0000, 0x8000, /* X                                                              X */
336 	0x0001, 0xF000, 0x0007, 0x8000, /* X                           XXXXXXX                            X */
337 	0x0002, 0xF800, 0x000F, 0x4000, /*  X                         XXXXXXXXX                          X  */
338 	0x0002, 0xFC00, 0x001F, 0x4000, /*  X                        XXXXXXXXXXX                         X  */
339 	0x0002, 0xFE00, 0x003F, 0x4000, /*  X                       XXXXXXXXXXXXX                        X  */
340 	0x0002, 0xFE00, 0x003F, 0x4000, /*  X                       XXXXXXXXXXXXX                        X  */
341 	0x0002, 0xFE00, 0x003F, 0x4000, /*  X                       XXXXXXXXXXXXX                        X  */
342 	0x0004, 0xFE00, 0x003F, 0x2000, /*   X                      XXXXXXXXXXXXX                       X   */
343 	0x0004, 0xFE00, 0x003F, 0x2000, /*   X                      XXXXXXXXXXXXX                       X   */
344 	0x0004, 0xFE00, 0x003F, 0x2000, /*   X                      XXXXXXXXXXXXX                       X   */
345 	0x0008, 0xFE00, 0x003F, 0x1000, /*    X                     XXXXXXXXXXXXX                      X    */
346 	0x0008, 0xFE00, 0x003F, 0x1000, /*    X                     XXXXXXXXXXXXX                      X    */
347 	0x0010, 0xFE00, 0x003F, 0x0800, /*     X                    XXXXXXXXXXXXX                     X     */
348 	0x0010, 0xFE00, 0x003F, 0x0800, /*     X                    XXXXXXXXXXXXX                     X     */
349 	0x0020, 0xFE00, 0x003F, 0x0400, /*      X                   XXXXXXXXXXXXX                    X      */
350 	0x0020, 0x0000, 0x0000, 0x0400, /*      X                                                    X      */
351 	0x0040, 0x0000, 0x0000, 0x0200, /*       X                                                  X       */
352 	0x0040, 0x0000, 0x0000, 0x0200, /*       X                                                  X       */
353 	0x0080, 0x0000, 0x0000, 0x0100, /*        X                                                X        */
354 	0x0080, 0x0000, 0x0000, 0x0100, /*        X                                                X        */
355 	0x0100, 0x0000, 0x0000, 0x0080, /*         X                                              X         */
356 	0x0200, 0x0000, 0x0000, 0x0040, /*          X                                            X          */
357 	0x0400, 0x0000, 0x0000, 0x0020, /*           X                                          X           */
358 	0xF800, 0xFFFF, 0xFFFF, 0x001F, /*            XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX            */
359 	0x0000, 0x0000, 0x0000, 0x0000, /*                                                                  */
360 	0x0000, 0x0000, 0x0000, 0x0000, /*                                                                  */
361 	0x0000, 0x0000, 0x0000, 0x0000, /*                                                                  */
362 	0x0000, 0x0000, 0x0000, 0x0000  /*                                                                  */
363   };
364 #endif
365 
366 #if 0
367 /* the normal cursor mask (NORMALCURSOR, an "X") */
368 static UINTSML gra_realcursormask[16] = {
369 	0xC003, /* XX            XX */
370 	0xE007, /* XXX          XXX */
371 	0x700E, /*  XXX        XXX  */
372 	0x381C, /*   XXX      XXX   */
373 	0x1C38, /*    XXX    XXX    */
374 	0x0E70, /*     XXX  XXX     */
375 	0x07E0, /*      XXXXXX      */
376 	0x03C0, /*       XXXX       */
377 	0x03C0, /*       XXXX       */
378 	0x07E0, /*      XXXXXX      */
379 	0x0E70, /*     XXX  XXX     */
380 	0x1C38, /*    XXX    XXX    */
381 	0x381C, /*   XXX      XXX   */
382 	0x700E, /*  XXX        XXX  */
383 	0xE007, /* XXX          XXX */
384 	0xC003  /* XX            XX */
385 };
386 
387 /* the normal cursor data (NORMALCURSOR, an "X") */
388 static UINTSML gra_realcursordata[16] = {
389 	0x0000, /*                  */
390 	0x4002, /*  X            X  */
391 	0x2004, /*   X          X   */
392 	0x1008, /*    X        X    */
393 	0x0810, /*     X      X     */
394 	0x0420, /*      X    X      */
395 	0x0240, /*       X  X       */
396 	0x0180, /*        XX        */
397 	0x0180, /*        XX        */
398 	0x0240, /*       X  X       */
399 	0x0420, /*      X    X      */
400 	0x0810, /*     X      X     */
401 	0x1008, /*    X        X    */
402 	0x2004, /*   X          X   */
403 	0x4002, /*  X            X  */
404 	0x0000  /*                  */
405 };
406 #else
407 /* the normal cursor mask (NORMALCURSOR, an "X") */
408 static UINTSML gra_realcursormask[16] = {
409 	0x6006, /*  XX          XX  */
410 	0xF00F, /* XXXX        XXXX */
411 	0xF81F, /* XXXXX      XXXXX */
412 	0x7C3E, /*  XXXXX    XXXXX  */
413 	0x3E7C, /*   XXXXX  XXXXX   */
414 	0x1FF8, /*    XXXXXXXXXX    */
415 	0x0FF0, /*     XXXXXXXX     */
416 	0x0660, /*      XX  XX      */
417 	0x0660, /*      XX  XX      */
418 	0x0FF0, /*     XXXXXXXX     */
419 	0x1FF8, /*    XXXXXXXXXX    */
420 	0x3E7C, /*   XXXXX  XXXXX   */
421 	0x7C3E, /*  XXXXX    XXXXX  */
422 	0xF81F, /* XXXXX      XXXXX */
423 	0xF00F, /* XXXX        XXXX */
424 	0x6006  /*  XX          XX  */
425 };
426 
427 /* the normal cursor data (NORMALCURSOR, an "X") */
428 static UINTSML gra_realcursordata[16] = {
429 	0x0000, /*                  */
430 	0x6006, /*  XX          XX  */
431 	0x700E, /*  XXX        XXX  */
432 	0x381C, /*   XXX      XXX   */
433 	0x1C38, /*    XXX    XXX    */
434 	0x0E70, /*     XXX  XXX     */
435 	0x07E0, /*      XXXXXX      */
436 	0x0240, /*       X  X       */
437 	0x0240, /*       X  X       */
438 	0x07E0, /*      XXXXXX      */
439 	0x0E70, /*     XXX  XXX     */
440 	0x1C38, /*    XXX    XXX    */
441 	0x381C, /*   XXX      XXX   */
442 	0x700E, /*  XXX        XXX  */
443 	0x6006, /*  XX          XX  */
444 	0x0000  /*                  */
445 };
446 #endif
447 
448 /* the "draw with pen" cursor mask (PENCURSOR, a pen) */
449 static UINTSML gra_drawcursormask[16] = {
450 	0x3000, /*             XX   */
451 	0x7800, /*            XXXX  */
452 	0xFC00, /*           XXXXXX */
453 	0xFE00, /*          XXXXXXX */
454 	0x7F00, /*         XXXXXXX  */
455 	0x3F80, /*        XXXXXXX   */
456 	0x1FC0, /*       XXXXXXX    */
457 	0x0FE0, /*      XXXXXXX     */
458 	0x07F0, /*     XXXXXXX      */
459 	0x03F8, /*    XXXXXXX       */
460 	0x01FC, /*   XXXXXXX        */
461 	0x00FC, /*   XXXXXX         */
462 	0x007E, /*  XXXXXX          */
463 	0x003E, /*  XXXXX           */
464 	0x000F, /* XXXX             */
465 	0x0003  /* XX               */
466 };
467 
468 /* the "draw with pen" cursor data (PENCURSOR, a pen) */
469 static UINTSML gra_drawcursordata[16] = {
470 	0x0000, /*                  */
471 	0x0000, /*                  */
472 	0x0800, /*            X     */
473 	0x1C00, /*           XXX    */
474 	0x3E00, /*          XXXXX   */
475 	0x1F00, /*         XXXXX    */
476 	0x0F80, /*        XXXXX     */
477 	0x07C0, /*       XXXXX      */
478 	0x03E0, /*      XXXXX       */
479 	0x01F0, /*     XXXXX        */
480 	0x00F0, /*     XXXX         */
481 	0x0070, /*     XXX          */
482 	0x0000, /*                  */
483 	0x0000, /*                  */
484 	0x0004, /*  X               */
485 	0x0000  /*                  */
486 };
487 
488 /* the "technology" command dragging cursor mask (TECHCURSOR, a "T") */
489 static UINTSML gra_techcursormask[16] = {
490 	0x0380, /*        XXX       A */
491 	0x07C0, /*       XXXXX      B */
492 	0x0FE0, /*      XXXXXXX     C */
493 	0x0380, /*        XXX       D */
494 	0x7FFC, /*   XXXXXXXXXXXXX  E */
495 	0x7FFC, /*   XXXXXXXXXXXXX  F */
496 	0x7FFC, /*   XXXXXXXXXXXXX  G */
497 	0x7FFC, /*   XXXXXXXXXXXXX  H */
498 	0x77DC, /*   XXX XXXXX XXX  I */
499 	0x07C0, /*       XXXXX      J */
500 	0x07C0, /*       XXXXX      K */
501 	0x07C0, /*       XXXXX      L */
502 	0x07C0, /*       XXXXX      M */
503 	0x0FE0, /*      XXXXXXX     N */
504 	0x0FE0, /*      XXXXXXX     O */
505 	0x0FE0  /*      XXXXXXX     P */
506 };
507 
508 /* the "technology" command dragging cursor data (TECHCURSOR, a "T") */
509 static UINTSML gra_techcursordata[16] = {
510 	0x0100, /*         X        A */
511 	0x0380, /*        XXX       B */
512 	0x0540, /*       X X X      C */
513 	0x0100, /*         X        D */
514 	0x0100, /*         X        E */
515 	0x3FF8, /*    XXXXXXXXXXX   F */
516 	0x3FF8, /*    XXXXXXXXXXX   G */
517 	0x2388, /*    X   XXX   X   H */
518 	0x0380, /*        XXX       I */
519 	0x0380, /*        XXX       J */
520 	0x0380, /*        XXX       K */
521 	0x0380, /*        XXX       L */
522 	0x0380, /*        XXX       M */
523 	0x0380, /*        XXX       N */
524 	0x07C0, /*       XXXXX      O */
525 	0x0000  /*                  P */
526 };
527 
528 /* the "ibeam" text selection cursor mask (IBEAMCURSOR, an "I") */
529 static UINTSML gra_ibeamcursormask[16] = {
530 	0x07F0, /*     XXXXXXX      */
531 	0x07F0, /*     XXXXXXX      */
532 	0x07F0, /*     XXXXXXX      */
533 	0x01C0, /*       XXX        */
534 	0x01C0, /*       XXX        */
535 	0x01C0, /*       XXX        */
536 	0x01C0, /*       XXX        */
537 	0x01C0, /*       XXX        */
538 	0x01C0, /*       XXX        */
539 	0x01C0, /*       XXX        */
540 	0x01C0, /*       XXX        */
541 	0x01C0, /*       XXX        */
542 	0x01C0, /*       XXX        */
543 	0x07F0, /*     XXXXXXX      */
544 	0x07F0, /*     XXXXXXX      */
545 	0x07F0  /*     XXXXXXX      */
546 };
547 
548 /* the "ibeam" text selection cursor data (IBEAMCURSOR, an "I") */
549 static UINTSML gra_ibeamcursordata[16] = {
550 	0x0000, /*                  */
551 	0x0360, /*      XX XX       */
552 	0x0080, /*        X         */
553 	0x0080, /*        X         */
554 	0x0080, /*        X         */
555 	0x0080, /*        X         */
556 	0x0080, /*        X         */
557 	0x0080, /*        X         */
558 	0x0080, /*        X         */
559 	0x0080, /*        X         */
560 	0x0080, /*        X         */
561 	0x0080, /*        X         */
562 	0x0080, /*        X         */
563 	0x0080, /*        X         */
564 	0x0360, /*      XX XX       */
565 	0x0000  /*                  */
566 };
567 
568 /* the "use the TTY" cursor (WANTTTYCURSOR, the word "tty" above keyboard) */
569 static UINTSML gra_nomousecursordata[16] = {
570 	0x7757, /* XXX X X XXX XXX  */
571 	0x1552, /*  X  X X X X X    */
572 	0x3772, /*  X  XXX XXX XX   */
573 	0x1122, /*  X   X  X   X    */
574 	0x7122, /*  X   X  X   XXX  */
575 	0x0000, /*                  */
576 	0xFFFF, /* XXXXXXXXXXXXXXXX */
577 	0x8001, /* X              X */
578 	0x8AA9, /* X  X X X X X   X */
579 	0x9551, /* X   X X X X X  X */
580 	0x8AA9, /* X  X X X X X   X */
581 	0x9551, /* X   X X X X X  X */
582 	0x8001, /* X              X */
583 	0x9FF9, /* X  XXXXXXXXXX  X */
584 	0x8001, /* X              X */
585 	0xFFFF  /* XXXXXXXXXXXXXXXX */
586 };
587 
588 /* the menu selection cursor (MENUCURSOR, a sideways arrow) */
589 static UINTSML gra_menucursordata[16] = {
590 	0x0000, /*                  */
591 	0x0000, /*                  */
592 	0x0400, /*           X      */
593 	0x0C00, /*           XX     */
594 	0x1C00, /*           XXX    */
595 	0x3C00, /*           XXXX   */
596 	0x7FFF, /* XXXXXXXXXXXXXXX  */
597 	0xFFFF, /* XXXXXXXXXXXXXXXX */
598 	0x7FFF, /* XXXXXXXXXXXXXXX  */
599 	0x3C00, /*           XXXX   */
600 	0x1C00, /*           XXX    */
601 	0x0C00, /*           XX     */
602 	0x0400, /*           X      */
603 	0x0000, /*                  */
604 	0x0000, /*                  */
605 	0x0000  /*                  */
606 };
607 
608 /****** time ******/
609 static QTime gra_timebase;
610 
611 /****** files ******/
612 static void         *gra_fileliststringarray = 0;
613 static char          gra_curpath[255] = {0};
614 static char        **gra_printerlist;
615 static INTBIG        gra_printerlistcount = 0;
616 static INTBIG        gra_printerlisttotal = 0;
617 
618 INTSML     gra_addprinter(char *buf);
619 #ifdef MACOS
620   void     mac_settypecreator(char *name, INTBIG type, INTBIG creator);
621 #endif
622 
623 /******************** INITIALIZATION ********************/
624 
main(int argc,char * argv[])625 int main(int argc, char *argv[])
626 {
627 	/* catch signals if Electric trys to bomb out */
628 	(void)signal(SIGILL, (SIGNALCAST)gra_sigill_trap);
629 	(void)signal(SIGFPE, (SIGNALCAST)gra_sigfpe_trap);
630 	(void)signal(SIGBUS, (SIGNALCAST)gra_sigbus_trap);
631 	(void)signal(SIGSEGV, (SIGNALCAST)gra_sigsegv_trap);
632 
633 	/* primary initialization of Electric */
634 	gra_state = S_STARTUP;
635 	osprimaryosinit();
636 #ifdef ETRACE
637 	etrace(GTRACE, "  after osprimaryosinit...\n");
638 #endif
639 
640 #if LANGTCL
641 	/* initialize TCL here */
642 	if (gra_initializetcl() == TCL_ERROR)
643 		error(_("Failed to initialize TCL: %s\n"), gra_tclinterp->result);
644 #endif
645 
646 	/* secondary initialization of Electric */
647 #ifdef ETRACE
648 	etrace(GTRACE, "  calling ossecondaryinit...\n");
649 #endif
650 	ossecondaryinit(argc, argv);
651 
652     /* initialize the "click" sound */
653 	if (QSound::available())
654 	{
655 		void *infstr = initinfstr();
656 		formatinfstr(infstr, "%sclick.wav", el_libdir);
657 		gra_clicksound = new QSound(returninfstr(infstr));
658 	}
659 
660 	gra_state = S_USER;
661 #ifdef ETRACE
662 	etrace(GTRACE, "  gra_state=USER\n");
663 #endif
664 	db_setcurrenttool(us_tool);
665 	/* first see if there is any pending input */
666 	el_pleasestop = 0;
667 
668 #ifdef ETRACE
669 	etrace(GTRACE, "  main loop...\n");
670 #endif
671 	gra->exec();
672 	return(0);
673 }
674 
675 /*
676  * Routine to establish the default display define tty codes.
677  */
graphicsoptions(char * name,INTBIG * argc,char ** argv)678 void graphicsoptions(char *name, INTBIG *argc, char **argv)
679 {
680 	Q_UNUSED( name );
681 
682 #ifdef ETRACE
683 	INTBIG i;
684 
685 	etrace(GTRACE, "{ graphicsoptions: args=");
686 	for (i = 0; i < *argc; i++) etrace(GTRACE_CONT, " <%s>", argv[i]);
687 	etrace(GTRACE_CONT, "\n");
688 #endif
689 
690 	int int_argc = *argc;
691 	gra = new EApplication(int_argc, argv);
692 	*argc = int_argc;
693 
694 	/* make the messages window */
695 #ifdef USEMDI
696     QDockWindow *messMainWin = new QDockWindow( QDockWindow::InDock, gra->mw );
697 	//QDockWindow *messMainWin = new QDockWindow( gra->mw, "MessagesMainWindow", 0 );
698 	messMainWin->setResizeEnabled( TRUE );
699     messMainWin->setCloseMode( QDockWindow::Never );
700 	gra->mw->moveDockWindow( messMainWin, Qt::DockBottom );
701 	gra->messages = new EMessages( messMainWin );
702     messMainWin->setWidget( gra->messages );
703     messMainWin->setFixedExtentHeight( 150 );
704 	gra->messages->connect(messMainWin, SIGNAL(placeChanged(QDockWindow::Place)), SLOT(setIcons()));
705 	gra->messages->show();
706 #else
707 #  ifdef MESSMENU
708 	EMainWindow *messMainWin = new EMainWindow( 0, "MessagesMainWindow", Qt::WType_TopLevel, FALSE );
709 	messMainWin->pulldownmenuload();
710 #  else
711 	QMainWindow *messMainWin = new QMainWindow( 0, "MessagesMainWindow", Qt::WType_TopLevel );
712 #  endif
713 	gra->messages = new EMessages( messMainWin );
714 	messMainWin->setCentralWidget( gra->messages );
715     messMainWin->installEventFilter( gra->messages );
716 	gra->setMainWidget( messMainWin );
717 #endif
718 
719     /* Determine initial position and size of messages window */
720 	INTBIG screensizex, screensizey;
721 	gra_getsensiblescreensize(&screensizex, &screensizey);
722 #ifdef ETRACE
723 	etrace(GTRACE, "  graphicsoptions: screensizex=%d screensizey=%d\n", screensizex, screensizey);
724 #endif
725     int width = screensizex / 3 * 2;
726     int height = screensizey / 4 - 80;
727     int x = (screensizex - width) / 2;
728     int y = screensizey - height - 52;
729 #ifndef USEMDI
730     messMainWin->setGeometry(x, y, width, height);
731 #endif
732 
733 	gra->messages->setIcons();
734 	messMainWin->show();
735 
736 	/* Determine initial position and size of edit window */
737 	gra_editposx = PALETTEWIDTH;
738 #ifdef MACOSX
739 	gra_editposy = 45;
740 #else
741 	gra_editposy = 0;
742 #endif
743 
744 	/* get screen size (but just 1 screen, if there are two) */
745 	gra_getsensiblescreensize(&screensizex, &screensizey);
746 #ifdef ETRACE
747 	etrace(GTRACE, "  graphicsoptions: screensizex=%d screensizey=%d\n", screensizex, screensizey);
748 #endif
749 	gra_editsizex = (screensizex - PALETTEWIDTH - 8) / 5 * 4;
750 	gra_editsizey = (screensizey - 2) * 3 / 5;
751 
752 	QSettings settings;
753 	settings.insertSearchPath( QSettings::Windows, "/StaticFreeSoft" ); /* MS Windows-only */
754 	if ( settings.subkeyList( "/Electric" ).contains( "geometry" ) > 0 )
755 	{
756 		/* Get position and size from settings */
757 		gra_editposx = settings.readNumEntry( "/Electric/geometry/x", gra_editposx );
758 		gra_editposy = settings.readNumEntry( "/Electric/geometry/y", gra_editposy );
759 		gra_editsizex = settings.readNumEntry( "/Electric/geometry/width", gra_editsizex );
760 		gra_editsizey = settings.readNumEntry( "/Electric/geometry/height", gra_editsizey );
761 	} else
762 	{
763 		/* setting not found. Write them */
764 		settings.writeEntry( "/Electric/geometry/x", int(gra_editposx) );
765 		settings.writeEntry( "/Electric/geometry/y", int(gra_editposy) );
766 		settings.writeEntry( "/Electric/geometry/width", int(gra_editsizex) );
767 		settings.writeEntry( "/Electric/geometry/height", int(gra_editsizey) );
768 	}
769 
770 #ifdef ETRACE
771 	etrace(GTRACE, "} graphicsoptions: el_colcursor=%#o el_maplength=%d\n", el_colcursor, el_maplength);
772 #endif
773 }
774 
775 /*
776  * Routine to initialize the display device.
777  */
initgraphics(BOOLEAN messages)778 BOOLEAN initgraphics(BOOLEAN messages)
779 {
780 #ifdef ETRACE
781 	etrace(GTRACE, "{} initgraphics: messages=%d\n", messages);
782 #else
783 	Q_UNUSED( messages );
784 #endif
785 	return(FALSE);
786 }
787 
EApplicationWindow()788 EApplicationWindow::EApplicationWindow()
789 	: EMainWindow( 0, "EApplicationWindow", WType_TopLevel, TRUE )
790 {
791 #ifdef USEMDI
792     QVBox* vb = new QVBox( this );
793     vb->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
794     ws = new QWorkspace( vb );
795     //ws->setScrollBarsEnabled( TRUE );
796     setCentralWidget( vb );
797 #endif
798 }
799 
EApplication(int & argc,char ** argv)800 EApplication::EApplication( int &argc, char **argv)
801   : QApplication (argc, argv), mw( 0 ), textbits( 0, 0 ), charbits( 0, 0 )
802 {
803     REGISTER UINTBIG i, j;
804     char *ptr;
805     char *geomSpec;
806 
807     /* initialize X and the toolkit */
808 
809 	/* get switch settings */
810 	geomSpec = NULL;
811 	for(int k=1; k < argc; k++)
812 	{
813 		if (argv[k][0] == '-')
814 		{
815 			switch (argv[k][1])
816 			{
817 				case 'g':       /* Geometry */
818 					if (++k >= argc) continue;
819 					geomSpec = argv[k];
820 					continue;
821 			}
822 		}
823 	}
824 
825 	/* double-click threshold (in milliseconds) */
826 #ifdef MACOS
827 	gra_doublethresh = GetDblTime()*1000/60;
828 #else
829 	gra_doublethresh = doubleClickInterval();
830 #endif
831 
832 	/* get the information about the edit display */
833 	if (QPixmap::defaultDepth() == 1)
834 		fprintf(stderr, _("Cannot run on 1-bit deep displays\n"));
835 	el_colcursor = CURSOR;	/* also done in usr.c later */
836 	el_maplength = 256;
837 
838 	gra_windownumber = 0;
839 
840 	/* get fonts */
841 #ifdef MACOS
842 	fixedfont.setFamily("Monaco");
843 	fixedfont.setPointSize(10);
844 #else
845 	fixedfont.setFamily( QString::null );
846 	fixedfont.setStyleHint( QFont::TypeWriter );
847 	fixedfont.setStyleStrategy( QFont::NoAntialias );
848 	fixedfont.setFixedPitch( TRUE );
849 #endif
850 
851 	/* initialize font cache */
852 	QFontDatabase fdb;
853 	facelist = fdb.families();
854 	gra_initfaces( facelist );
855 	char **localfacelist;
856 	screengetfacelist(&localfacelist, TRUE);
857 	ptr = getenv("ELECTRIC_TRUETYPE_FONT");
858 	if (ptr != NULL)
859 	{
860 		for(i=0; i<facelist.count(); i++)
861 		{
862 			if (namesame(ptr, localfacelist[i]) == 0)
863 			{
864 				defface = localfacelist[i];
865 				break;
866 			}
867 		}
868 		if (i >= facelist.count())
869 		{
870 			printf(_("Warning: environment variable 'ELECTRIC_TRUETYPE_FONT' is '%s' which is not a known font\n"),
871 				ptr);
872 			printf(_("Choices are:\n"));
873 			for(j=0; j<facelist.count(); j++)
874 			{
875 				printf("  %s\n", localfacelist[j]);
876 			}
877 		}
878 	}
879 	if (defface.isEmpty())
880 	{
881 #ifdef MACOSX
882 		for(i=0; i<facelist.count(); i++)
883 		{
884 			if (namesame("Charcoal", localfacelist[i]) == 0)
885 			{
886 				defface = localfacelist[i];
887 				break;
888 			}
889 		}
890 		if (defface.isEmpty())
891 #endif
892 		defface = font().family();
893 	}
894 
895 
896 	/* on machines with reverse byte ordering, fix the icon and the cursors */
897 #ifdef SWAPPED
898 	j = PROGICONSIZE * PROGICONSIZE / 16;
899 	for(i=0; i<j; i++)
900 		gra_icon[i] = ((gra_icon[i] >> 8) & 0xFF) | ((gra_icon[i] << 8) & 0xFF00);
901 	for(i=0; i<16; i++)
902 	{
903 		gra_realcursordata[i] = ((gra_realcursordata[i] >> 8) & 0xFF) |
904 			((gra_realcursordata[i] << 8) & 0xFF00);
905 		gra_realcursormask[i] = ((gra_realcursormask[i] >> 8) & 0xFF) |
906 			((gra_realcursormask[i] << 8) & 0xFF00);
907 
908 		gra_drawcursordata[i] = ((gra_drawcursordata[i] >> 8) & 0xFF) |
909 			((gra_drawcursordata[i] << 8) & 0xFF00);
910 		gra_drawcursormask[i] = ((gra_drawcursormask[i] >> 8) & 0xFF) |
911 			((gra_drawcursormask[i] << 8) & 0xFF00);
912 
913 		gra_techcursordata[i] = ((gra_techcursordata[i] >> 8) & 0xFF) |
914 			((gra_techcursordata[i] << 8) & 0xFF00);
915 		gra_techcursormask[i] = ((gra_techcursormask[i] >> 8) & 0xFF) |
916 			((gra_techcursormask[i] << 8) & 0xFF00);
917 
918 		gra_ibeamcursordata[i] = ((gra_ibeamcursordata[i] >> 8) & 0xFF) |
919 			((gra_ibeamcursordata[i] << 8) & 0xFF00);
920 		gra_ibeamcursormask[i] = ((gra_ibeamcursormask[i] >> 8) & 0xFF) |
921 			((gra_ibeamcursormask[i] << 8) & 0xFF00);
922 
923 		gra_nomousecursordata[i] = ((gra_nomousecursordata[i] >> 8) & 0xFF) |
924 			((gra_nomousecursordata[i] << 8) & 0xFF00);
925 		gra_menucursordata[i] = ((gra_menucursordata[i] >> 8) & 0xFF) |
926 			((gra_menucursordata[i] << 8) & 0xFF00);
927 	}
928 #endif
929 #ifndef MACOS
930 	programicon = QBitmap (PROGICONSIZE, PROGICONSIZE, (uchar*)gra_icon, TRUE);
931 #endif
932 
933 	/* create the cursors */
934 	QBitmap bitm, mbitm;
935 
936 	/* these cursors have shadows around them and show up right on any color scheme */
937 	nullcursor = QCursor(WaitCursor);
938 	handcursor = QCursor(PointingHandCursor);
939 	lrcursor = QCursor(SizeHorCursor);
940 	udcursor = QCursor(SizeVerCursor);
941 
942 	bitm = QBitmap( 16, 16, (uchar*)gra_realcursordata, TRUE );
943 	mbitm = QBitmap( 16, 16, (uchar*)gra_realcursormask, TRUE );
944 	realcursor = QCursor( bitm, mbitm, 8, 8 );
945 
946 	bitm = QBitmap( 16, 16, (uchar*)gra_drawcursordata, TRUE );
947 	mbitm = QBitmap( 16, 16, (uchar*)gra_drawcursormask, TRUE );
948 	drawcursor = QCursor( bitm, mbitm, 0, 16 );
949 
950 	bitm = QBitmap( 16, 16, (uchar*)gra_ibeamcursordata, TRUE );
951 	mbitm = QBitmap( 16, 16, (uchar*)gra_ibeamcursormask, TRUE );
952 	ibeamcursor = QCursor( bitm, mbitm, 8, 8 );
953 
954 	bitm = QBitmap( 16, 16, (uchar*)gra_techcursordata, TRUE );
955 	mbitm = QBitmap( 16, 16, (uchar*)gra_techcursormask, TRUE );
956 	techcursor = QCursor( bitm, mbitm, 8, 0 );
957 
958 	/* these cursors are not really used, so the masking doesn't really matter */
959 	bitm = QBitmap( 16, 16, (uchar*)gra_nomousecursordata, TRUE );
960 	nomousecursor = QCursor( bitm, bitm, 8, 8 );
961 
962 	bitm = QBitmap( 16, 16, (uchar*)gra_menucursordata, TRUE );
963 	menucursor = QCursor( bitm, bitm, 16, 8 );
964 
965 	/* initialize the window frames */
966 	el_firstwindowframe = el_curwindowframe = NOWINDOWFRAME;
967 
968 	/* initialize the mouse */
969 	us_cursorstate = -1;
970 	us_normalcursor = NORMALCURSOR;
971 
972 #ifdef USEMDI
973 	/* initialize application window with workspace */
974 	mw = new EApplicationWindow();
975 #ifdef EPROGRAMNAME
976     (void)sprintf(gra_localstring, EPROGRAMNAME);
977 #else
978     (void)sprintf(gra_localstring, _("Electric"));
979 #endif
980 #ifndef MACOS
981     mw->setIcon( programicon );
982 #endif
983     mw->setCaption( gra_localstring );
984     mw->setIconText( gra_localstring );
985 
986 	setMainWidget( mw );
987 	mw->show();
988 #endif
989 
990 #ifdef ETRACE
991 	etrace(GTRACE, "  initgraphics: us_cursorstate=%d us_normalcursor=%d\n",
992 	       us_cursorstate, us_normalcursor);
993 #endif
994 }
995 
notify(QObject * receiver,QEvent * e)996 bool EApplication::notify( QObject *receiver, QEvent *e )
997 {
998 #ifdef MACOSX
999 	if (e->spontaneous())
1000 	{
1001 		switch (e->type())
1002 		{
1003 			case QEvent::KeyPress:
1004 				{
1005 					QKeyEvent *ke = (QKeyEvent*)e;
1006 					/* ttyputmsg(_("Key %x pressed"), ke->key()); */
1007 				}
1008 				break;
1009 			case QEvent::KeyRelease:
1010 				{
1011 					QKeyEvent *ke = (QKeyEvent*)e;
1012 					/* ttyputmsg(_("Key %x released"), ke->key()); */
1013 				}
1014 				break;
1015 
1016 			case QEvent::MouseButtonPress:
1017 				{
1018 					QMouseEvent *me = (QMouseEvent*)e;
1019 					/* ttyputmsg(_("notify MouseButtonPress %o"), me->button() ); */
1020 				}
1021 				break;
1022 		}
1023 	}
1024 #endif
1025 	return QApplication::notify( receiver, e );
1026 }
1027 
1028 /*
1029  * Routine to return the size of the screen (but only one of them if a multiscreen world)
1030  */
gra_getsensiblescreensize(INTBIG * screensizex,INTBIG * screensizey)1031 void gra_getsensiblescreensize(INTBIG *screensizex, INTBIG *screensizey)
1032 {
1033 #ifdef USEMDI
1034 	if (gra->mw && gra->mw->ws)
1035 	{
1036 		*screensizex = gra->mw->ws->width();
1037 		*screensizey = gra->mw->ws->height();
1038 	} else
1039 #endif
1040 	{
1041 		*screensizex = gra->desktop()->width();
1042 		*screensizey = gra->desktop()->height();
1043 	}
1044 	if (*screensizex > *screensizey * 2) *screensizex /= 2; else
1045 		if (*screensizey > *screensizex * 2) *screensizey /= 2;
1046 }
1047 
EMessages(QWidget * parent)1048 EMessages::EMessages( QWidget *parent )
1049   : QVBox( parent ), stopped(FALSE)
1050 {
1051     scroll = new QTextEdit( this );
1052 	scroll->setTextFormat(Qt::PlainText);
1053     scroll->setReadOnly( TRUE );
1054     scroll->setWordWrap( QTextEdit::NoWrap );
1055     scroll->viewport()->setCursor( IbeamCursor );
1056     scroll->installEventFilter( this );
1057 
1058     input = new QHBox( this );
1059     prompt = new QLabel( input );
1060     line = new QLineEdit( input );
1061     input->hide();
1062 
1063     connect(line, SIGNAL(returnPressed()), SLOT(lineEntered()));
1064     line->installEventFilter( this );
1065 
1066     gra_messages_typingin = 0;
1067 }
1068 
clear()1069 void EMessages::clear()
1070 {
1071 	scroll->clear();
1072 }
1073 
putString(char * s,BOOLEAN important)1074 void EMessages::putString(char *s, BOOLEAN important)
1075 {
1076     QString qstr = QString::fromLocal8Bit( s );
1077 	scroll->insertParagraph( qstr, -1 );
1078     scroll->scrollToBottom();
1079 	qApp->flush();
1080 
1081 	/* make sure the window isn't iconified or obscured */
1082 	if (important)
1083 		parentWidget()->raise();
1084 }
1085 
getString(char * promptStr)1086 char *EMessages::getString(char *promptStr)
1087 {
1088 	/* change state */
1089 	GRAPHSTATE savedstate = gra_state;
1090 	gra_state = S_MODAL;
1091 #ifdef ETRACE
1092 	etrace(GTRACE, "  gra_state=MODAL\n");
1093 #endif
1094 	gra->charhandler = 0;
1095 	gra->buttonhandler = 0;
1096 
1097 	/* set cursor */
1098 	INTBIG oldnormalcursor = us_normalcursor;
1099 	setnormalcursor(WANTTTYCURSOR);
1100 
1101     QString qstr = QString::fromLocal8Bit( promptStr );
1102 	prompt->setText( qstr );
1103 	line->clear();
1104 	stopped = FALSE;
1105 	input->show();
1106 	parentWidget()->raise();
1107 	line->grabKeyboard();
1108 	gra->enter_loop();
1109 	input->hide();
1110 
1111 	/* restore cursor */
1112 	setnormalcursor(oldnormalcursor);
1113 	gra_state = savedstate;
1114 
1115 	if (stopped) return(0);
1116 	scroll->insertParagraph( prompt->text() + line->text(), -1 );
1117 	scroll->scrollToBottom();
1118 	char *str = EApplication::localize( line->text() );
1119 	return(str);
1120 }
1121 
setFont()1122 void EMessages::setFont()
1123 {
1124 	bool ok;
1125 	QFont font = scroll->font();
1126 	font = QFontDialog::getFont( &ok, font, parentWidget() );
1127 	if (ok)
1128 		scroll->setFont( font );
1129 }
1130 
setColor(QColor & bg,QColor & fg)1131 void EMessages::setColor( QColor &bg, QColor &fg )
1132 {
1133 	QPalette palette = scroll->palette();
1134 	palette.setColor( QColorGroup::Base, bg );
1135 	palette.setColor( QColorGroup::Text, fg );
1136 	scroll->setPalette( palette );
1137 }
1138 
keyPressEvent(QKeyEvent * e)1139 void EMessages::keyPressEvent( QKeyEvent *e )
1140 {
1141 #ifdef ETRACE
1142     etrace(GTRACE, "{ EMessages::keyPressEvent %s accepted=%d\n", stateNames[gra_state], e->isAccepted());
1143 #endif
1144     INTBIG special;
1145     int state = gra->translatekey(e, &special);
1146 
1147     if (state != 0 || special != 0)
1148     {
1149         us_state |= DIDINPUT;
1150 		INTSML cmd = state;
1151 #ifdef ETRACE
1152 		etrace(GTRACE, "  EMessages::keyPressEvent: %s state=%#o cmd=%#o special=%#o DIDINPUT%d,%d\n",
1153 			stateNames[gra_state], state, cmd, special, gra_cursorx, gra_cursory );
1154 #endif
1155 
1156 		switch (gra_state)
1157 		{
1158 			case S_USER:
1159 #ifdef ETRACE
1160 				etrace(GTRACE, "{ us_oncommand: cmd=%#o special=%#o\n", cmd, special);
1161 #endif
1162 				us_oncommand( cmd, special );
1163 				gra->toolTimeSlice();
1164 #ifdef ETRACE
1165 				etrace(GTRACE, "} us_oncommand\n");
1166 #endif
1167 				break;
1168             default:
1169                 break;
1170 		}
1171 		e->accept();
1172     }
1173     else QVBox::keyPressEvent( e );
1174 #ifdef ETRACE
1175     etrace(GTRACE, "} EMessages::keyPressEvent accepted=%d\n", e->isAccepted());
1176 #endif
1177 }
1178 
lineEntered()1179 void EMessages::lineEntered()
1180 {
1181     line->releaseKeyboard();
1182     gra->exit_loop();
1183 }
1184 
setIcons()1185 void EMessages::setIcons()
1186 {
1187 #ifdef EPROGRAMNAME
1188     char *title = EPROGRAMNAME;
1189 #else
1190     char *title = "Electric";
1191 #endif
1192 #ifndef MACOS
1193     parentWidget()->setIcon( gra->programicon );
1194 #endif
1195     (void)sprintf(gra_localstring, _("%s Messages"), title);
1196     parentWidget()->setCaption( gra_localstring );
1197     (void)strcpy(gra_localstring, _("Messages"));
1198     parentWidget()->setIconText( gra_localstring );
1199 }
1200 
eventFilter(QObject * watched,QEvent * e)1201 bool EMessages::eventFilter( QObject *watched, QEvent *e )
1202 {
1203     if (e->type () == QEvent::KeyPress) {
1204         QKeyEvent *ke = (QKeyEvent *) e;
1205 		if (watched == line && (ke->state() & ControlButton) && ke->key() == Key_D &&
1206 			line->text().isEmpty()) {
1207 			stopped = TRUE;
1208 			lineEntered();
1209 			return TRUE;
1210 		}
1211 		if (watched == scroll && ke->key() == Key_Space) ke->ignore ();
1212     } else if (e->type () == QEvent::Close) {
1213 		if (watched == parentWidget())
1214 		{
1215 			ttyputerr(_("Cannot delete the messages window"));
1216 			return TRUE;
1217 		}
1218 	}
1219     return QVBox::eventFilter( watched, e );
1220 }
1221 
1222 #if LANGTCL
gra_initializetcl(void)1223 INTBIG gra_initializetcl(void)
1224 {
1225 	INTBIG err;
1226 	char *newArgv[2];
1227 
1228 	/* set the program name/path */
1229 	newArgv[0] = "Electric";
1230 	newArgv[1] = NULL;
1231 	(void)Tcl_FindExecutable(newArgv[0]);
1232 
1233 	gra_tclinterp = Tcl_CreateInterp();
1234 	if (gra_tclinterp == 0) error(_("from Tcl_CreateInterp"));
1235 
1236 	/* tell Electric the TCL interpreter handle */
1237 	el_tclinterpreter(gra_tclinterp);
1238 
1239 	/* Make command-line arguments available in the Tcl variables "argc" and "argv" */
1240 	Tcl_SetVar(gra_tclinterp, "argv", "", TCL_GLOBAL_ONLY);
1241 	Tcl_SetVar(gra_tclinterp, "argc", "0", TCL_GLOBAL_ONLY);
1242 	Tcl_SetVar(gra_tclinterp, "argv0", "electric", TCL_GLOBAL_ONLY);
1243 
1244 	/* Set the "tcl_interactive" variable */
1245 	Tcl_SetVar(gra_tclinterp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
1246 
1247 	/* initialize the interpreter */
1248 	err = Tcl_Init(gra_tclinterp);
1249 	if (err != TCL_OK) error(_("(from Tcl_Init) %s"), gra_tclinterp->result);
1250 	return(err);
1251 }
1252 #endif
1253 
1254 /*
1255  * Routine to establish the library directories from the environment.
1256  */
setupenvironment(void)1257 void setupenvironment(void)
1258 {
1259 	REGISTER char *pt, *buf;
1260 	REGISTER INTBIG len, filestatus;
1261 	REGISTER void *infstr;
1262 
1263 #ifdef ETRACE
1264 	etrace(GTRACE, "{ setupenvironment: us_tool->USER_machine\n");
1265 #endif
1266 
1267 	/* set machine name */
1268 	nextchangequiet();
1269 #ifdef MACOSX
1270 	(void)setval((INTBIG)us_tool, VTOOL, "USER_machine",
1271 		(INTBIG)"MacintoshX", VSTRING|VDONTSAVE);
1272 #endif
1273 #ifdef WIN32
1274 	(void)setval((INTBIG)us_tool, VTOOL, "USER_machine",
1275 		(INTBIG)"Windows", VSTRING|VDONTSAVE);
1276 #endif
1277 #ifdef ONUNIX
1278 	(void)setval((INTBIG)us_tool, VTOOL, "USER_machine",
1279 		(INTBIG)"UNIX", VSTRING|VDONTSAVE);
1280 #endif
1281 
1282 	pt = getenv("ELECTRIC_LIBDIR");
1283 	if (pt != NULL)
1284 	{
1285 		/* environment variable ELECTRIC_LIBDIR is set: use it */
1286 		buf = (char *)emalloc(strlen(pt)+5, el_tempcluster);
1287 		if (buf == 0)
1288 		{
1289 			fprintf(stderr, _("Cannot make environment buffer\n"));
1290 			exitprogram();
1291 		}
1292 		strcpy(buf, pt);
1293 		if (buf[strlen(buf)-1] != '/') strcat(buf, "/");
1294 		(void)allocstring(&el_libdir, buf, db_cluster);
1295 		efree(buf);
1296 #ifdef ETRACE
1297 		etrace(GTRACE, "} setupenvironment: el_libdir = %s\n", el_libdir);
1298 #endif
1299 		return;
1300 	}
1301 
1302 	/* try the #defined library directory */
1303 	infstr = initinfstr();
1304 	if (LIBDIR[0] != '/') addstringtoinfstr(infstr, currentdirectory());
1305 	addstringtoinfstr(infstr, LIBDIR);
1306 	addstringtoinfstr(infstr, CADRCFILENAME);
1307 	pt = returninfstr(infstr);
1308 #ifdef ETRACE
1309 	etrace(GTRACE, "   setupenvironment: trying %s\n", pt);
1310 #endif
1311 	filestatus = fileexistence(pt);
1312 	if (filestatus == 1 || filestatus == 3)
1313 	{
1314 		len = strlen(pt);
1315 		pt[len-strlen(CADRCFILENAME)] = 0;
1316 		(void)allocstring(&el_libdir, pt, db_cluster);
1317 #ifdef ETRACE
1318 		etrace(GTRACE, "} setupenvironment: el_libdir = %s\n", el_libdir);
1319 #endif
1320 		return;
1321 	}
1322 
1323 	/* try the current location (look for "lib") */
1324 	infstr = initinfstr();
1325 	addstringtoinfstr(infstr, currentdirectory());
1326 	addstringtoinfstr(infstr, "lib/");
1327 	addstringtoinfstr(infstr, CADRCFILENAME);
1328 	pt = returninfstr(infstr);
1329 #ifdef ETRACE
1330 	etrace(GTRACE, "   setupenvironment: trying %s\n", pt);
1331 #endif
1332 	filestatus = fileexistence(pt);
1333 	if (filestatus == 1 || filestatus == 3)
1334 	{
1335 		len = strlen(pt);
1336 		pt[len-strlen(CADRCFILENAME)] = 0;
1337 		(void)allocstring(&el_libdir, pt, db_cluster);
1338 #ifdef ETRACE
1339 		etrace(GTRACE, "} setupenvironment: el_libdir = %s\n", el_libdir);
1340 #endif
1341 		return;
1342 	}
1343 
1344 	/* no environment, #define, or current directory: look for ".cadrc" */
1345 #ifdef ETRACE
1346 	etrace(GTRACE, "   setupenvironment: trying %s\n", CADRCFILENAME);
1347 #endif
1348 	filestatus = fileexistence(CADRCFILENAME);
1349 	if (filestatus == 1 || filestatus == 3)
1350 	{
1351 		/* found ".cadrc" in current directory: use that */
1352 		(void)allocstring(&el_libdir, currentdirectory(), db_cluster);
1353 #ifdef ETRACE
1354 		etrace(GTRACE, "} setupenvironment: el_libdir = %s\n", el_libdir);
1355 #endif
1356 		return;
1357 	}
1358 
1359 	/* look for "~/.cadrc" */
1360 	infstr = initinfstr();
1361 	formatinfstr(infstr, "~/%s", CADRCFILENAME);
1362 	pt = truepath(returninfstr(infstr));
1363 #ifdef ETRACE
1364 	etrace(GTRACE, "   setupenvironment: trying %s\n", pt);
1365 #endif
1366 	filestatus = fileexistence(pt);
1367 	if (filestatus == 1 || filestatus == 3)
1368 	{
1369 		(void)allocstring(&el_libdir, pt, db_cluster);
1370 #ifdef ETRACE
1371 		etrace(GTRACE, "} setupenvironment: el_libdir = %s\n", el_libdir);
1372 #endif
1373 		return;
1374 	}
1375 
1376 	ttyputerr(_("Warning: cannot find '%s' startup file"), CADRCFILENAME);
1377 	(void)allocstring(&el_libdir, ".", db_cluster);
1378 #ifdef ETRACE
1379 	etrace(GTRACE, "} setupenvironment: el_libdir = %s\n", el_libdir);
1380 #endif
1381 }
1382 
setlibdir(char * libdir)1383 void setlibdir(char *libdir)
1384 {
1385 	REGISTER void *infstr;
1386 
1387 	infstr = initinfstr();
1388 	if (libdir[0] != '/') addstringtoinfstr(infstr, currentdirectory());
1389 	addstringtoinfstr(infstr, libdir);
1390 	if (libdir[strlen(libdir)-1] != DIRSEP) addtoinfstr(infstr, DIRSEP);
1391 	(void)reallocstring(&el_libdir, returninfstr(infstr), db_cluster);
1392 #ifdef ETRACE
1393 	etrace(GTRACE, "{}setlibdir: el_libdir = %s\n", el_libdir);
1394 #endif
1395 }
1396 
1397 /******************** TERMINATION ********************/
1398 
~EApplication()1399 EApplication::~EApplication()
1400 {
1401 	REGISTER INTBIG i;
1402 
1403 	/* deallocate font cache */
1404 	gra_termfaces();
1405 
1406 #ifdef USEMDI
1407 	/*???*/
1408 #else
1409 	if (messages) delete messages->parentWidget();
1410 #endif
1411 
1412 	gra_termgraph();
1413 
1414 	killstringarray(gra_fileliststringarray);
1415 
1416 	/* free printer list */
1417 	for(i=0; i<gra_printerlistcount; i++)
1418 		efree((char *)gra_printerlist[i]);
1419 	if (gra_printerlisttotal > 0) efree((char *)gra_printerlist);
1420 }
1421 
termgraphics(void)1422 void termgraphics(void)
1423 {
1424 #ifdef ETRACE
1425 	etrace(GTRACE, "{}termgraphics\n");
1426 #endif
1427     delete gra;
1428     gra = 0;
1429 }
1430 
exitprogram(void)1431 void exitprogram(void)
1432 {
1433 	exit(0);
1434 }
1435 
1436 /******************** WINDOW CONTROL ********************/
1437 
1438 /*
1439  * These routines implement multiple windows on the display (each display window
1440  * is called a "windowframe".  Currently these routines are unimplemented.
1441  */
1442 
newwindowframe(BOOLEAN floating,RECTAREA * r)1443 WINDOWFRAME *newwindowframe(BOOLEAN floating, RECTAREA *r)
1444 {
1445 	WINDOWFRAME *wf, *oldlisthead;
1446 
1447 #ifdef ETRACE
1448 	etrace(GTRACE, "{ newwindowframe: floating=%d", floating);
1449 	if (r != NULL) etrace(GTRACE_CONT, " r=%d,%d %d,%d", r->top, r->left, r->bottom, r->right);
1450 	etrace(GTRACE_CONT, "\n");
1451 #else
1452 	Q_UNUSED( r );
1453 #endif
1454 
1455 	/* allocate one */
1456 	wf = (WINDOWFRAME *)emalloc((sizeof (WINDOWFRAME)), us_tool->cluster);
1457 	if (wf == 0) return(NOWINDOWFRAME);
1458 	wf->numvar = 0;
1459 	wf->windindex = gra_windowframeindex++;
1460 
1461 	/* insert window-frame in linked list */
1462 	oldlisthead = el_firstwindowframe;
1463 	wf->nextwindowframe = el_firstwindowframe;
1464 	el_firstwindowframe = wf;
1465 
1466 	/* load an editor window into this frame */
1467 	if (gra_buildwindow(QApplication::desktop(), wf, floating) != 0)
1468 	{
1469 		efree((char *)wf);
1470 		el_firstwindowframe = oldlisthead;
1471 #ifdef ETRACE
1472 		etrace(GTRACE, "} newwindowframe: failed\n");
1473 #endif
1474 		return(NOWINDOWFRAME);
1475 	}
1476 
1477 	/* remember that this is the current window frame */
1478 	if (!floating) el_curwindowframe = wf;
1479 
1480 #ifdef ETRACE
1481 	etrace(GTRACE, "} newwindowframe: wf=%d swid=%d shei=%d\n",
1482 	       wf->windindex, wf->swid, wf->shei);
1483 #endif
1484 	return(wf);
1485 }
1486 
killwindowframe(WINDOWFRAME * owf)1487 void killwindowframe(WINDOWFRAME *owf)
1488 {
1489 	WINDOWFRAME *wf, *lastwf;
1490 
1491 #ifdef ETRACE
1492 	etrace(GTRACE, "{}killwindowframe: owf=%d gra_windowbeingdeleted=%d\n",
1493 	       owf->windindex, gra_windowbeingdeleted);
1494 #endif
1495 
1496 	/* don't do this if window is being deleted from another place */
1497 	if (gra_windowbeingdeleted != 0) return;
1498 
1499 	/* kill the actual window, that will remove the frame, too */
1500 #ifdef USEMDI
1501 	/*??*/
1502 #else
1503 	delete owf->draw->parentWidget();
1504 #endif
1505 
1506 	/* ind this frame in the list */
1507 	lastwf = NOWINDOWFRAME;
1508 	for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
1509 	{
1510 		if (wf == owf) break;
1511 		lastwf = wf;
1512 	}
1513 	if (wf == NOWINDOWFRAME) return;
1514 	if (lastwf == NOWINDOWFRAME) el_firstwindowframe = owf->nextwindowframe; else
1515 		lastwf->nextwindowframe = owf->nextwindowframe;
1516 	if (el_curwindowframe == owf) el_curwindowframe = NOWINDOWFRAME;
1517 
1518 	efree((char *)owf);
1519 }
1520 
movedisplay(void)1521 void movedisplay(void)
1522 {
1523 #if 1
1524 	WINDOWFRAME *wf = getwindowframe(1);
1525 	if (wf == NOWINDOWFRAME) return;
1526 #  ifdef ETRACE
1527 	etrace(GTRACE, "{ movedisplay: wf->windindex=%d\n",
1528 		wf->windindex);
1529 #  endif
1530 	QWidget *qwin = wf->draw->parentWidget();
1531 	QWidget *newDesktop;
1532 	QDesktopWidget *desktop = QApplication::desktop();
1533 	newDesktop = desktop->screen( (desktop->screenNumber(qwin) + 1) % desktop->numScreens() );
1534 	qwin->deleteLater();
1535 	qwin = NULL;
1536 	if (gra_buildwindow(newDesktop, wf, wf->floating) != 0)
1537 	  ttyputerr(_("Problem moving the display"));
1538 
1539 	/* redisplay */
1540 	us_drawmenu(1, wf);
1541 	us_redostatus(wf);
1542 	us_endbatch();
1543 #  ifdef ETRACE
1544 	etrace(GTRACE, "} movedisplay: wf->windindex=%d\n",
1545 		wf->windindex);
1546 #  endif
1547 #else
1548 	ttyputmsg(_("(Display move works only with Qt version 3\n"));
1549 #endif
1550 }
1551 
getwindowframe(BOOLEAN canfloat)1552 WINDOWFRAME *getwindowframe(BOOLEAN canfloat)
1553 {
1554 #ifdef ETRACE
1555 	etrace(GTRACE, "{}getwindowframe: canfloat=%d el_curwindowframe=%#x windindex=%d\n",
1556 	       canfloat, el_curwindowframe,
1557 	       el_curwindowframe != NOWINDOWFRAME ? el_curwindowframe->windindex : -1);
1558 #else
1559 	Q_UNUSED( canfloat );
1560 #endif
1561 	return(el_curwindowframe);
1562 }
1563 
1564 /*
1565  * routine to return size of window "win" in "wid" and "hei"
1566  */
getwindowframesize(WINDOWFRAME * wf,INTBIG * wid,INTBIG * hei)1567 void getwindowframesize(WINDOWFRAME *wf, INTBIG *wid, INTBIG *hei)
1568 {
1569 	*wid = wf->swid;
1570 	*hei = wf->shei;
1571 }
1572 
1573 /*
1574  * Routine to get the extent of the messages window.
1575  */
getmessagesframeinfo(INTBIG * top,INTBIG * left,INTBIG * bottom,INTBIG * right)1576 void getmessagesframeinfo(INTBIG *top, INTBIG *left, INTBIG *bottom, INTBIG *right)
1577 {
1578     QRect geom = gra->messages->parentWidget()->geometry();
1579     *top = geom.top();
1580     *left = geom.left();
1581     *bottom = geom.bottom();
1582     *right = geom.right();
1583 #ifdef ETRACE
1584 	etrace(GTRACE, "{}getmessagesframeinfo: top=%d left=%d bottom=%d right=%d\n",
1585 	       *top, *left, *bottom, *right);
1586 #endif
1587 }
1588 
1589 /*
1590  * Routine to set the size and position of the messages window.
1591  */
setmessagesframeinfo(INTBIG top,INTBIG left,INTBIG bottom,INTBIG right)1592 void setmessagesframeinfo(INTBIG top, INTBIG left, INTBIG bottom, INTBIG right)
1593 {
1594 #ifdef ETRACE
1595 	etrace(GTRACE, "{}setmessagesframeinfo: top=%d left=%d bottom=%d right=%d\n",
1596 	       top, left, bottom, right);
1597 #endif
1598     QRect geom( QPoint( left, top ) , QPoint( right, bottom ) );
1599     gra->messages->parentWidget()->setGeometry( geom );
1600 }
1601 
sizewindowframe(WINDOWFRAME * wf,INTBIG wid,INTBIG hei)1602 void sizewindowframe(WINDOWFRAME *wf, INTBIG wid, INTBIG hei)
1603 {
1604 	static WINDOWFRAME *lastwf = 0;
1605 	static INTBIG lastwid, lasthei, repeat;
1606 
1607 #ifdef ETRACE
1608 	etrace(GTRACE, "{ sizewindowframe: windindex=%d wid=%d hei=%d\n",
1609 	       wf->windindex, wid, hei);
1610 #endif
1611 	if (wid == wf->draw->parentWidget()->width() && hei == wf->draw->parentWidget()->height())
1612 	{
1613 #ifdef ETRACE
1614 		etrace(GTRACE, "} sizewindowframe: nothing to do\n");
1615 #endif
1616 		return;
1617 	}
1618 	if (wf == lastwf && wid == lastwid && hei == lasthei)
1619 	{
1620 		repeat++;
1621 		if (repeat > 2)
1622 		{
1623 #ifdef ETRACE
1624 			etrace(GTRACE, "} sizewindowframe: failed repeat=%d\n", repeat);
1625 #endif
1626 			return;
1627 		}
1628 	} else
1629 	{
1630 		lastwf = wf;   lastwid = wid;   lasthei = hei;   repeat = 1;
1631 	}
1632 	gra_internalchange = ticktime();
1633 #ifdef ETRACE
1634 	etrace(GTRACE, "  sizewindowframe: resize to %d %d\n", wid, hei);
1635 #endif
1636 	wf->draw->parentWidget()->resize(wid, hei);
1637 #ifdef ETRACE
1638 	etrace(GTRACE, "} sizewindowframe: done\n");
1639 #endif
1640 }
1641 
movewindowframe(WINDOWFRAME * wf,INTBIG left,INTBIG top)1642 void movewindowframe(WINDOWFRAME *wf, INTBIG left, INTBIG top)
1643 {
1644 #ifdef ETRACE
1645 	etrace(GTRACE, "{}movewindowframe: windindex=%d left=%d top=%d\n",
1646 	       wf->windindex, left, top);
1647 #endif
1648 #ifdef MACOS
1649 	/* allow for menubar */
1650 	if (wf->floating != 0 && top < WMTOPBORDERMAC) top = WMTOPBORDERMAC;
1651 #endif
1652 	if (left == wf->draw->parentWidget()->x() && top == wf->draw->parentWidget()->y()) return;
1653 	gra_internalchange = ticktime();
1654 	wf->draw->parentWidget()->move(left, top);
1655 }
1656 
1657 /*
1658  * Routine to close the messages window if it is in front.  Returns true if the
1659  * window was closed.
1660  */
closefrontmostmessages(void)1661 BOOLEAN closefrontmostmessages(void)
1662 {
1663 #ifdef ETRACE
1664 	etrace(GTRACE, "{}closefrontmostmessages:\n");
1665 #endif
1666 
1667 	return(FALSE);
1668 }
1669 
1670 /*
1671  * Routine to bring window "wf" to the front.
1672  */
bringwindowtofront(WINDOWFRAME * wf)1673 void bringwindowtofront(WINDOWFRAME *wf)
1674 {
1675 #ifdef ETRACE
1676 	etrace(GTRACE, "{}bringwindowtofront: windindex\n", wf->windindex);
1677 #endif
1678 	wf->draw->parentWidget()->raise();
1679 	wf->draw->setFocus();
1680 }
1681 
1682 /*
1683  * Routine to organize the windows according to "how" (0: tile horizontally,
1684  * 1: tile vertically, 2: cascade).
1685  */
adjustwindowframe(INTBIG how)1686 void adjustwindowframe(INTBIG how)
1687 {
1688 #ifdef ETRACE
1689 	etrace(GTRACE, "{ adjustwindowframe: how=%d\n", how);
1690 #endif
1691 
1692 	gra_adjustwindowframeon(how);
1693 
1694 #ifdef ETRACE
1695 	etrace(GTRACE, "} adjustwindowframe:\n");
1696 #endif
1697 }
1698 
gra_adjustwindowframeon(INTSML how)1699 void gra_adjustwindowframeon(INTSML how)
1700 {
1701 	RECTAREA r, wr;
1702 	REGISTER INTBIG children, child, sizex, sizey, scr;
1703 	REGISTER WINDOWFRAME *wf, *compmenu;
1704 
1705 	/* loop through the screens */
1706 	for(scr=0; scr<gra->desktop()->numScreens(); scr++)
1707 	{
1708 		/* determine area for windows */
1709 		QRect qr = gra->desktop()->screenGeometry(scr);
1710 		r.left = qr.left();   r.right = qr.right();
1711 #ifdef MACOSX
1712 		r.top = qr.top() + WMTOPBORDERMAC;
1713 #else
1714 		r.top = qr.top();
1715 #endif
1716 		r.bottom = qr.bottom();
1717 
1718 		/* figure out how many windows need to be rearranged */
1719 		children = 0;
1720 		compmenu = 0;
1721 		for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
1722 		{
1723 			if (!gra_onthiswindow(wf->draw->parentWidget(), &r)) continue;
1724 			if (wf->floating == 0) children++; else
1725 				compmenu = wf;
1726 		}
1727 		if (children <= 0) return;
1728 
1729 		if (compmenu != NULL)
1730 		{
1731 			/* remove component menu from area of tiling */
1732 			if (gra_onthiswindow(compmenu->draw->parentWidget(), &r))
1733 				gra_removewindowextent(&r, compmenu->draw->parentWidget());
1734 		}
1735 		if (gra->messages != 0)
1736 		{
1737 			/* remove messages menu from area of tiling */
1738 			if (gra_onthiswindow(gra->messages->parentWidget(), &r))
1739 				gra_removewindowextent(&r, gra->messages->parentWidget());
1740 		}
1741 
1742 		/* rearrange the windows */
1743 		child = 0;
1744 		for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
1745 		{
1746 			if (!gra_onthiswindow(wf->draw->parentWidget(), &r)) continue;
1747 			if (wf->floating != 0) continue;
1748 			switch (how)
1749 			{
1750 				case 0:		/* tile horizontally */
1751 					wr.left = r.left;
1752 					wr.right = r.right;
1753 					sizey = (r.bottom - r.top) / children;
1754 					wr.top = r.top + child*sizey;
1755 					wr.bottom = wr.top + sizey;
1756 					break;
1757 				case 1:		/* tile vertically */
1758 					wr.top = r.top;
1759 					wr.bottom = r.bottom;
1760 					sizex = (r.right - r.left) / children;
1761 					wr.left = r.left + child*sizex;
1762 					wr.right = wr.left + sizex;
1763 					break;
1764 				case 2:		/* cascade */
1765 					sizex = (r.right - r.left) / children / 2;
1766 					sizey = (r.bottom - r.top) / children / 2;
1767 					wr.left = r.left + child*sizex;
1768 					wr.right = wr.left + (r.right-r.left)/2;
1769 					wr.top = r.top + child*sizey;
1770 					wr.bottom = wr.top + (r.bottom-r.top)/2;
1771 					break;
1772 			}
1773 #ifdef MACOS
1774 			wr.left += 1;
1775 			wr.bottom -= 23;
1776 #else
1777 			wr.bottom -= WMTOPBORDER;
1778 #endif
1779 			sizewindowframe(wf, wr.right-wr.left, wr.bottom-wr.top);
1780 			movewindowframe(wf, wr.left, wr.top);
1781 			child++;
1782 		}
1783 	}
1784 }
1785 
1786 /*
1787  * Helper routine to determine whether window "window" is on the display bounded by "left",
1788  * "right", "top" and "bottom".  Returns true if so.
1789  */
gra_onthiswindow(QWidget * wnd,RECTAREA * r)1790 BOOLEAN gra_onthiswindow(QWidget *wnd, RECTAREA *r)
1791 {
1792 	REGISTER INTBIG pixels, onpixels;
1793 
1794     QRect er = wnd->geometry();
1795 
1796 	pixels = (er.right() - er.left()) * (er.bottom() - er.top());
1797 	if (er.left() > r->right || er.right() < r->left ||
1798 		er.top() > r->bottom || er.bottom() < r->top) return(FALSE);
1799 	if (er.left() < r->left) er.rLeft() = r->left;
1800 	if (er.right() > r->right) er.rRight() = r->right;
1801 	if (er.top() < r->top) er.rTop() = r->top;
1802 	if (er.bottom() > r->bottom) er.rBottom() = r->bottom;
1803 	onpixels = (er.right() - er.left()) * (er.bottom() - er.top());
1804 	if (onpixels * 2 >= pixels) return(TRUE);
1805 	return(FALSE);
1806 }
1807 
1808 /*
1809  * Helper routine to remove the location of window "wnd" from the rectangle "r".
1810  */
gra_removewindowextent(RECTAREA * r,QWidget * wnd)1811 void gra_removewindowextent(RECTAREA *r, QWidget *wnd)
1812 {
1813     QRect er = wnd->frameGeometry();
1814 
1815     if (er.width() > er.height())
1816     {
1817 	    /* horizontal occluding window */
1818 	    if (er.bottom() - r->top < r->bottom - er.top())
1819 	    {
1820 		    /* occluding window on top */
1821 		    r->top = er.bottom();
1822 	    } else
1823 	    {
1824 		    /* occluding window on bottom */
1825 		    r->bottom = er.top();
1826 	    }
1827     } else
1828     {
1829 	    /* vertical occluding window */
1830 	    if (er.right() - r->left < r->right - er.left())
1831 	    {
1832 		    /* occluding window on left */
1833 		    r->left = er.right();
1834 	    } else
1835 	    {
1836 		    /* occluding window on right */
1837 		    r->right = er.left();
1838 	    }
1839     }
1840 }
1841 
getpaletteparameters(INTBIG * wid,INTBIG * hei,INTBIG * palettewidth)1842 void getpaletteparameters(INTBIG *wid, INTBIG *hei, INTBIG *palettewidth)
1843 {
1844 #ifdef USEMDI
1845 	*wid = gra->mw->ws->width();
1846 	*hei = gra->mw->ws->height();
1847 #else
1848 	*wid = gra->desktop()->width() - WMLEFTBORDER;
1849 	*hei = gra->desktop()->height() - WMTOPBORDER;
1850 #endif
1851 	*palettewidth = PALETTEWIDTH;
1852 #ifdef ETRACE
1853 	etrace(GTRACE, "{}getpaletteparameters: wid=%d hei=%d palettewidth=%d\n",
1854 	       *wid, *hei, *palettewidth);
1855 #endif
1856 }
1857 
1858 /*
1859  * Routine called when the component menu has moved to a different location
1860  * on the screen (left/right/top/bottom).  Resets local state of the position.
1861  */
resetpaletteparameters(void)1862 void resetpaletteparameters(void)
1863 {
1864 #ifdef ETRACE
1865 	etrace(GTRACE, "{}resetpaletteparameters:\n");
1866 #endif
1867 }
1868 
GraphicsDraw(QWidget * parent)1869 GraphicsDraw::GraphicsDraw( QWidget *parent )
1870   : QWidget( parent, "draw", WRepaintNoErase )
1871 {
1872     setMouseTracking( TRUE );
1873     setFocusPolicy( QWidget::StrongFocus );
1874 	metaheld = false;
1875 }
1876 
eventFilter(QObject * watched,QEvent * e)1877 bool GraphicsDraw::eventFilter( QObject *watched, QEvent *e )
1878 {
1879     if (e->type () == QEvent::Close) {
1880 		if (watched == parentWidget())
1881 		{
1882 #ifdef ETRACE
1883 			etrace(GTRACE, "{ GraphicsDraw::eventFilter::Close %s\n", stateNames[gra_state]);
1884 #endif
1885 			/* queue this frame for deletion */
1886 			gra_deletethisframe = wf;
1887 			gra->toolTimeSlice();
1888 #ifdef ETRACE
1889 			etrace(GTRACE, "} GraphicsDraw::eventFilter::Close\n");
1890 #endif
1891 			return TRUE;
1892 		}
1893 	}
1894     return QWidget::eventFilter( watched, e );
1895 }
1896 
1897 #ifdef DOUBLESELECT
1898 static BOOLEAN activationChanged = FALSE;
1899 static UINTBIG oldActivationTick = 0;
1900 #  define ACTIVATION_TICKS 10
1901 #endif
windowActivationChange(bool oldActive)1902 void GraphicsDraw::windowActivationChange( bool oldActive )
1903 {
1904 #ifdef DOUBLESELECT
1905 	//ttyputmsg(M_("windowActivationChange %s%d %d %ld"), isActiveWindow()?"+":"-", oldActive, wf->windindex, ticktime());
1906 	if ( oldActive )
1907 	{
1908 		gra->activationChange();
1909 	} else
1910     {
1911 		gra_setcurrentwindowframe(wf);
1912 		activationChanged = (ticktime() - oldActivationTick > ACTIVATION_TICKS);
1913 /*		ttyputmsg(M_("dt=%ld"), ticktime() - oldActivationTick); */
1914 	}
1915 #else
1916 	if (isActiveWindow())
1917 		gra_setcurrentwindowframe(wf);
1918 #endif
1919 }
1920 
windowActivationChange(bool oldActive)1921 void EMessages::windowActivationChange( bool oldActive )
1922 {
1923 #ifdef DOUBLESELECT
1924 	if ( oldActive )
1925 	{
1926 		gra->activationChange();
1927 	}
1928 #else
1929 	Q_UNUSED( oldActive );
1930 #endif
1931 }
1932 
1933 #ifdef DOUBLESELECT
activationChange()1934 void EApplication::activationChange()
1935 {
1936 	oldActivationTick = ticktime();
1937 }
1938 #endif
1939 
focusInEvent(QFocusEvent * e)1940 void GraphicsDraw::focusInEvent( QFocusEvent *e )
1941 {
1942 #ifdef ETRACE
1943     etrace(GTRACE, "{ GraphicsDraw::focusInEvent %s\n", stateNames[gra_state]);
1944 #endif
1945     QWidget::focusInEvent( e );
1946 #ifdef ETRACE
1947     etrace(GTRACE, "} GraphicsDraw::focusInEvent\n");
1948 #endif
1949 }
1950 
focusOutEvent(QFocusEvent * e)1951 void GraphicsDraw::focusOutEvent( QFocusEvent *e )
1952 {
1953 #ifdef ETRACE
1954     etrace(GTRACE, "{ GraphicsDraw::focusOutEvent %s\n", stateNames[gra_state]);
1955 #endif
1956     QWidget::focusOutEvent( e );
1957 #ifdef ETRACE
1958     etrace(GTRACE, "} GraphicsDraw::focusOutEvent\n");
1959 #endif
1960 }
1961 
keyPressEvent(QKeyEvent * e)1962 void GraphicsDraw::keyPressEvent( QKeyEvent *e )
1963 {
1964 #ifdef ETRACE
1965     etrace(GTRACE, "{ GraphicsDraw::keyPressEvent %s accepted=%d\n", stateNames[gra_state], e->isAccepted());
1966 #endif
1967 
1968     INTBIG special;
1969 	BOOLEAN keepon;
1970 
1971 	int state = gra->translatekey(e, &special);
1972     if (state != 0 || special != 0)
1973     {
1974         us_state |= DIDINPUT;
1975 		INTBIG cmd = state;
1976 		keepCursorPos( mapFromGlobal( QCursor::pos() ) );
1977 #ifdef ETRACE
1978 		etrace(GTRACE, "  GraphicsDraw::keyPressEvent: %s state=%#o cmd=%#o special=%#o DIDINPUT%d,%d\n",
1979 			stateNames[gra_state], state, cmd, special, gra_cursorx, gra_cursory );
1980 #endif
1981 
1982 		switch (gra_state)
1983 		{
1984 			case S_USER:
1985 #ifdef ETRACE
1986 				etrace(GTRACE, "{ us_oncommand: cmd=%#o\n", cmd);
1987 #endif
1988 				us_oncommand( cmd, special );
1989 				gra->toolTimeSlice();
1990 #ifdef ETRACE
1991 				etrace(GTRACE, "} us_oncommand\n");
1992 #endif
1993 				break;
1994 			case S_TRACK:
1995 #ifdef ETRACE
1996 				etrace(GTRACE, "  trackcursor { eachchar x=%d y=%d cmd=%#o\n", gra_cursorx, gra_cursory, cmd);
1997 #endif
1998 				keepon = (*gra->eachchar)(gra_cursorx, gra_cursory, cmd);
1999 				flushscreen();
2000 #ifdef ETRACE
2001 				etrace(GTRACE, "  trackcursor } eachchar: keepon=%d el_pleasestop=%d\n", keepon, el_pleasestop);
2002 #endif
2003 				if (keepon || el_pleasestop) gra->exit_loop();
2004 				break;
2005 			case S_MODAL:
2006 #ifdef ETRACE
2007 				etrace(GTRACE, "  modalloop { charhandler cmd=%#o special=%#o\n", cmd, special);
2008 #endif
2009 				keepon = (*gra->charhandler)(cmd, special);
2010 				flushscreen();
2011 #ifdef ETRACE
2012 				etrace(GTRACE, "  modalloop } charhandler: keepon=%d el_pleasestop=%d\n", keepon, el_pleasestop);
2013 #endif
2014 				if (keepon || el_pleasestop) gra->exit_loop();
2015 				break;
2016             default:
2017                 break;
2018 		}
2019 		e->accept();
2020 	}
2021 	/* Linux Meta key modifier does not come through in QKeyEvent->state() for some reason
2022 	   so we fake it by setting metaheld here, and unsetting it in KeyReleaseEvent */
2023 	else if ((e->key() == Key_Super_L) || (e->key() == Key_Super_R)) {
2024 		metaheld = true;
2025 #ifdef ETRACE
2026 		etrace(GTRACE, "  metaheld set to true");
2027 #endif
2028 	}
2029     else QWidget::keyPressEvent( e );
2030 #ifdef ETRACE
2031     etrace(GTRACE, "} GraphicsDraw::keyPressEvent accepted=%d\n", e->isAccepted());
2032 #endif
2033 }
2034 
keyReleaseEvent(QKeyEvent * e)2035 void GraphicsDraw::keyReleaseEvent( QKeyEvent *e )
2036 {
2037 #ifdef ETRACE
2038     etrace(GTRACE, "{ GraphicsDraw::keyReleaseEvent %s accepted=%d\n", stateNames[gra_state], e->isAccepted());
2039 #endif
2040 	/* Linux Meta key modifier does not come through in QKeyEvent->state() for some reason
2041 	   so we fake it by setting metaheld in KeyPressEvent, and unsetting it here */
2042 	if ((e->key() == Key_Super_L) || (e->key() == Key_Super_R)) {
2043 		metaheld = false;
2044 #ifdef ETRACE
2045 		etrace(GTRACE, "  metaheld set to false");
2046 #endif
2047 	}
2048 	else QWidget::keyReleaseEvent( e );
2049 #ifdef ETRACE
2050     etrace(GTRACE, "} GraphicsDraw::keyReleaseEvent accepted=%d\n", e->isAccepted());
2051 #endif
2052 }
2053 
2054 
gra_buildwindow(QWidget * desktop,WINDOWFRAME * wf,BOOLEAN floating)2055 INTSML gra_buildwindow(QWidget *desktop, WINDOWFRAME *wf, BOOLEAN floating)
2056 {
2057 	wf->floating = floating;
2058 	int x, y, width, height;
2059 
2060 	/* determine window position */
2061 #ifdef USEMDI
2062 	int screenw = gra->mw->ws->width();
2063 	int screenh = gra->mw->ws->height();
2064 #else
2065 	int screenw = desktop->width();
2066 	int screenh = desktop->height();
2067 #endif
2068 	if (!floating)
2069 	{
2070 		x = gra_editposx;
2071 		y = gra_editposy;
2072 		width = gra_editsizex;
2073 		height = gra_editsizey;
2074 		x += (gra_windownumber%5) * 40;
2075 		y += (gra_windownumber%5) * 40;
2076 		if (x + width > screenw)
2077 			width = screenw - x;
2078 		if (y + height > screenh)
2079 			height = screenh - y;
2080 		gra_windownumber++;
2081 	} else
2082 	{
2083 		x = 0;
2084 		y = 1;
2085 		width = PALETTEWIDTH;
2086 		height = screenh - 50;
2087 		gra_internalchange = ticktime();
2088 	}
2089 
2090 	/*
2091 	 * make top-level graphics widget
2092 	 */
2093 #ifdef USEMDI
2094 #ifdef ETRACE
2095 	etrace(GTRACE, "  gra_buildwindow: screenw=%d screenh=%d width=%d height=%d\n", screenw, screenh, width, height);
2096 #endif
2097 	wf->draw = new GraphicsDraw( gra->mw->ws );
2098 	wf->draw->wf = wf;
2099 
2100 	/* get window size and depth after creation */
2101 	wf->swid = wf->shei = -1;
2102 	wf->rowstart = 0;
2103 	QWidget *qwin = wf->draw->parentWidget();
2104 #ifdef ETRACE
2105 	etrace(GTRACE, "qwin->className=%s\n", qwin->className());
2106 #endif
2107 	gra->sendPostedEvents( qwin, QEvent::ChildInserted );
2108 	qwin = wf->draw->parentWidget();
2109 #ifdef ETRACE
2110 	etrace(GTRACE, "qwin->className=%s\n", qwin->className());
2111 #endif
2112 
2113 #else
2114 	EMainWindow *qwin = new EMainWindow( desktop, "GraphicsMainWindow", Qt::WType_TopLevel, !floating );
2115 	if (!floating) qwin->pulldownmenuload();
2116 	wf->draw = new GraphicsDraw( qwin );
2117 	wf->draw->wf = wf;
2118 	qwin->setCentralWidget( wf->draw );
2119 #endif
2120 
2121 	/* load window manager information */
2122 #ifndef MACOS
2123 	qwin->setIcon( gra->programicon );
2124 #endif
2125 	if (!floating) (void)strcpy(gra_localstring, _("Electric")); else
2126 		(void)strcpy(gra_localstring, _("Components"));
2127 	qwin->setCaption( gra_localstring );
2128 	qwin->setIconText( gra_localstring );
2129 
2130     qwin->installEventFilter( wf->draw );
2131 	qwin->setFocusProxy( wf->draw );
2132 	qwin->resize( width, height );
2133 	qwin->move( x, y );
2134 
2135 	/* get window size and depth after creation */
2136 	wf->swid = wf->shei = -1;
2137 	wf->rowstart = 0;
2138 #ifdef USEMDI
2139 	wf->draw->show();
2140 #endif
2141 	qwin->show();
2142 
2143 	/* reload cursor */
2144 	us_cursorstate = -1;
2145 	setdefaultcursortype(us_normalcursor);
2146 
2147 	/* fill the color map  */
2148 #if 0
2149 	us_getcolormap(el_curtech, COLORSDEFAULT, FALSE);
2150 #endif
2151 	gra_reloadmap();
2152 
2153 	return(0);
2154 }
2155 
2156 /******************** MISCELLANEOUS EXTERNAL ROUTINES ********************/
2157 
2158 /*
2159  * return nonzero if the capabilities in "want" are present
2160  */
graphicshas(INTBIG want)2161 BOOLEAN graphicshas(INTBIG want)
2162 {
2163 	BOOLEAN has = gra_graphicshas(want);
2164 #ifdef ETRACE
2165 	etrace(GTRACE, "{}graphicshas: want=%#o has=%d\n", want, has);
2166 #endif
2167 	return(has);
2168 }
2169 
gra_graphicshas(INTSML want)2170 static INTSML gra_graphicshas(INTSML want)
2171 {
2172 	if ((want & CANHAVENOWINDOWS) != 0) return(0);
2173 	return(1);
2174 }
2175 
2176 
2177 /*
2178  * Routine to make sound "sound".  If sounds are turned off, no
2179  * sound is made (unless "force" is TRUE)
2180  */
ttybeep(INTBIG sound,BOOLEAN force)2181 void ttybeep(INTBIG sound, BOOLEAN force)
2182 {
2183 #ifdef ETRACE
2184 	etrace(GTRACE, "{}ttybeep force=%d\n", force);
2185 #endif
2186 	if ((us_tool->toolstate & TERMBEEP) != 0 || force)
2187 	{
2188 		switch (sound)
2189 		{
2190 			case SOUNDBEEP:
2191 				QApplication::beep();
2192 				break;
2193 			case SOUNDCLICK:
2194 				if ((us_useroptions&NOEXTRASOUND) != 0) break;
2195 				if (QSound::available())
2196 					gra_clicksound->play();
2197 				break;
2198 		}
2199 	}
2200 }
2201 
2202 DIALOGITEM db_severeerrordialogitems[] =
2203 {
2204  /*  1 */ {0, {80,8,104,72}, BUTTON, N_("Exit")},
2205  /*  2 */ {0, {80,96,104,160}, BUTTON, N_("Save")},
2206  /*  3 */ {0, {80,184,104,256}, BUTTON, N_("Continue")},
2207  /*  4 */ {0, {8,8,72,256}, MESSAGE, ""}
2208 };
2209 DIALOG db_severeerrordialog = {{50,75,163,341}, N_("Fatal Error"), 0, 4, db_severeerrordialogitems, 0, 0};
2210 
2211 /* special items for the severe error dialog: */
2212 #define DSVE_EXIT      1		/* Exit (button) */
2213 #define DSVE_SAVE      2		/* Save (button) */
2214 #define DSVE_CONTINUE  3		/* Continue (button) */
2215 #define DSVE_MESSAGE   4		/* Error Message (stat text) */
2216 
error(char * s,...)2217 void error(char *s, ...)
2218 {
2219 	va_list ap;
2220 	char line[500];
2221 	REGISTER INTBIG itemHit, *curstate;
2222 	REGISTER INTBIG retval;
2223 	REGISTER LIBRARY *lib;
2224 	REGISTER void *dia;
2225 
2226 	/* disable any session logging */
2227 	if (us_logplay != NULL)
2228 	{
2229 		xclose(us_logplay);
2230 		us_logplay = NULL;
2231 	}
2232 
2233 	/* build the error message */
2234 	var_start(ap, s);
2235 	evsnprintf(line, 500, s, ap);
2236 	va_end(ap);
2237 #ifdef ETRACE
2238 	etrace(GTRACE, "{ error: line=<%s> us_logplay=NULL\n", line);
2239 #endif
2240 
2241 	/* print to stderr if graphics not initiaized */
2242 	if (gra == 0) {
2243 		fprintf(stderr, "Fatal Error: %s\n", line);
2244 #ifdef ETRACE
2245 		etrace(GTRACE, "} error stderr\n");
2246 #endif
2247 		return;
2248 	}
2249 
2250 	/* display the severe error dialog box */
2251 	dia = DiaInitDialog(&db_severeerrordialog);
2252 	if (dia == 0) return;
2253 
2254 	/* load the message */
2255 	DiaSetText(dia, DSVE_MESSAGE, line);
2256 
2257 	/* loop until done */
2258 	for(;;)
2259 	{
2260 		itemHit = DiaNextHit(dia);
2261 		if (itemHit == DSVE_EXIT) exitprogram();
2262 		if (itemHit == DSVE_CONTINUE) break;
2263 		if (itemHit == DSVE_SAVE)
2264 		{
2265 #ifdef ETRACE
2266 			etrace(GTRACE, "  error: saving libraries\n");
2267 #endif
2268 			/* save libraries: make sure that backups are kept */
2269 			curstate = io_getstatebits();
2270 			if ((curstate[0]&BINOUTBACKUP) == BINOUTNOBACK)
2271 			{
2272 				curstate[0] |= BINOUTONEBACK;
2273 				io_setstatebits(curstate);
2274 			}
2275 
2276 			/* save each modified library */
2277 			for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
2278 			{
2279 				if ((lib->userbits&HIDDENLIBRARY) != 0) continue;
2280 				if ((lib->userbits&(LIBCHANGEDMAJOR|LIBCHANGEDMINOR)) == 0) continue;
2281 
2282 				/* save the library in binary format */
2283 				makeoptionstemporary(lib);
2284 				retval = asktool(io_tool, "write", (INTBIG)lib, (INTBIG)"binary");
2285 				restoreoptionstate(lib);
2286 				if (retval != 0)
2287 				{
2288 #ifdef ETRACE
2289 					etrace(GTRACE, "} error: saving libraries failed\n");
2290 #endif
2291 					return;
2292 				}
2293 			}
2294 		}
2295 	}
2296 	DiaDoneDialog(dia);
2297 #ifdef ETRACE
2298 	etrace(GTRACE, "} error\n");
2299 #endif
2300 }
2301 
2302 /*
2303  * Routine to get the environment variable "name" and return its value.
2304  */
egetenv(char * name)2305 char *egetenv(char *name)
2306 {
2307 	char *value = getenv(name);
2308 #ifdef ETRACE
2309 	etrace(GTRACE, "{}getenv: name=%s value=<%s>\n", name, value != NULL ? value : "NULL");
2310 #endif
2311 	return(value);
2312 }
2313 
2314 /*
2315  * Routine to get the current language that Electric speaks.
2316  */
elanguage(void)2317 char *elanguage(void)
2318 {
2319 	char *lang;
2320 
2321 	lang = getenv("LANGUAGE");
2322 	if (lang == 0) lang = "en";
2323 	return(lang);
2324 }
2325 
2326 /*
2327  * Routine to run the string "command" in a shell.
2328  * Returns nonzero if the command cannot be run.
2329  */
esystem(char * command)2330 INTBIG esystem(char *command)
2331 {
2332 #ifdef ETRACE
2333 	etrace(GTRACE, "{}esystem: command=<%s>\n", command);
2334 #endif
2335 	system(command);
2336 	return(0);
2337 }
2338 
2339 /*
2340  * Routine to execute the program "program" with the arguments "args"
2341  */
eexec(char * program,char * args[])2342 void eexec(char *program, char *args[])
2343 {
2344 #ifdef ETRACE
2345 	char **arg;
2346 
2347 	etrace(GTRACE, "{}exec: program=<%s> args=", program);
2348 	for (arg = args; *arg != NULL; arg++)
2349 	{
2350 		etrace(GTRACE_CONT, " <%s>", *arg);
2351 	}
2352 	etrace(GTRACE_CONT, "\n");
2353 #endif
2354 	execvp(program, args);
2355 }
2356 
2357 /*
2358  * Routine to return the number of processors on this machine.
2359  */
enumprocessors(void)2360 INTBIG enumprocessors(void)
2361 {
2362 #ifdef ONUNIX
2363 	return(sysconf(_SC_NPROCESSORS_ONLN));
2364 #endif
2365 #ifdef MACOS
2366 	return(MPProcessors());
2367 #endif
2368 	return(1);
2369 }
2370 
2371 /*
2372  * Routine to create a new thread that calls "function" with "argument".
2373  */
enewthread(void * (* function)(void *),void * argument)2374 void enewthread(void* (*function)(void*), void *argument)
2375 {
2376 #ifdef HAVE_PTHREAD
2377 	pthread_t threadptr;
2378 
2379 	pthread_create(&threadptr, NULL, function, argument);
2380 #else
2381 	thread_t threadid;
2382 
2383 	if (thr_create(NULL, 0, function, argument, THR_BOUND, &threadid) != 0)
2384 		printf("Thread creation failed\n");
2385 #endif
2386 }
2387 
2388 /*
2389  * Routine that creates a mutual-exclusion object and returns it.
2390  */
emakemutex(void)2391 void *emakemutex(void)
2392 {
2393 #ifdef HAVE_PTHREAD
2394 	pthread_mutex_t *mutex;
2395 
2396 	mutex = (pthread_mutex_t *)calloc(1, sizeof (pthread_mutex_t));
2397 	pthread_mutex_init(mutex, NULL);
2398 	return((void *)mutex);
2399 #else
2400 	mutex_t *mutexid;
2401 
2402 	mutexid = calloc(1, sizeof (mutex_t));
2403 	mutex_init(mutexid, USYNC_THREAD, 0);
2404 	return((void *)mutexid);
2405 #endif
2406 }
2407 
2408 /*
2409  * Routine that locks mutual-exclusion object "vmutex".  If the object is already
2410  * locked, the routine blocks until it is unlocked.
2411  */
emutexlock(void * vmutex)2412 void emutexlock(void *vmutex)
2413 {
2414 #ifdef HAVE_PTHREAD
2415 	pthread_mutex_t *mutex;
2416 
2417 	mutex = (pthread_mutex_t *)vmutex;
2418 	pthread_mutex_lock(mutex);
2419 #else
2420 	mutex_t *mutexid;
2421 
2422 	mutexid = (mutex_t *)vmutex;
2423 	mutex_lock(mutexid);
2424 #endif
2425 }
2426 
2427 /*
2428  * Routine that unlocks mutual-exclusion object "vmutex".
2429  */
emutexunlock(void * vmutex)2430 void emutexunlock(void *vmutex)
2431 {
2432 #ifdef HAVE_PTHREAD
2433 	pthread_mutex_t *mutex;
2434 
2435 	mutex = (pthread_mutex_t *)vmutex;
2436 	pthread_mutex_unlock(mutex);
2437 #else
2438 	mutex_t *mutexid;
2439 
2440 	mutexid = (mutex_t *)vmutex;
2441 	mutex_unlock(mutexid);
2442 #endif
2443 }
2444 
2445 /*
2446  * Routine to determine the list of printers and return it.
2447  * The list terminates with a zero.
2448  */
eprinterlist(void)2449 char **eprinterlist(void)
2450 {
2451 	char **list;
2452 #ifdef ETRACE
2453 	char **p;
2454 
2455 	etrace(GTRACE, "{ eprinterlist:\n");
2456 #endif
2457 	list = gra_eprinterlist();
2458 #ifdef ETRACE
2459 	etrace(GTRACE, "} eprinterlist:");
2460 	for (p = list; *p != NULL; p++) etrace(GTRACE_CONT, " <%s>", *p);
2461 	etrace(GTRACE_CONT, "\n");
2462 #endif
2463 	return(list);
2464 }
2465 
gra_eprinterlist(void)2466 static char **gra_eprinterlist(void)
2467 {
2468 	static char *nulllplist[1];
2469 	INTBIG i;
2470 	char buf[200], *pt;
2471 	FILE *io;
2472 
2473 	/* remove former list */
2474 	for(i=0; i<gra_printerlistcount; i++)
2475 		efree((char *)gra_printerlist[i]);
2476 	gra_printerlistcount = 0;
2477 	nulllplist[0] = 0;
2478 
2479 	/* look for "/etc/printcap" */
2480 	io = fopen("/etc/printcap", "r");
2481 	if (io != 0)
2482 	{
2483 		for(;;)
2484 		{
2485 			if (xfgets(buf, 200, io)) break;
2486 			if (buf[0] == '#' || buf[0] == ' ' || buf[0] == '\t') continue;
2487 			for(pt = buf; *pt != 0; pt++)
2488 				if (*pt == ':') break;
2489 			if (*pt == 0) continue;
2490 			*pt = 0;
2491 			if (gra_addprinter(buf) != 0)
2492 				return(nulllplist);
2493 		}
2494 		fclose(io);
2495 		if (gra_printerlistcount <= 0) return(nulllplist);
2496 		return(gra_printerlist);
2497 	}
2498 
2499 	/* no file "/etc/printcap": try to run "lpget" */
2500 	QProcess lpget;
2501 	lpget.addArgument( "lpget" );
2502 	lpget.addArgument( "list" );
2503 	if ( !lpget.launch( QString::null ) )
2504 		return(nulllplist);
2505 	do
2506 	{
2507 		if (lpget.canReadLineStdout())
2508 		{
2509 			QString qstr = lpget.readLineStdout();
2510 			int pos = qstr.find(':');
2511 			if (pos < 0) continue;
2512 			qstr.remove( 0, pos + 1 );
2513 			char *str = EApplication::localize( qstr );
2514 			gra_addprinter( str );
2515 			continue;
2516 		}
2517 	} while( lpget.isRunning() );
2518 	if (gra_printerlistcount <= 0) return(nulllplist);
2519 	return(gra_printerlist);
2520 }
2521 
gra_addprinter(char * buf)2522 INTSML gra_addprinter(char *buf)
2523 {
2524 	char **newlist;
2525 	INTBIG i, j, newtotal;
2526 
2527 	if (strcmp(buf, "_default") == 0) return(0);
2528 	if (buf[0] == ' ' || buf[0] == '\t') return(0);
2529 
2530 	/* stop if it is already in the list */
2531 	for(i=0; i<gra_printerlistcount; i++)
2532 		if (strcmp(buf, gra_printerlist[i]) == 0) return(0);
2533 
2534 	/* make room in the list */
2535 	if (gra_printerlistcount >= gra_printerlisttotal-1)
2536 	{
2537 		newtotal = gra_printerlistcount + 10;
2538 		newlist = (char **)emalloc(newtotal * (sizeof (char *)), us_tool->cluster);
2539 		if (newlist == 0) return(1);
2540 		for(i=0; i<gra_printerlistcount; i++)
2541 			newlist[i] = gra_printerlist[i];
2542 		if (gra_printerlisttotal > 0) efree((char *)gra_printerlist);
2543 		gra_printerlist = newlist;
2544 		gra_printerlisttotal = newtotal;
2545 	}
2546 
2547 	/* insert into the list */
2548 	for(i=0; i<gra_printerlistcount; i++)
2549 		if (strcmp(buf, gra_printerlist[i]) < 0) break;
2550 	for(j=gra_printerlistcount; j>i; j--) gra_printerlist[j] = gra_printerlist[j-1];
2551 	gra_printerlist[i] = (char *)emalloc(strlen(buf)+1, us_tool->cluster);
2552 	strcpy(gra_printerlist[i], buf);
2553 	gra_printerlistcount++;
2554 	gra_printerlist[gra_printerlistcount] = 0;
2555 	return(0);
2556 }
2557 
2558 /******************** STATUS BAR ROUTINES ********************/
2559 
2560 /*
2561  * Routine to return the number of status lines on the display.
2562  */
ttynumstatuslines(void)2563 INTBIG ttynumstatuslines(void)
2564 {
2565 	return(MAXSTATUSLINES);
2566 }
2567 
2568 /*
2569  * Routine to free status field object "sf".
2570  */
ttyfreestatusfield(STATUSFIELD * sf)2571 void ttyfreestatusfield(STATUSFIELD *sf)
2572 {
2573 	INTSML i, j;
2574 	REGISTER WINDOWFRAME *wf;
2575 
2576 #ifdef ETRACE
2577 	etrace(GTRACE, "{}ttyfreestatusfield: %s\n", sf->label);
2578 #endif
2579 	for(i=0; i<gra_indicatorcount; i++)
2580 	{
2581 		if (gra_statusfields[i] != sf) continue;
2582 
2583 		/* remove the field */
2584 		efree(gra_statusfieldtext[i]);
2585 #ifdef USEMDI
2586 		gra->mw->removeStatusItem( i );
2587 #else
2588 		for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
2589 		{
2590 			if (wf->floating) continue;
2591 			EMainWindow *qwin = (EMainWindow*)wf->draw->parentWidget();
2592 			qwin->removeStatusItem( i );
2593 		}
2594 #endif
2595 
2596 		for(j=i+1; j<gra_indicatorcount; j++)
2597 		{
2598 			gra_statusfields[j-1] = gra_statusfields[j];
2599 			gra_statusfieldtext[j-1] = gra_statusfieldtext[j];
2600 		}
2601 		gra_indicatorcount--;
2602 	}
2603 
2604 	efree(sf->label);
2605 	efree((char *)sf);
2606 }
2607 
2608 /*
2609  * Routine to display "message" in the status "field" of window "frame" (uses all windows
2610  * if "frame" is zero).  If "cancrop" is false, field cannot be cropped and should be
2611  * replaced with "*" if there isn't room.
2612  */
ttysetstatusfield(WINDOWFRAME * wwf,STATUSFIELD * field,char * message,BOOLEAN cancrop)2613 void ttysetstatusfield(WINDOWFRAME *wwf, STATUSFIELD *field, char *message, BOOLEAN cancrop)
2614 {
2615 	INTSML len, i;
2616 	REGISTER WINDOWFRAME *wf;
2617 
2618 #ifdef ETRACE_
2619 	etrace(GTRACE, "{%cttysetstatusfield: wwf=%d field=%s message=<%s> cancrop=%d\n",
2620 	       field != 0 ? ' ' : '}',
2621 	       wwf != NOWINDOWFRAME ? wwf->windindex : -1,
2622 	       field != 0 ? field->label : "<NULL>",
2623 	       message != NULL ? message : "<NULL>",
2624 	       cancrop);
2625 #else
2626 	Q_UNUSED( cancrop );
2627 #endif
2628 
2629 	/* figure out which indicator this is */
2630 	if (field == 0) return;
2631 
2632 	/* if this is a title bar setting, do it now */
2633 	if (field->line == 0)
2634 	{
2635 		if (wwf == NOWINDOWFRAME) return;
2636 			/* should set title bar here */
2637 #ifdef EPROGRAMNAME
2638 		(void)strcpy(gra_localstring, EPROGRAMNAME);
2639 #else
2640 		(void)strcpy(gra_localstring, _("Electric"));
2641 #endif
2642 		if (strlen(message) > 0)
2643 		{
2644 			(void)strcat(gra_localstring, " (");
2645 			(void)strcat(gra_localstring, field->label);
2646 			(void)strcat(gra_localstring, message);
2647 			(void)strcat(gra_localstring, ")");
2648 		}
2649 		len = strlen(gra_localstring);
2650 		while (len > 0 && gra_localstring[len-1] == ' ') gra_localstring[--len] = 0;
2651 		wwf->draw->parentWidget()->setCaption( gra_localstring );
2652 		return;
2653 	}
2654 
2655 	/* ignore null fields */
2656 	if (*field->label == 0) return;
2657 
2658 	/* construct the status line */
2659 	len = strlen(field->label);
2660 	if (len + strlen(message) >= MAXLOCALSTRING)
2661 	{
2662 		strcpy(gra_localstring, field->label);
2663 		i = MAXLOCALSTRING - len - 1;
2664 		strncat(gra_localstring, message, i);
2665 		gra_localstring[MAXLOCALSTRING-1] = 0;
2666 	} else
2667 	{
2668 		sprintf(gra_localstring, "%s%s", field->label, message);
2669 	}
2670 	len = strlen(gra_localstring);
2671 	while (len > 0 && gra_localstring[len-1] == ' ') gra_localstring[--len] = 0;
2672 
2673 	/* see if this indicator is in the list */
2674 	for(i=0; i<gra_indicatorcount; i++)
2675 	{
2676 		if (gra_statusfields[i]->line != field->line ||
2677 			gra_statusfields[i]->startper != field->startper ||
2678 			gra_statusfields[i]->endper != field->endper) continue;
2679 
2680 		/* load the string */
2681 #ifdef USEMDI
2682 		gra->mw->changeStatusItem( i, gra_localstring );
2683 #else
2684 		for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
2685 		{
2686 			if (wf->floating) continue;
2687 			if (wwf != NOWINDOWFRAME && wwf != wf) continue;
2688 			EMainWindow *qwin = (EMainWindow*)wf->draw->parentWidget();
2689 			qwin->changeStatusItem( i, gra_localstring );
2690 		}
2691 #endif
2692         (void)reallocstring(&gra_statusfieldtext[i], gra_localstring, db_cluster);
2693         return;
2694 	}
2695 
2696 	/* not found: find where this field fits in the order */
2697 	(void)allocstring(&gra_statusfieldtext[i], gra_localstring, db_cluster);
2698 #ifdef USEMDI
2699 	gra->mw->addStatusItem( field->endper - field->startper, gra_localstring );
2700 #else
2701 	for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
2702 	{
2703 		if (wf->floating) continue;
2704 		EMainWindow *qwin = (EMainWindow*)wf->draw->parentWidget();
2705 		qwin->addStatusItem( field->endper - field->startper, gra_localstring );
2706 	}
2707 #endif
2708 	gra_statusfields[gra_indicatorcount++] = field;
2709 #ifdef ETRACE_
2710 	etrace(GTRACE, "} ttysetstatusfield\n");
2711 #endif
2712 }
2713 
2714 /*
2715  * Routine to force the module to return with some event so that the user interface will
2716  * relinquish control and let a slice happen.
2717  */
forceslice(void)2718 void forceslice(void)
2719 {
2720 }
2721 
2722 /******************** MESSAGES WINDOW ROUTINES ********************/
2723 
2724 /*
2725  * Routine to put the string "s" into the messages window.
2726  * Pops up the messages window if "important" is true.
2727  */
putmessagesstring(char * s,BOOLEAN important)2728 void putmessagesstring(char *s, BOOLEAN important)
2729 {
2730 #ifdef ETRACE
2731 	etrace(GTRACE, "{}putmessagesstring: <%s> important=%d\n", s, important);
2732 #endif
2733 	/* print to stderr if messages are not initiaized */
2734 	if (gra == 0 || gra->messages == 0) {
2735 		fprintf(stderr, "%s\n", s);
2736 		return;
2737 	}
2738 	gra->messages->putString( s, important );
2739 }
2740 
2741 /*
2742  * Routine to return the name of the key that ends a session from the messages window.
2743  */
getmessageseofkey(void)2744 char *getmessageseofkey(void)
2745 {
2746 #ifdef ETRACE
2747 	etrace(GTRACE, "{}getmessageseofkey: ^D\n");
2748 #endif
2749 	return("^D");
2750 }
2751 
getmessagesstring(char * prompt)2752 char *getmessagesstring(char *prompt)
2753 {
2754 #ifdef ETRACE
2755 	etrace(GTRACE, "{ getmessagesstring: prompt=<%s>\n", prompt);
2756 #endif
2757 	char *str = gra->messages->getString( prompt );
2758 #ifdef ETRACE
2759 	etrace(GTRACE, "} getmessagesstring: <%s> gra_state=%s\n",
2760 	       str ? str : "STOPPED", stateNames[gra_state]);
2761 #endif
2762 	return(str);
2763 }
2764 
2765 /*
2766  * routine to select fonts in the messages window
2767  */
setmessagesfont(void)2768 void setmessagesfont(void)
2769 {
2770 #ifdef ETRACE
2771 	etrace(GTRACE, "{ setmessagesfont\n");
2772 #endif
2773 	gra->messages->setFont();
2774 #ifdef ETRACE
2775 	etrace(GTRACE, "} setmessagesfont\n");
2776 #endif
2777 }
2778 
2779 /*
2780  * routine to cut text from the messages window if it is current.  Returns true
2781  * if sucessful.
2782  */
cutfrommessages(void)2783 BOOLEAN cutfrommessages(void)
2784 {
2785 #ifdef ETRACE
2786 	etrace(GTRACE, "{}cutrommessages: result=0\n");
2787 #endif
2788 	return(FALSE);
2789 }
2790 
2791 /*
2792  * routine to copy text from the messages window if it is current.  Returns true
2793  * if sucessful.
2794  */
copyfrommessages(void)2795 BOOLEAN copyfrommessages(void)
2796 {
2797 #ifdef ETRACE
2798 	etrace(GTRACE, "{}copyfrommessages: result=0\n");
2799 #endif
2800 	return(FALSE);
2801 }
2802 
2803 /*
2804  * routine to paste text to the messages window if it is current.  Returns true
2805  * if sucessful.
2806  */
pastetomessages(void)2807 BOOLEAN pastetomessages(void)
2808 {
2809 #ifdef ETRACE
2810 	etrace(GTRACE, "{}pastetomessages: result=0\n");
2811 #endif
2812 	return(FALSE);
2813 }
2814 
2815 /*
2816  * routine to get the contents of the system cut buffer
2817  */
getcutbuffer(void)2818 char *getcutbuffer(void)
2819 {
2820 	char *string;
2821 	REGISTER void *infstr;
2822 
2823 	infstr = initinfstr();
2824 	addstringtoinfstr(infstr, EApplication::localize( EApplication::clipboard()->text() ) );
2825 	string = returninfstr(infstr);
2826 #ifdef ETRACE
2827 	etrace(GTRACE, "{}getcutbuffer: <%s>\n", string);
2828 #endif
2829 	return(string);
2830 }
2831 
2832 /*
2833  * routine to set the contents of the system cut buffer to "msg"
2834  */
setcutbuffer(char * msg)2835 void setcutbuffer(char *msg)
2836 {
2837 #ifdef ETRACE
2838 	etrace(GTRACE, "{}setcutbuffer: msg=<%s>\n", msg);
2839 #endif
2840 	EApplication::clipboard()->setText( QString::fromLocal8Bit( msg ) );
2841 }
2842 
2843 /*
2844  * Routine to clear all text from the messages window.
2845  */
clearmessageswindow(void)2846 void clearmessageswindow(void)
2847 {
2848 	gra->messages->clear();
2849 #ifdef ETRACE
2850 	etrace(GTRACE, "{}clearmessageswindow\n");
2851 #endif
2852 }
2853 
2854 /******************** GRAPHICS CONTROL ROUTINES ********************/
2855 
flushscreen(void)2856 void flushscreen(void)
2857 {
2858 	REGISTER WINDOWFRAME *wf;
2859 
2860 	for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
2861 	{
2862 		/* nothing to do if no changes have been made to offscreen buffer */
2863 		QRect r;
2864 		if (!wf->offscreendirty) continue;
2865 		wf->offscreendirty = FALSE;
2866 		r = QRect( wf->copyleft, wf->copytop,
2867 			   wf->copyright - wf->copyleft, wf->copybottom - wf->copytop );
2868 		wf->draw->repaint( r, FALSE );
2869 	}
2870 	qApp->flush();
2871 }
2872 
2873 /*
2874  * Routine to mark an area of the offscreen buffer as "changed".
2875  */
gra_setrect(WINDOWFRAME * wf,INTBIG lx,INTBIG hx,INTBIG ly,INTBIG hy)2876 void gra_setrect(WINDOWFRAME *wf, INTBIG lx, INTBIG hx, INTBIG ly, INTBIG hy)
2877 {
2878 	static INTBIG checktimefreq = 0;
2879 
2880 	if (gra_noflush) return;
2881 	if (wf->offscreendirty)
2882 	{
2883 		if (lx < wf->copyleft) wf->copyleft = lx;
2884 		if (hx > wf->copyright) wf->copyright = hx;
2885 		if (ly < wf->copytop) wf->copytop = ly;
2886 		if (hy > wf->copybottom) wf->copybottom = hy;
2887 	} else
2888 	{
2889 		wf->copyleft = lx;   wf->copyright = hx;
2890 		wf->copytop = ly;    wf->copybottom = hy;
2891 		wf->offscreendirty = TRUE;
2892 		wf->starttime = ticktime();
2893 	}
2894 
2895 	/* flush the screen every two seconds */
2896 	checktimefreq++;
2897 	if (checktimefreq > 10000)
2898 	{
2899 		checktimefreq = 0;
2900 		if (ticktime() - wf->starttime > FLUSHTICKS) flushscreen();
2901 	}
2902 }
2903 
2904 /*
2905  * Routine to change the default cursor (to indicate modes).
2906  */
setnormalcursor(INTBIG curs)2907 void setnormalcursor(INTBIG curs)
2908 {
2909 #ifdef ETRACE
2910 	etrace(GTRACE, "{ setnormalcursor: curs=%d\n", curs);
2911 #endif
2912 	us_normalcursor = curs;
2913 	setdefaultcursortype(us_normalcursor);
2914 #ifdef ETRACE
2915 	etrace(GTRACE, "} setnormalcursor\n", curs);
2916 #endif
2917 }
2918 
gra_reloadmap(void)2919 void gra_reloadmap(void)
2920 {
2921 	REGISTER VARIABLE *varred, *vargreen, *varblue;
2922 
2923 	varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
2924 	vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
2925 	varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
2926 	if (varred == NOVARIABLE || vargreen == NOVARIABLE || varblue == NOVARIABLE) return;
2927 	colormapload((INTBIG *)varred->addr, (INTBIG *)vargreen->addr, (INTBIG *)varblue->addr, 0, 255);
2928 }
2929 
colormapload(INTBIG * red,INTBIG * green,INTBIG * blue,INTBIG low,INTBIG high)2930 void colormapload(INTBIG *red, INTBIG *green, INTBIG *blue, INTBIG low, INTBIG high)
2931 {
2932 	REGISTER WINDOWFRAME *wf;
2933 	REGISTER INTSML i;
2934 	REGISTER INTBIG r, g, b;
2935 
2936 #ifdef ETRACE
2937 	etrace(GTRACE, "{ colormapload: low=%d high=%d\n", low, high);
2938 #endif
2939 	/* clip to the number of map entries requested */
2940 	if (high >= el_maplength) high = el_maplength - 1;
2941 
2942 	for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
2943 	{
2944 		for(i=low; i<=high; i++)
2945 		{
2946 			r = red[i-low];
2947 			g = green[i-low];
2948 			b = blue[i-low];
2949 
2950 			/* always complement the highest color */
2951 			if (low < 255 && i == 255)
2952 			{
2953 				r = 255 - red[i-low];
2954 				g = 255 - green[i-low];
2955 				b = 255 - blue[i-low];
2956 			}
2957 
2958 			gra_colortable[i] = qRgb( r, g, b );
2959 			wf->draw->image.setColor( i, gra_colortable[i] );
2960 		}
2961 		/* mark the entire screen for redrawing */
2962 		gra_setrect(wf, 0, wf->swid, 0, wf->shei);
2963 	}
2964 
2965 	flushscreen();
2966 
2967 	/* change messages window colors */
2968 	if (low == 0 && high == 255)
2969 	{
2970 		QColor bg( blue[0], green[0], red[0]);
2971 		QColor fg( blue[CELLTXT], green[CELLTXT], red[CELLTXT]);
2972 		gra->messages->setColor( bg, fg );
2973 	}
2974 
2975 #ifdef ETRACE
2976 	etrace(GTRACE, "} colormapload\n");
2977 #endif
2978 }
2979 
2980 /*
2981  * Helper routine to set the cursor shape to "state".
2982  */
setdefaultcursortype(INTBIG state)2983 void setdefaultcursortype(INTBIG state)
2984 {
2985 	WINDOWFRAME *wf;
2986 
2987 	if (us_cursorstate == state) return;
2988 
2989     QCursor cursor = gra->realcursor;
2990     switch (state)
2991     {
2992         case NORMALCURSOR:
2993             cursor = gra->realcursor;
2994             break;
2995         case WANTTTYCURSOR:
2996             cursor = gra->nomousecursor;
2997             break;
2998         case PENCURSOR:
2999             cursor = gra->drawcursor;
3000             break;
3001         case NULLCURSOR:
3002             cursor = gra->nullcursor;
3003             break;
3004         case MENUCURSOR:
3005             cursor = gra->menucursor;
3006             break;
3007         case HANDCURSOR:
3008             cursor = gra->handcursor;
3009             break;
3010         case TECHCURSOR:
3011             cursor = gra->techcursor;
3012             break;
3013         case IBEAMCURSOR:
3014             cursor = gra->ibeamcursor;
3015             break;
3016         case LRCURSOR:
3017             cursor = gra->lrcursor;
3018             break;
3019         case UDCURSOR:
3020             cursor = gra->udcursor;
3021             break;
3022     }
3023 
3024 	for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
3025 	{
3026         wf->draw->setCursor( cursor );
3027 	}
3028 
3029 #ifdef ETRACE
3030 	etrace(GTRACE, "  setdefaultcursortype: oldcursor=%d newcursor=%d\n",
3031 	       us_cursorstate, state);
3032 #endif
3033 	us_cursorstate = state;
3034 }
3035 
3036 /******************** MOUSE CONTROL ********************/
3037 
3038 /*
3039  * routine to return the number of buttons on the mouse
3040  */
buttoncount(void)3041 INTBIG buttoncount(void)
3042 {
3043 	return(mini(BUTTONS, NUMBUTS));
3044 }
3045 
3046 /*
3047  * routine to tell whether button "but" is a double-click
3048  */
doublebutton(INTBIG b)3049 BOOLEAN doublebutton(INTBIG b)
3050 {
3051 #ifdef MACOS
3052 	if (b == 16) return(TRUE);
3053 #else
3054 	if (b >= BUTTONS - REALBUTS) return(TRUE);
3055 #endif
3056 	return(FALSE);
3057 }
3058 
3059 /*
3060  * routine to tell whether button "but" is a context button (right)
3061  */
contextbutton(INTBIG b)3062 BOOLEAN contextbutton(INTBIG b)
3063 {
3064 #ifdef MACOS
3065 	if ((b%4) >= 2) return(TRUE);
3066 #else
3067 	if ((b%5) == 2) return(TRUE);
3068 #endif
3069 	return(FALSE);
3070 }
3071 
3072 /*
3073  * routine to tell whether button "but" has the "shift" key held
3074  */
shiftbutton(INTBIG b)3075 BOOLEAN shiftbutton(INTBIG b)
3076 {
3077 #ifdef MACOS
3078 	if ((b%2) == 1) return(TRUE);
3079 #else
3080 	/* this "switch" statement is taken from the array "gra_butonname" */
3081 	b = b / REALBUTS;
3082 	switch (b)
3083 	{
3084 		case 0: return(FALSE);	/* no shift keys */
3085 		case 1: return(TRUE);	/* shift */
3086 		case 2: return(FALSE);	/* control */
3087 		case 3: return(FALSE);	/* alt */
3088 		case 4: return(TRUE);	/* shift-control */
3089 		case 5: return(TRUE);	/* shift-alt */
3090 		case 6: return(FALSE);	/* control-alt */
3091 		case 7: return(TRUE);	/* shift-control-alt */
3092 		case 8: return(FALSE);	/* double-click */
3093 	}
3094 #endif
3095 	return(FALSE);
3096 }
3097 
3098 /*
3099  * routine to tell whether button "but" is a "mouse wheel" button
3100  */
wheelbutton(INTBIG b)3101 BOOLEAN wheelbutton(INTBIG b)
3102 {
3103 #ifndef MACOS
3104 	b = b % REALBUTS;
3105 	if (b == 3 || b == 4) return(TRUE);
3106 #endif
3107 	return(FALSE);
3108 }
3109 
3110 /*
3111  * routine to return the name of button "b" (from 0 to "buttoncount()").
3112  * The number of letters unique to the button is placed in "important".
3113  */
buttonname(INTBIG b,INTBIG * important)3114 char *buttonname(INTBIG b, INTBIG *important)
3115 {
3116 	*important = gra_buttonname[b].unique;
3117 	return(gra_buttonname[b].name);
3118 }
3119 
3120 /*
3121  * routine to wait for a button push and return its index (0 based) in "*but".
3122  * The coordinates of the cursor are placed in "*x" and "*y".  If there is no
3123  * button push, the value of "*but" is negative.
3124  */
waitforbutton(INTBIG * x,INTBIG * y,INTBIG * but)3125 void waitforbutton(INTBIG *x, INTBIG *y, INTBIG *but)
3126 {
3127 	/* This function is not used on Qt */
3128 	Q_UNUSED( x );
3129 	Q_UNUSED( y );
3130 #ifdef ETRACE
3131 	etrace(GTRACE, "{} waitforbutton: but=-1\n");
3132 #endif
3133 	*but = -1;
3134 }
3135 
3136 /*
3137  * routine to do modal loop, calling "charhandler" for each typed key and "buttonhandler"
3138  * for each pushed button. The "charhandler" routine is called with the character value
3139  * that was typed. The "buttonhandler" routine is called with coordinates of cursor.
3140  * The "charhandler" and "buttonhandler" returns true to abort loop.
3141  * The value of "cursor" determines cursor appearance.
3142  */
modalloop(BOOLEAN (* charhandler)(INTSML chr,INTBIG special),BOOLEAN (* buttonhandler)(INTBIG x,INTBIG y,INTBIG but),INTBIG cursor)3143 void modalloop(BOOLEAN (*charhandler)(INTSML chr, INTBIG special),
3144 	BOOLEAN (*buttonhandler)(INTBIG x, INTBIG y, INTBIG but), INTBIG cursor)
3145 {
3146 #ifdef ETRACE
3147 	etrace(GTRACE, "{ modalloop: cursor=%d %s\n",
3148 	       cursor, stateNames[gra_state]);
3149 #endif
3150 	/* change state */
3151 	GRAPHSTATE savedstate = gra_state;
3152 	gra_state = S_MODAL;
3153 #ifdef ETRACE
3154 	etrace(GTRACE, "  gra_state=MODAL\n");
3155 #endif
3156 	gra->charhandler = charhandler;
3157 	gra->buttonhandler = buttonhandler;
3158 
3159 	/* set cursor */
3160 	INTBIG oldnormalcursor = us_normalcursor;
3161 	setnormalcursor(cursor);
3162 #if 1
3163 	flushscreen();
3164 #endif
3165 
3166 	qApp->enter_loop();
3167 
3168 	/* restore cursor */
3169 	setnormalcursor(oldnormalcursor);
3170 	gra_state = savedstate;
3171 #ifdef ETRACE
3172 	etrace(GTRACE, "  gra_state=%s\n", stateNames[gra_state]);
3173 #endif
3174 	gra->charhandler = 0;
3175 	gra->buttonhandler = 0;
3176 #ifdef ETRACE
3177 	etrace(GTRACE, "} modalloop\n");
3178 #endif
3179 }
3180 
3181 /*
3182  * routine to track the cursor until a button is released, calling "whileup" for
3183  * each co-ordinate when the mouse moves before the first button push, calling
3184  * "whendown" once when the button goes down, calling "eachdown" for each
3185  * co-ordinate when the mouse moves after the button is pushed, calling
3186  * "eachchar" for each key that is typed at any time, and calling "done" once
3187  * when done.  The "whendown" and "done" routines are called with no parameters;
3188  * "whileup" and "eachdown" are called with the X and Y coordinates of the
3189  * cursor; and "eachchar" is called with the X, Y, and character value that was
3190  * typed.  The "whileup", "eachdown", and "eachchar" routines return nonzero to
3191  * abort tracking.
3192  * If "waitforpush" is true then the routine will wait for a button to
3193  * actually be pushed before tracking (otherwise it will begin tracking
3194  * immediately).  The value of "purpose" determines what the cursor will look
3195  * like during dragging: 0 for normal (the X cursor), 1 for drawing (a pen),
3196  * 2 for dragging (a hand), 3 for popup menu selection (a horizontal arrow), 4 for
3197  * hierarchical popup menu selection (arrow, stays at end).
3198  */
trackcursor(BOOLEAN waitforpush,BOOLEAN (* whileup)(INTBIG,INTBIG),void (* whendown)(void),BOOLEAN (* eachdown)(INTBIG,INTBIG),BOOLEAN (* eachchar)(INTBIG,INTBIG,INTSML),void (* done)(void),INTBIG purpose)3199 void trackcursor(BOOLEAN waitforpush, BOOLEAN (*whileup)(INTBIG, INTBIG),
3200 	void (*whendown)(void), BOOLEAN (*eachdown)(INTBIG, INTBIG),
3201 	BOOLEAN (*eachchar)(INTBIG, INTBIG, INTSML), void (*done)(void), INTBIG purpose)
3202 {
3203 #ifdef ETRACE
3204 	etrace(GTRACE, "{ trackcursor: waitforpush=%d purpose=%d %s\n",
3205 	       waitforpush, purpose, stateNames[gra_state]);
3206 #endif
3207 	/* change state */
3208 	GRAPHSTATE savedstate = gra_state;
3209 	gra_state = S_TRACK;
3210 #ifdef ETRACE
3211 	etrace(GTRACE, "  gra_state=TRACK\n");
3212 #endif
3213 	gra->waitforpush = waitforpush;
3214 	gra->whileup = whileup;
3215 	gra->whendown = whendown;
3216 	gra->eachdown = eachdown;
3217 	gra->eachchar = eachchar;
3218 
3219 	/* change the cursor to an appropriate icon */
3220 	INTSML oldnormalcursor = us_normalcursor;
3221 	switch (purpose)
3222 	{
3223 		case TRACKDRAWING:    us_normalcursor = PENCURSOR;    break;
3224 		case TRACKDRAGGING:   us_normalcursor = HANDCURSOR;   break;
3225 		case TRACKSELECTING:
3226 		case TRACKHSELECTING: us_normalcursor = MENUCURSOR;   break;
3227 	}
3228 	setdefaultcursortype(us_normalcursor);
3229 
3230 	flushscreen();
3231 
3232 	BOOLEAN keepon = FALSE;
3233 	if (!waitforpush) {
3234 #ifdef ETRACE
3235         etrace(GTRACE, "  trackcursor { whendown\n");
3236 #endif
3237 		(*whendown)();
3238 #ifdef ETRACE
3239 		etrace(GTRACE, "  trackcursor } whendown\n");
3240 		etrace(GTRACE, "  trackcursor { eachdown x=%d y=%d\n", gra_cursorx, gra_cursory);
3241 #endif
3242 		keepon = (*eachdown)(gra_cursorx, gra_cursory);
3243 #ifdef ETRACE
3244 		etrace(GTRACE, "  trackcursor } eachdown: keepon=%d el_pleasestp=%d\n",
3245 		       keepon, el_pleasestop);
3246 #endif
3247 	}
3248 
3249 	/* enter modal loop */
3250 	if (!keepon && !el_pleasestop) qApp->enter_loop();
3251 
3252 	/* inform the user that all is done */
3253 #ifdef ETRACE
3254 	etrace(GTRACE, "  trackcursor { done\n");
3255 #endif
3256 	(*done)();
3257 #ifdef ETRACE
3258 	etrace(GTRACE, "  trackcursor } done\n");
3259 #endif
3260 	flushscreen();
3261 
3262 	/* restore the state of the world */
3263 	us_normalcursor = oldnormalcursor;
3264 	setdefaultcursortype(us_normalcursor);
3265 	gra_state = savedstate;
3266 #ifdef ETRACE
3267 	etrace(GTRACE, "  gra_state=%s\n", stateNames[gra_state]);
3268 #endif
3269 	gra->whileup = 0;
3270 	gra->whendown = 0;
3271 	gra->eachdown = 0;
3272 	gra->eachchar = 0;
3273 #ifdef ETRACE
3274 	etrace(GTRACE, "} trackcursor\n");
3275 #endif
3276 }
3277 
3278 /*
3279  * routine to read the current co-ordinates of the tablet and return them in "*x" and "*y"
3280  */
readtablet(INTBIG * x,INTBIG * y)3281 void readtablet(INTBIG *x, INTBIG *y)
3282 {
3283 	*x = gra_cursorx;
3284 	*y = gra_cursory;
3285 #ifdef ETRACE
3286 	etrace(GTRACE, "{}readtablet: x=%d y=%d\n", *x, *y);
3287 #endif
3288 }
3289 
3290 /*
3291  * routine to turn off the cursor tracking if it is on
3292  */
stoptablet(void)3293 void stoptablet(void)
3294 {
3295 	/* This function is not used on Qt */
3296 #ifdef ETRACE
3297 	etrace(GTRACE, "{ stoptablet\n");
3298 #endif
3299 	if (us_cursorstate != IBEAMCURSOR) setdefaultcursortype(us_normalcursor);
3300 #ifdef ETRACE
3301 	etrace(GTRACE, "} stoptablet\n");
3302 #endif
3303 }
3304 
3305 /******************** KEYBOARD CONTROL ********************/
3306 
3307 /*
3308  * routine to get the next character from the keyboard
3309  */
getnxtchar(INTBIG * special)3310 INTSML getnxtchar(INTBIG *special)
3311 {
3312 	/* This function is not used on Qt */
3313 #ifdef ETRACE
3314 	etrace(GTRACE, "{ getnxtchar\n");
3315 #endif
3316 	modalloop(gra_nxtcharhandler, gra_nullbuttonhandler, WANTTTYCURSOR);
3317 #ifdef ETRACE
3318 	etrace(GTRACE, "} getnxtchar: char=%#o special=%#o\n",
3319 	       gra_nxtchar, gra_nxtcharspecial);
3320 #endif
3321 	*special = gra_nxtcharspecial;
3322 	return(gra_nxtchar);
3323 }
3324 
gra_nxtcharhandler(INTSML chr,INTBIG special)3325 static BOOLEAN gra_nxtcharhandler(INTSML chr, INTBIG special)
3326 {
3327 	gra_nxtchar = chr;
3328 	gra_nxtcharspecial = special;
3329 	return(TRUE);
3330 }
3331 
gra_nullbuttonhandler(INTBIG x,INTBIG y,INTBIG but)3332 static BOOLEAN gra_nullbuttonhandler(INTBIG x, INTBIG y, INTBIG but)
3333 {
3334 	Q_UNUSED( x );
3335 	Q_UNUSED( y );
3336 	Q_UNUSED( but );
3337 	return(FALSE);
3338 }
3339 
3340 /* not required with X11 */
checkforinterrupt(void)3341 void checkforinterrupt(void)
3342 {
3343 #ifdef ETRACE_
3344 	etrace(GTRACE, "{ checkforinterrupt: %s\n", stateNames[gra_state]);
3345 #endif
3346 #if 0
3347 	GRAPHSTATE savedstate = gra_state;
3348 	gra_state = S_CHECKINT;
3349 
3350 	if (gra->hasPendingEvents())
3351 		gra->processEvents();
3352 	setdefaultcursortype(NULLCURSOR);
3353 
3354 	gra_state = savedstate;
3355 #endif
3356 #ifdef ETRACE_
3357 	etrace(GTRACE, "} checkforinterrupt\n");
3358 #endif
3359 }
3360 
3361 /*
3362  * Routine to return which "bucky bits" are held down (shift, control, etc.)
3363  */
getbuckybits(void)3364 INTBIG getbuckybits(void)
3365 {
3366 	REGISTER INTBIG bits;
3367 
3368 	bits = 0;
3369 	if (gra_lastbuttonstate & Qt::ControlButton) bits |= CONTROLDOWN|ACCELERATORDOWN;
3370 	if (gra_lastbuttonstate & Qt::ShiftButton) bits |= SHIFTDOWN;
3371 	if (gra_lastbuttonstate & Qt::AltButton) bits |= OPTALTMETDOWN;
3372 	return(bits);
3373 }
3374 
3375 /*
3376  * routine to tell whether data is waiting at the terminal.  Returns true
3377  * if data is ready.
3378  */
ttydataready(void)3379 BOOLEAN ttydataready(void)
3380 {
3381 	/* This function is not used on Qt */
3382 #ifdef ETRACE
3383 	etrace(GTRACE, "{}ttydataready: result=0\n");
3384 #endif
3385 	return(FALSE);
3386 }
3387 
3388 /****************************** FILES ******************************/
3389 
3390 #ifdef MACOS
3391 /*
3392  * Routine to set the type and creator of file "name" to "type" and "creator"
3393  */
mac_settypecreator(char * name,INTBIG type,INTBIG creator)3394 void mac_settypecreator(char *name, INTBIG type, INTBIG creator)
3395 {
3396 	FSRef ref, parentRef;
3397 	OSErr result;
3398 	FSCatalogInfo catalogInfo;
3399 
3400 	/* convert the full path to a FSRef */
3401 	FSPathMakeRef((unsigned char *)name, &ref, NULL);
3402 
3403 	/* get info about the FSRef */
3404 	result = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags + kFSCatInfoFinderInfo, &catalogInfo , NULL, NULL, &parentRef);
3405 	if (result != noErr) return;
3406 
3407 	/* set the type and creator */
3408 	((FileInfo *)&catalogInfo.finderInfo)->fileType = type;
3409 	((FileInfo *)&catalogInfo.finderInfo)->fileCreator = creator;
3410 	FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catalogInfo);
3411 }
3412 #endif
3413 
localize(QString qstr)3414 char *EApplication::localize (QString qstr)
3415 {
3416     static QCString str[2];
3417 	static int i = 0;
3418 
3419     str[i] = qstr.local8Bit();
3420     const char *s = str[i];
3421 	i = (i + 1) % (sizeof(str)/sizeof(str[0]));
3422     return((char*)s);
3423 }
3424 
localizeFilePath(QString filePath,bool addSeparator)3425 char *EApplication::localizeFilePath (QString filePath, bool addSeparator )
3426 {
3427     static QCString filePathCS;
3428 
3429     if ( addSeparator && !filePath.isEmpty() && filePath.right(1) != QString::fromLatin1("/") )
3430 	filePath += '/';
3431     filePath = QDir::convertSeparators( filePath );
3432     filePathCS = QFile::encodeName( filePath );
3433     const char *s = filePathCS;
3434     return((char*)s);
3435 }
3436 
3437 /*
3438  * Routine to prompt for multiple files of type "filetype", giving the
3439  * message "msg".  Returns a string that contains all of the file names,
3440  * separated by the NONFILECH (a character that cannot be in a file name).
3441  */
multifileselectin(char * msg,INTBIG filetype)3442 char *multifileselectin(char *msg, INTBIG filetype)
3443 {
3444 	return(fileselect(msg, filetype, ""));
3445 }
3446 
3447 extern "C" COMCOMP us_yesnop;
3448 
3449 /*
3450  * Routine to display a standard file prompt dialog and return the selected file.
3451  * The prompt message is in "msg" and the kind of file is in "filetype".  The default
3452  * output file name is in "defofile" (only used if "filetype" is for output files).
3453  */
fileselect(char * msg,INTBIG filetype,char * defofile)3454 char *fileselect(char *msg, INTBIG filetype, char *defofile)
3455 {
3456 	INTBIG mactype;
3457 	BOOLEAN binary;
3458 	char *extension, *winfilter, *shortname, *longname, temp[300];
3459 
3460 #ifdef ETRACE
3461 	etrace(GTRACE, "{ fileselect: msg=%s filetype=%d defofile\n", msg, filetype, defofile);
3462 #endif
3463 
3464 	QString fileName;
3465 	QWidget *parent;
3466 
3467 #ifdef MACOSX
3468 	parent = 0;
3469 #else
3470 	parent = el_curwindowframe != NOWINDOWFRAME ?
3471 	  el_curwindowframe->draw->parentWidget() :
3472 	  gra->mainWidget();
3473 #endif
3474 	describefiletype(filetype, &extension, &winfilter, &mactype, &binary, &shortname, &longname);
3475 	sprintf(temp, "%s (%s);;All Files (*)", msg, winfilter);
3476 	QString filter = QString::fromLocal8Bit( temp );
3477 	if ((filetype&FILETYPEWRITE) == 0)
3478 	{
3479 		/* input file selection: display the file input dialog box */
3480 		sprintf(temp, _("%s Selection"), msg);
3481 		QString title = QString::fromLocal8Bit( temp );
3482 
3483 		fileName = QFileDialog::getOpenFileName(
3484 			QString::null, filter, parent, "FileSelection", title);
3485 	} else
3486 	{
3487 		/* output file selection: display the file input dialog box */
3488 		sprintf(temp, _("%s Selection"), msg);
3489 		QString startWith = QFile::decodeName( fullfilename(defofile) );
3490 #ifdef MACOSX
3491 		QFileDialog *fd = new QFileDialog(parent, temp, TRUE);
3492 		fd->setMode(QFileDialog::AnyFile);
3493 		fd->setFilter(filter);
3494 		fd->setSelection(startWith);
3495 		if (fd->exec() != QDialog::Accepted) fileName = QString::null; else
3496 			fileName = fd->selectedFile();
3497 		delete fd;
3498 #else
3499 		QString title = QString::fromLocal8Bit( temp );
3500 		fileName = QFileDialog::getSaveFileName(
3501 			startWith, filter, parent, "File Creation", title);
3502 #endif
3503 
3504 		/* give warning if creating file that already exists */
3505 		if (!fileName.isEmpty() && QFile::exists( fileName ))
3506 		{
3507 			QFileInfo fileInfo( fileName );
3508 			char fullmsg[300], *pars[5];
3509 			const char *s = EApplication::localize( fileName );
3510 			if (fileInfo.isDir())
3511 			{
3512 				DiaMessageInDialog(_("'%s' is a directory: cannot write it"), s);
3513 				fileName = QString::null;
3514 			} else if (!fileInfo.isWritable())
3515 			{
3516 				DiaMessageInDialog(_("'%s' is read-only: cannot overwrite it"), s);
3517 				fileName = QString::null;
3518 			} else
3519 			{
3520 				sprintf(fullmsg, _("File '%s' exists.  Overwrite? "), s);
3521 				INTSML count = ttygetparam(fullmsg, &us_yesnop, 2, pars);
3522 				if (count > 0 && namesamen(pars[0], "no", strlen(pars[0])) == 0)
3523 					fileName = QString::null;
3524 			}
3525 		}
3526 	}
3527 	if (!fileName.isEmpty()) {
3528 		QDir::setCurrent( QFileInfo(fileName).dirPath() );
3529 	}
3530 	strcpy(gra_curpath, EApplication::localizeFilePath( fileName, FALSE) );
3531 
3532 #ifdef ETRACE
3533 	etrace(GTRACE, "} fileselect: %s\n", gra_curpath);
3534 #endif
3535 	if (gra_curpath[0] == 0) return((char *)NULL); else
3536 	{
3537 		return(gra_curpath);
3538 	}
3539 }
3540 
3541 /*
3542  * Routine to search for all of the files/directories in directory "directory" and
3543  * return them in the array of strings "filelist".  Returns the number of files found.
3544  */
filesindirectory(char * directory,char *** filelist)3545 INTBIG filesindirectory(char *directory, char ***filelist)
3546 {
3547 	INTBIG len;
3548 	QDir dir( QString::fromLocal8Bit (directory) );
3549 
3550 #ifdef ETRACE
3551 	etrace(GTRACE, "{ fileindirectory: %s\n", directory);
3552 #endif
3553 	if (gra_fileliststringarray == 0)
3554 	{
3555 		gra_fileliststringarray = newstringarray(db_cluster);
3556 		if (gra_fileliststringarray == 0) return 0;
3557 	}
3558 	clearstrings(gra_fileliststringarray);
3559 
3560 	for(uint i=0; i < dir.count(); i++)
3561 	{
3562 		if (dir[i] == "." || dir[i] == "..") continue;
3563 		addtostringarray( gra_fileliststringarray,  EApplication::localizeFilePath ( dir[i], FALSE ) );
3564 	}
3565 	*filelist = getstringarray(gra_fileliststringarray, &len);
3566 #ifdef ETRACE
3567 	for (int i = 0; i < len; i++)
3568 	  etrace(GTRACE, "\t%s\n", (*filelist)[i]);
3569 	etrace(GTRACE, "} filesindirectory\n");
3570 #endif
3571 	return(len);
3572 }
3573 
3574 /* routine to convert a path name with "~" to a real path */
truepath(char * line)3575 char *truepath(char *line)
3576 {
3577 #if defined(ONUNIX) || defined(MACOSX)
3578 	static char outline[100], home[50];
3579 	REGISTER char save, *ch;
3580 	static INTSML gothome = 0;
3581 	struct passwd *tmp;
3582 
3583 	if (line[0] != '~') return(line);
3584 
3585 	/* if it is the form "~username", figure it out */
3586 	if (line[1] != '/')
3587 	{
3588 		for(ch = &line[1]; *ch != 0 && *ch != '/'; ch++);
3589 		save = *ch;   *ch = 0;
3590 		tmp = getpwnam(&line[1]);
3591 		if (tmp == 0) return(line);
3592 		*ch = save;
3593 		(void)strcpy(outline, tmp->pw_dir);
3594 		(void)strcat(outline, ch);
3595 		return(outline);
3596 	}
3597 
3598 	/* get the user's home directory once only */
3599 	if (gothome == 0)
3600 	{
3601 		/* get name of user */
3602 		tmp = getpwuid(getuid());
3603 		if (tmp == 0) return(line);
3604 		(void)strcpy(home, tmp->pw_dir);
3605 		gothome++;
3606 	}
3607 
3608 	/* substitute home directory for the "~" */
3609 	(void)strcpy(outline, home);
3610 	(void)strcat(outline, &line[1]);
3611 	return(outline);
3612 #else
3613 	/* only have tilde parsing on UNIX and Mac OS 10 */
3614 	return(line);
3615 #endif
3616 }
3617 
3618 /*
3619  * Routine to return the full path to file "file".
3620  */
fullfilename(char * file)3621 char *fullfilename(char *file)
3622 {
3623 #if 1
3624 	QFileInfo fileInfo( QString::fromLocal8Bit( file ) );
3625 	return EApplication::localizeFilePath( fileInfo.absFilePath(), FALSE );
3626 #else
3627 	static char fullfile[MAXPATHLEN];
3628 
3629 	if (file[0] == '/') return(file);
3630 	strcpy(fullfile, currentdirectory());
3631 	strcat(fullfile, file);
3632 	return(fullfile);
3633 #endif
3634 }
3635 
3636 /*
3637  * routine to rename file "file" to "newfile"
3638  * returns nonzero on error
3639  */
erename(char * file,char * newfile)3640 INTBIG erename(char *file, char *newfile)
3641 {
3642 #ifdef WIN32
3643 	return(rename(file, newfile));
3644 #else
3645 	if (link(file, newfile) < 0) return(1);
3646 	if (unlink(file) < 0) return(1);
3647 	return(0);
3648 #endif
3649 }
3650 
3651 /*
3652  * routine to delete file "file"
3653  */
eunlink(char * file)3654 INTBIG eunlink(char *file)
3655 {
3656 	return(unlink(file));
3657 }
3658 
3659 /*
3660  * Routine to return information about the file or directory "name":
3661  *  0: does not exist
3662  *  1: is a file
3663  *  2: is a directory
3664  *  3: is a locked file (read-only)
3665  */
fileexistence(char * name)3666 INTBIG fileexistence(char *name)
3667 {
3668 	QFileInfo fileInfo( QString::fromLocal8Bit( name ));
3669 	if (!fileInfo.exists()) return(0);
3670 	if (fileInfo.isDir()) return(2);
3671 	if (!fileInfo.isWritable()) return(3);
3672 	return(1);
3673 }
3674 
3675 /*
3676  * Routine to create a directory.
3677  * Returns true on error.
3678  */
createdirectory(char * dirname)3679 BOOLEAN createdirectory(char *dirname)
3680 {
3681 	char cmd[256];
3682 
3683 	sprintf(cmd, "mkdir %s", dirname);
3684 	if (system(cmd) == 0) return(FALSE);
3685 	return(TRUE);
3686 }
3687 
3688 /*
3689  * Routine to return the current directory name
3690  */
currentdirectory(void)3691 char *currentdirectory(void)
3692 {
3693 	char *s = EApplication::localizeFilePath(QDir::currentDirPath(), TRUE);
3694 #ifdef ETRACE
3695 	etrace(GTRACE, "{}currentdirectory: %s\n", s);
3696 #endif
3697 	return(s);
3698 }
3699 
3700 /*
3701  * Routine to return the home directory (returns 0 if it doesn't exist)
3702  */
hashomedir(void)3703 char *hashomedir(void)
3704 {
3705 	char *s = EApplication::localizeFilePath(QDir::homeDirPath(), TRUE);
3706 	return(s);
3707 }
3708 
3709 /*
3710  * Routine to return the path to the "options" library.
3711  */
optionsfilepath(void)3712 char *optionsfilepath(void)
3713 {
3714 	return("~/.electricoptions.elib");
3715 }
3716 
3717 /*
3718  * routine to return the date of the last modification to file "filename"
3719  */
filedate(char * filename)3720 time_t filedate(char *filename)
3721 {
3722 	struct stat buf;
3723 
3724 	stat(filename, &buf);
3725 	buf.st_mtime -= machinetimeoffset();
3726 	return(buf.st_mtime);
3727 }
3728 
3729 /*
3730  * Routine to lock a resource called "lockfilename" by creating such a file
3731  * if it doesn't exist.  Returns true if successful, false if unable to
3732  * lock the file.
3733  */
lockfile(char * lockfilename)3734 BOOLEAN lockfile(char *lockfilename)
3735 {
3736 	INTBIG fd;
3737 
3738 	fd = creat(lockfilename, 0);
3739 	if (fd == -1 && errno == EACCES) return(FALSE);
3740 	if (fd == -1 || close(fd) == -1) return(FALSE);
3741 	return(TRUE);
3742 }
3743 
3744 /*
3745  * Routine to unlock a resource called "lockfilename" by deleting such a file.
3746  */
unlockfile(char * lockfilename)3747 void unlockfile(char *lockfilename)
3748 {
3749 	if (unlink(lockfilename) == -1)
3750 		ttyputerr(_("Error unlocking %s"), lockfilename);
3751 }
3752 
3753 /*
3754  * Routine to show file "filename" in a browser window.
3755  * Returns true if the operation cannot be done.
3756  */
browsefile(char * filename)3757 BOOLEAN browsefile(char *filename)
3758 {
3759 	char line[300];
3760 
3761 	sprintf(line, "netscape %s&", filename);
3762 	if (system(line) == 0) return(FALSE);
3763 	return(TRUE);
3764 }
3765 
3766 /************************ EProcess class ***************************/
3767 
EProcessPrivate()3768 EProcessPrivate::EProcessPrivate()
3769 	: QProcess()
3770 {
3771 }
3772 
idle()3773 void EProcessPrivate::idle()
3774 {
3775 	QTimer timer( this );
3776 	timer.start( EPROCESSWAIT, TRUE );
3777 	qApp->processOneEvent();
3778 }
3779 
EProcess()3780 EProcess::EProcess()
3781 {
3782 	d = new EProcessPrivate();
3783 	setCommunication( TRUE, TRUE, TRUE );
3784 }
3785 
~EProcess()3786 EProcess::~EProcess()
3787 {
3788 	clearArguments();
3789 	delete d;
3790 }
3791 
clearArguments()3792 void EProcess::clearArguments()
3793 {
3794 	d->clearArguments();
3795 }
3796 
addArgument(CHAR * arg)3797 void EProcess::addArgument( CHAR *arg )
3798 {
3799 	d->addArgument( arg );
3800 }
3801 
setCommunication(BOOLEAN cStdin,BOOLEAN cStdout,BOOLEAN cStderr)3802 void EProcess::setCommunication( BOOLEAN cStdin, BOOLEAN cStdout, BOOLEAN cStderr )
3803 {
3804 	int comms = 0;
3805 
3806 	if ( cStdin) comms |= QProcess::Stdin;
3807 	if ( cStdout ) comms |= QProcess::Stdout;
3808 	if ( cStderr ) comms |= QProcess::Stderr;
3809 	if ( cStdout || cStderr ) comms |= QProcess::DupStderr;
3810 	d->setCommunication( comms );
3811 }
3812 
start(CHAR * infile)3813 BOOLEAN EProcess::start( CHAR *infile )
3814 {
3815 	d->buf.resize( 0 );
3816 
3817 	if (!infile) return d->start(); else
3818 	{
3819 		QFile file( infile );
3820 		if ( !file.open( IO_ReadOnly ) )
3821 		{
3822 			ttyputmsg(_("File %s not opened. Process not launched"), infile);
3823 			return FALSE;
3824 		}
3825 		QByteArray inp = file.readAll();
3826 		file.close();
3827 		return d->launch( inp );
3828 	}
3829 }
3830 
wait()3831 void EProcess::wait()
3832 {
3833 	while (d->isRunning()) d->idle();
3834 }
3835 
kill()3836 void EProcess::kill()
3837 {
3838 #if 1
3839 	d->kill();
3840 	wait();
3841 	char *arg0 = EApplication::localize( d->arguments()[0] );
3842 	if (d->normalExit())
3843 		ttyputmsg(_("%s execution terminated"), arg0 );
3844 	else
3845 		ttyputmsg(_("%s execution reports error %d"), arg0, d->exitStatus());
3846 #else
3847 	if ( d->_cStdout || d->_cStderr) eclose(d->opipe[0]);
3848 	if (ekill(d->process) == 0)
3849 	{
3850 		ewait(d->process);
3851 		if (errno > 0)
3852 			ttyputmsg(_("%s execution reports error %d"), d->arguments[0], errno);
3853 		else ttyputmsg(_("%s execution terminated"), d->arguments[0]);
3854 	}
3855 #endif
3856 }
3857 
getChar()3858 INTSML EProcess::getChar()
3859 {
3860 	if (d->bufp >= d->buf.size())
3861 	{
3862 		d->bufp = 0;
3863 		for(;;)
3864 		{
3865 			d->buf = (d->communication() & QProcess::Stdout) != 0 ? d->readStdout() : d->readStderr();
3866 			if ( d->buf.size() > 0 ) break;
3867 			if ( !d->isRunning() ) return EOF;
3868 			d->idle();
3869 		}
3870 	}
3871 	return d->buf[d->bufp++];
3872 }
3873 
putChar(UCHAR1 ch)3874 void EProcess::putChar( UCHAR1 ch )
3875 {
3876 	QString qstr = QChar( ch );
3877 	d->writeToStdin( qstr );
3878 }
3879 
3880 /******************** TIME ROUTINES ********************/
3881 
3882 /*
3883  * This routine returns the amount to add to the operating-system time
3884  * to adjust for a common time format.
3885  */
machinetimeoffset(void)3886 time_t machinetimeoffset(void)
3887 {
3888 	return(0);
3889 }
3890 
3891 /* returns the time at which the current event occurred */
eventtime(void)3892 UINTBIG eventtime(void)
3893 {
3894 	return(ticktime());
3895 }
3896 
3897 /* returns the current time in 60ths of a second */
ticktime(void)3898 UINTBIG ticktime(void)
3899 {
3900 	return (-QTime::currentTime().msecsTo( QTime() ) ) * 6 / 100;
3901 }
3902 
3903 /* returns the double-click interval in 60ths of a second */
doubleclicktime(void)3904 INTBIG doubleclicktime(void)
3905 {
3906 	INTBIG dct;
3907 
3908 	dct = gra_doublethresh;
3909 	dct = dct * 60 / 1000;
3910 	return(dct);
3911 }
3912 
3913 /*
3914  * Routine to wait "ticks" sixtieths of a second and then return.
3915  */
gotosleep(INTBIG ticks)3916 void gotosleep(INTBIG ticks)
3917 {
3918 #ifdef WIN32
3919 	Sleep(ticks * 100 / 6);
3920 #else
3921 	sleep(ticks);
3922 #endif
3923 }
3924 
3925 /*
3926  * Routine to start counting time.
3927  */
starttimer(void)3928 void starttimer(void)
3929 {
3930 	gra_timebase.start();
3931 }
3932 
3933 /*
3934  * Routine to stop counting time and return the number of elapsed seconds
3935  * since the last call to "starttimer()".
3936  */
endtimer(void)3937 float endtimer(void)
3938 {
3939 	return ((float)gra_timebase.elapsed()) / 1000.0;
3940 }
3941 
3942 /*************************** EVENT ROUTINES ***************************/
3943 
toolTimeSlice()3944 void EApplication::toolTimeSlice()
3945 {
3946 #ifdef ETRACE
3947     etrace(GTRACE, "{ toolTimeSlice %s %d\n", stateNames[gra_state], gra_stop_dowork);
3948 #endif
3949     if (gra_state == S_USER) {
3950         Q_ASSERT( gra_stop_dowork == 0 );
3951         gra_stop_dowork++;
3952 
3953 	/* announce end of broadcast of changes */
3954 	db_endbatch();
3955 
3956 	gra_state = S_TOOL;
3957 #if 1
3958 	do {
3959 		tooltimeslice();
3960 	} while((us_state&LANGLOOP) != 0);
3961 #else
3962 	tooltimeslice();
3963 #endif
3964 
3965 	gra_state = S_USER;
3966 	db_setcurrenttool(us_tool);
3967 	flushscreen();
3968 
3969 	/* first see if there is any pending input */
3970 	el_pleasestop = 0;
3971 	if (us_cursorstate != IBEAMCURSOR) setdefaultcursortype(us_normalcursor);
3972 	gra_handlequeuedframedeletion();
3973         gra_stop_dowork--;
3974     }
3975 #ifdef ETRACE
3976     etrace(GTRACE, "} toolTimeSlice\n");
3977 #endif
3978 }
3979 
gra_handlequeuedframedeletion(void)3980 void gra_handlequeuedframedeletion(void)
3981 {
3982 	char *par[MAXPARS];
3983 	REGISTER INTBIG windows;
3984 	REGISTER WINDOWFRAME *wf, *delwf;
3985 	REGISTER WINDOWPART *win, *nextw, *neww;
3986 	REGISTER NODEPROTO *np;
3987 
3988 	if (gra_deletethisframe == 0) return;
3989 	delwf = gra_deletethisframe;
3990 	gra_deletethisframe = 0;
3991 
3992 	/* turn off component menu if it was deleted */
3993 	if (delwf->floating)
3994 	{
3995 		par[0] = "off";
3996 		us_menu(1, par);
3997 		return;
3998 	}
3999 
4000 	/* make sure there is another window */
4001 	windows = 0;
4002 	for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
4003 		if (!wf->floating) windows++;
4004 #ifndef MACOS
4005 	if (windows < 2)
4006 	{
4007 		/* no other windows: kill the program */
4008 		if (us_preventloss(NOLIBRARY, 0, TRUE)) return;
4009 		bringdown();
4010 	} else
4011 #endif
4012 	{
4013 		/* there are other windows: allow this one to be killed (code copied from us_window("delete")) */
4014 
4015 		/* remember that a window is being deleted */
4016 		gra_windowbeingdeleted = 1;
4017 
4018 		/* save highlighting and turn it off */
4019 		us_pushhighlight();
4020 		us_clearhighlightcount();
4021 
4022 		startobjectchange((INTBIG)us_tool, VTOOL);
4023 
4024 		/* kill all editor windows on this frame */
4025 		neww = NOWINDOWPART;
4026 		for(win = el_topwindowpart; win != NOWINDOWPART; win = nextw)
4027 		{
4028 			nextw = win->nextwindowpart;
4029 			if (win->frame != delwf)
4030 			{
4031 				neww = win;
4032 				continue;
4033 			}
4034 
4035 			/* kill this window */
4036 			killwindowpart(win);
4037 		}
4038 		endobjectchange((INTBIG)us_tool, VTOOL);
4039 
4040 		if (neww == NOWINDOWPART) el_curwindowpart = NOWINDOWPART;
4041 		(void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)neww, VWINDOWPART|VDONTSAVE);
4042 		if (neww != NOWINDOWPART) np = neww->curnodeproto; else np = NONODEPROTO;
4043 		(void)setval((INTBIG)el_curlib, VLIBRARY, "curnodeproto", (INTBIG)np, VNODEPROTO);
4044 
4045 		/* restore highlighting */
4046 		us_pophighlight(FALSE);
4047 
4048 		/* now no widget being deleted, and kill the window properly */
4049 		gra_windowbeingdeleted = 0;
4050 		killwindowframe(delwf);
4051 	}
4052 }
4053 
keepCursorPos(QPoint pos)4054 void GraphicsDraw::keepCursorPos( QPoint pos )
4055 {
4056     gra_cursorx = pos.x();
4057     gra_cursory = wf->revy - pos.y();
4058     if (gra_cursory < 0) gra_cursory = 0;
4059 	us_state &= ~GOTXY;
4060 }
4061 
buttonPressed(QPoint pos,INTSML but)4062 void GraphicsDraw::buttonPressed( QPoint pos, INTSML but )
4063 {
4064 #ifdef DOUBLESELECT
4065 	if (activationChanged)
4066 	{
4067 		activationChanged = FALSE;
4068 		return;
4069 	}
4070 #endif
4071     keepCursorPos( pos );
4072     us_state |= DIDINPUT;
4073     if (gra_state == S_USER)
4074 	{
4075 #ifdef ETRACE
4076         etrace(GTRACE, "{  on_tablet gra_cursorx=%d gra_cursory=%d but=%d\n",
4077 			gra_cursorx, gra_cursory, but);
4078 #endif
4079         us_ontablet(gra_cursorx, gra_cursory, but);
4080 #ifdef ETRACE
4081         etrace(GTRACE, "}  on_tablet\n");
4082 #endif
4083     } else if (gra_state == S_MODAL && gra->buttonhandler != 0)
4084 	{
4085 #ifdef ETRACE
4086         etrace(GTRACE, "  modalloop { buttonhandler: x=%d y=%d but=%d\n", gra_cursorx, gra_cursory, but);
4087 #endif
4088 		BOOLEAN keepon = gra->buttonhandler(gra_cursorx, gra_cursory, but);
4089 #ifdef ETRACE
4090 		etrace(GTRACE, "  modalloop } buttonhandler: keepon=%d el_pleasestop=%d\n", keepon, el_pleasestop);
4091 #endif
4092 		if (keepon || el_pleasestop) gra->exit_loop();
4093     }
4094     gra->toolTimeSlice();
4095 }
4096 
mouseDoubleClickEvent(QMouseEvent * e)4097 void GraphicsDraw::mouseDoubleClickEvent( QMouseEvent *e )
4098 {
4099 #ifdef ETRACE
4100     etrace(GTRACE, "{ GraphicsDraw::mouseDoubleClickEvent %s %d %d,%d %#o\n",
4101 	   stateNames[gra_state], wf->windindex, e->x(), e->y(), e->state());
4102 #endif
4103     gra_lastbuttonstate = e->stateAfter();
4104     if (gra_state == S_USER || gra_state == S_MODAL)
4105 	{
4106 		INTSML but;
4107 #ifdef MACOS
4108 		but = 16;
4109 #else
4110 		switch (e->button())
4111 		{
4112 			case LeftButton: but = 0; break;
4113 			case RightButton: but = 2; break;
4114 			case MidButton: but = 1; break;
4115             default: but = 0;
4116 		}
4117 		but += REALBUTS*8;
4118 #endif
4119 		buttonPressed( e->pos(), but );
4120     }
4121     else QWidget::mouseDoubleClickEvent( e );
4122 
4123 #ifdef ETRACE
4124     etrace(GTRACE, "} GraphicsDraw::mouseDoubleClickEvent\n");
4125 #endif
4126 }
4127 
4128 extern "C" INTBIG sim_window_wavexbar;
4129 
mouseMoveEvent(QMouseEvent * e)4130 void GraphicsDraw::mouseMoveEvent( QMouseEvent *e )
4131 {
4132 	INTSML setcursor, inmenu;
4133 	char *str;
4134 	REGISTER INTBIG x, y, xfx, xfy;
4135 	REGISTER VARIABLE *var;
4136 	INTBIG lx, hx, ly, hy;
4137 	REGISTER WINDOWPART *win;
4138 	COMMANDBINDING commandbinding;
4139 	static INTSML overrodestatus = 0;
4140 
4141 #ifdef ETRACE_
4142 	etrace(GTRACE, "{ GraphicsDraw::mouseMoveEvent %s %d %d,%d %#o\n",
4143 		stateNames[gra_state], wf->windindex, e->x(), e->y(), e->state());
4144 #endif
4145 	gra_lastbuttonstate = e->stateAfter();
4146 	QWidget::mouseMoveEvent( e );
4147 #if 1
4148 	gra_cursorx = e->pos().x();
4149 	gra_cursory = wf->revy - e->pos().y();
4150 	if (gra_cursory < 0) gra_cursory = 0;
4151 	us_state &= ~GOTXY;
4152 #else
4153 	keepCursorPos( e->pos() );
4154 #endif
4155 	if ((e->state() & (LeftButton | RightButton | MidButton)) == 0 || gra->waitforpush)
4156 	{
4157 		/* motion while up considers any window */
4158 
4159 		/* report the menu if over one */
4160 		inmenu = 0;
4161 		if (wf->floating)
4162 		{
4163 			x = (gra_cursorx-us_menulx) / us_menuxsz;
4164 			y = (gra_cursory-us_menuly) / us_menuysz;
4165 			if (x >= 0 && y >= 0 && x < us_menux && y < us_menuy)
4166 			{
4167 				var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_binding_menu_key);
4168 				if (var != NOVARIABLE)
4169 				{
4170 					if (us_menupos <= 1) str = ((char **)var->addr)[y * us_menux + x]; else
4171 						str = ((char **)var->addr)[x * us_menuy + y];
4172 					us_parsebinding(str, &commandbinding);
4173 					if (*commandbinding.command != 0)
4174 					{
4175 						if (commandbinding.nodeglyph != NONODEPROTO)
4176 						{
4177 							ttysetstatusfield(NOWINDOWFRAME, us_statusarc,
4178 								describearcproto(us_curarcproto), TRUE);
4179 							ttysetstatusfield(NOWINDOWFRAME, us_statusnode,
4180 								us_describemenunode(&commandbinding), TRUE);
4181 							inmenu = 1;
4182 							overrodestatus = 1;
4183 						}
4184 						if (commandbinding.arcglyph != NOARCPROTO)
4185 						{
4186 							ttysetstatusfield(NOWINDOWFRAME, us_statusarc,
4187 								describearcproto(commandbinding.arcglyph), TRUE);
4188 							if (us_curnodeproto == NONODEPROTO) str = ""; else
4189 								str = describenodeproto(us_curnodeproto);
4190 							ttysetstatusfield(NOWINDOWFRAME, us_statusnode, str, TRUE);
4191 							inmenu = 1;
4192 							overrodestatus = 1;
4193 						}
4194 					}
4195 					us_freebindingparse(&commandbinding);
4196 				}
4197 			}
4198 		}
4199 		if (inmenu == 0 && overrodestatus != 0)
4200 		{
4201 			ttysetstatusfield(NOWINDOWFRAME, us_statusarc,
4202 				describearcproto(us_curarcproto), TRUE);
4203 			if (us_curnodeproto == NONODEPROTO) str = ""; else
4204 				str = describenodeproto(us_curnodeproto);
4205 			ttysetstatusfield(NOWINDOWFRAME, us_statusnode, str, TRUE);
4206 			overrodestatus = 0;
4207 		}
4208 
4209 		setcursor = 0;
4210 		for(win = el_topwindowpart; win != NOWINDOWPART; win = win->nextwindowpart)
4211 		{
4212 			/* see if the cursor is over a window partition separator */
4213 			if (win->frame != wf) continue;
4214 			us_gettruewindowbounds(win, &lx, &hx, &ly, &hy);
4215 			if (gra_cursorx >= lx-1 && gra_cursorx <= lx+1 && gra_cursory > ly+1 &&
4216 				gra_cursory < hy-1 && us_hasotherwindowpart(lx-10, gra_cursory, win))
4217 			{
4218 				setdefaultcursortype(LRCURSOR);
4219 				setcursor = 1;
4220 				break;
4221 			} else if (gra_cursorx >= hx-1 && gra_cursorx <= hx+1 && gra_cursory > ly+1 &&
4222 				gra_cursory < hy-1 && us_hasotherwindowpart(hx+10, gra_cursory, win))
4223 			{
4224 				setdefaultcursortype(LRCURSOR);
4225 				setcursor = 1;
4226 				break;
4227 			} else if (gra_cursory >= ly-1 && gra_cursory <= ly+1 && gra_cursorx > lx+1 &&
4228 				gra_cursorx < hx-1 && us_hasotherwindowpart(gra_cursorx, ly-10, win))
4229 			{
4230 				setdefaultcursortype(UDCURSOR);
4231 				setcursor = 1;
4232 				break;
4233 			} else if (gra_cursory >= hy-1 && gra_cursory <= hy+1 && gra_cursorx > lx+1 &&
4234 				gra_cursorx < hx-1 && us_hasotherwindowpart(gra_cursorx, hy+10, win))
4235 			{
4236 				setdefaultcursortype(UDCURSOR);
4237 				setcursor = 1;
4238 				break;
4239 			}
4240 
4241 			if (gra_cursorx < win->uselx || gra_cursorx > win->usehx ||
4242 				gra_cursory < win->usely || gra_cursory > win->usehy) continue;
4243 			if ((win->state&WINDOWTYPE) == WAVEFORMWINDOW)
4244 			{
4245 				xfx = muldiv(gra_cursorx - win->uselx, win->screenhx - win->screenlx,
4246 					win->usehx - win->uselx) + win->screenlx;
4247 				xfy = muldiv(gra_cursory - win->usely, win->screenhy - win->screenly,
4248 					win->usehy - win->usely) + win->screenly;
4249 				if (abs(xfx - sim_window_wavexbar) < 2 && xfy >= 560)
4250 				{
4251 					setdefaultcursortype(LRCURSOR);
4252 					setcursor = 1;
4253 					break;
4254 				}
4255 			}
4256 			if ((win->state&WINDOWTYPE) == POPTEXTWINDOW ||
4257 				(win->state&WINDOWTYPE) == TEXTWINDOW)
4258 			{
4259 				EDITOR *ed = win->editor;
4260 				if ((ed->state&EDITORTYPE) == PACEDITOR)
4261 				{
4262 					if (gra_cursorx <= win->usehx - SBARWIDTH &&
4263 						gra_cursory >= win->usely + SBARWIDTH &&
4264 						gra_cursory < ed->revy)
4265 					{
4266 						setdefaultcursortype(IBEAMCURSOR);
4267 						setcursor = 1;
4268 						break;
4269 					}
4270 				}
4271 			}
4272 		}
4273 		if (setcursor == 0) setdefaultcursortype(us_normalcursor);
4274 		if (gra_state == S_TRACK) {
4275 #ifdef ETRACE
4276 		  etrace(GTRACE, "  trackcursor { whileup x=%d y=%d\n",
4277 			 gra_cursorx, gra_cursory);
4278 #endif
4279 		  BOOLEAN keepon = (*gra->whileup)(gra_cursorx, gra_cursory);
4280 #ifdef ETRACE
4281 		  etrace(GTRACE, "  trackcursor } whileup: keepon=%d el_pleasestop=%d\n",
4282 			 keepon, el_pleasestop);
4283 #endif
4284 		  if (keepon || el_pleasestop) gra->exit_loop();
4285 		}
4286 	} else
4287 	{
4288 		/* motion while button down: use last window */
4289 	        if (gra_state == S_TRACK) {
4290 #ifdef ETRACE
4291 		  etrace(GTRACE, "  trackcursor { eachdown x=%d y=%d\n",
4292 			 gra_cursorx, gra_cursory);
4293 #endif
4294 		  BOOLEAN keepon = (*gra->eachdown)(gra_cursorx, gra_cursory);
4295 #ifdef ETRACE
4296 		  etrace(GTRACE, "  trackcursor } eachdown: keepon=%d el_pleasestop=%d\n",
4297 			 keepon, el_pleasestop);
4298 #endif
4299 		  flushscreen();
4300 		  if (keepon || el_pleasestop) gra->exit_loop();
4301 		}
4302 	}
4303 
4304 #ifdef ETRACE_
4305 	//	etrace(GTRACE, "} GraphicsDraw::mouseMoveEvent\n");
4306 #endif
4307 }
4308 
mousePressEvent(QMouseEvent * e)4309 void GraphicsDraw::mousePressEvent( QMouseEvent *e )
4310 {
4311 #ifdef ETRACE
4312     etrace(GTRACE, "{ GraphicsDraw::mousePressEvent %s %d %d,%d %#o\n",
4313 	   stateNames[gra_state], wf->windindex, e->x(), e->y(), e->state());
4314     etrace(GTRACE, "{ GraphicsDraw::mousePressEvent %s %d %d,%d state: %x\n",
4315 	   stateNames[gra_state], wf->windindex, e->x(), e->y(), e->state());
4316 #endif
4317     gra_lastbuttonstate = e->stateAfter();
4318     if (gra_state == S_USER || gra_state == S_MODAL)
4319 	{
4320         INTSML but;
4321 		switch (e->button())
4322 		{
4323 			case LeftButton: but = 0; break;
4324 			case RightButton: but = 2; break;
4325 			case MidButton: but = 1; break;
4326             default: but = 0;
4327 		}
4328 #ifdef MACOS
4329 		but = 0;
4330 		if (e->state() & ShiftButton) but++;      /* Shift key */
4331 		if (e->state() & ControlButton) but += 2; /* Command key */
4332 		if (e->state() & AltButton) but += 4;     /* Option key */
4333 		if (e->state() & MetaButton) but += 8;    /* Control key */
4334 #else
4335 		INTSML modifier = 0;
4336 		if (e->state() & ShiftButton) modifier |= 1;
4337 		if (e->state() & ControlButton) modifier |= 2;
4338 		if (e->state() & AltButton) modifier |= 4;
4339 		/* In Linux, Meta key does not come through in state(), so we
4340 		   fake it using KeyPressEvent<->KeyReleaseEvent and setting
4341 		   metaheld */
4342 		/* Note that under qt, Meta and alt are synonymous */
4343 		if (metaheld) modifier |= 4;
4344 		switch (modifier)
4345 		{
4346 			case 1: but += REALBUTS*1; break;
4347 			case 2: but += REALBUTS*2; break;
4348 			case 4: but += REALBUTS*3; break;
4349 			case 3: but += REALBUTS*4; break;
4350 			case 5: but += REALBUTS*5; break;
4351 			case 6: but += REALBUTS*6; break;
4352 			case 7: but += REALBUTS*7; break;
4353 		}
4354 #endif
4355 		buttonPressed( e->pos(), but );
4356     } else if (gra_state == S_TRACK)
4357 	{
4358         if ((e->state() & (LeftButton | RightButton | MidButton)) == 0)
4359 		{
4360 			keepCursorPos( e->pos() );
4361 			if (gra->waitforpush)
4362 			{
4363 #ifdef ETRACE
4364 				etrace(GTRACE, "  trackcursor { whendown\n");
4365 #endif
4366 				(*gra->whendown)();
4367 #ifdef ETRACE
4368 				etrace(GTRACE, "  trackcursor } whendown\n");
4369 #endif
4370 				gra->waitforpush = 0;
4371 			}
4372 #ifdef ETRACE
4373 			etrace(GTRACE, "  trackcursor { eachdown x=%d y=%d\n", gra_cursorx, gra_cursory);
4374 #endif
4375 			BOOLEAN keepon = (*gra->eachdown)(gra_cursorx, gra_cursory);
4376 #ifdef ETRACE
4377 			etrace(GTRACE, "  trackcursor } eachdown: keepon=%d el_pleasestop=%d\n", keepon, el_pleasestop);
4378 #endif
4379 			if (keepon || el_pleasestop) gra->exit_loop();
4380 		}
4381 		us_state |= DIDINPUT;
4382     }
4383 
4384 #ifdef ETRACE
4385 	etrace(GTRACE, "} GraphicsDraw::mousePressEvent\n");
4386 #endif
4387 }
4388 
mouseReleaseEvent(QMouseEvent * e)4389 void GraphicsDraw::mouseReleaseEvent( QMouseEvent *e )
4390 {
4391 #ifdef ETRACE
4392 	etrace(GTRACE, "{ GraphicsDraw::mouseReleaseEvent %s %d %d,%d %#o\n",
4393 	       stateNames[gra_state], wf->windindex, e->x(), e->y(), e->state());
4394 #endif
4395 	gra_lastbuttonstate = e->stateAfter();
4396 	keepCursorPos( e->pos() );
4397 
4398 	if (gra_state == S_TRACK && !gra->waitforpush) {
4399 	  if ((e->stateAfter() & (LeftButton | RightButton | MidButton)) == 0)
4400 	    gra->exit_loop();
4401 	}
4402 	us_state |= DIDINPUT;
4403 #ifdef ETRACE
4404 	etrace(GTRACE, "} GraphicsDraw::mouseReleaseEvent\n");
4405 #endif
4406 }
4407 
paintEvent(QPaintEvent * e)4408 void GraphicsDraw::paintEvent( QPaintEvent * e)
4409 {
4410     QRect r = e->rect();
4411 #ifdef ETRACE
4412     etrace(GTRACE, "{ GraphicsDraw::paintEvent %d %s %d,%d %d,%d\n",
4413 	   wf->windindex, stateNames[gra_state],
4414 	   r.left(), r.top(), r.right(), r.bottom());
4415 #endif
4416     /* get bounds of display update */
4417     int lx = r.left();
4418     int hx = r.right() + 1;
4419     int ly = r.top();
4420     int hy = r.bottom() + 1;
4421     if (lx < 0) lx = 0;
4422     if (hx > wf->swid) hx = wf->swid;
4423     if (ly < 0) ly = 0;
4424     if (hy > wf->shei) hy = wf->shei;
4425 
4426     /* copy from offscreen buffer to Ximage while doing color mapping */
4427     QPainter p( this );
4428     p.drawImage( r.topLeft(), image, r );
4429 #ifdef ETRACE
4430     etrace(GTRACE, "} GraphicsDraw::paintEvent\n");
4431 #endif
4432 }
4433 
4434 
resizeEvent(QResizeEvent * e)4435 void GraphicsDraw::resizeEvent( QResizeEvent *e )
4436 {
4437     static INTSML inresize = 0;
4438 
4439 #ifdef ETRACE
4440     etrace(GTRACE, "{ GraphicsDraw::resizeEvent %s OldSize=%d,%d NewSize=%d,%d\n",
4441 	   stateNames[gra_state],
4442 	   e->oldSize().width(),
4443 	   e->oldSize().height(),
4444 	   e->size().width(),
4445 	   e->size().height());
4446 #endif
4447     if (width() != wf->swid || height() != wf->shei && inresize == 0) {
4448 		inresize = 1;
4449 
4450 #ifdef ETRACE
4451 		etrace(GTRACE, "{ inresize: wf=%d\n", wf->windindex);
4452 #endif
4453 		recalcSize();
4454 
4455 		if (wf->floating)
4456 		{
4457 			us_startbatch(NOTOOL, FALSE);
4458 			us_drawmenu(1, wf);
4459 			us_endbatch();
4460 		} else
4461 		{
4462 			/* mark start of redisplay */
4463 			us_startbatch(NOTOOL, FALSE);
4464 
4465 			/* save and clear highlighting */
4466 			us_pushhighlight();
4467 			us_clearhighlightcount();
4468 
4469 			/* rewrite status area */
4470 #if 1
4471 			us_drawmenu(-1, wf);
4472 #else
4473 			us_drawmenu(1, wf);
4474 #endif
4475 
4476 			/* restore highlighting */
4477 			us_pophighlight(FALSE);
4478 
4479 			/* finish drawing */
4480 			us_endbatch();
4481 
4482 			us_redostatus(wf);
4483 
4484 			/* describe this change */
4485 			setactivity(_("Window Resize"));
4486 		}
4487 		inresize = 0;
4488 #ifdef ETRACE
4489 		etrace(GTRACE, "} inresize\n");
4490 #endif
4491     }
4492     QWidget::resizeEvent( e );
4493 #ifdef ETRACE
4494     etrace(GTRACE, "} GraphicsDraw::resizeEvent\n");
4495 #endif
4496 }
4497 
wheelEvent(QWheelEvent * e)4498 void GraphicsDraw::wheelEvent( QWheelEvent * e)
4499 {
4500 #ifdef ETRACE
4501     etrace(GTRACE, "{ GraphicsDraw::wheelEvent %s %d %d,%d %#o\n",
4502 		stateNames[gra_state], wf->windindex, e->x(), e->y(), e->state());
4503 #endif
4504     if (gra_state == S_USER || gra_state == S_MODAL)
4505 	{
4506 		INTSML but = e->delta() > 0 ? 3 : 4;
4507 		INTSML modifier = 0;
4508 		if (e->state() & ShiftButton) modifier |= 1;
4509 		if (e->state() & ControlButton) modifier |= 2;
4510 		if (e->state() & AltButton) modifier |= 4;
4511 		switch (modifier)
4512 		{
4513 			case 1: but += REALBUTS*1; break;
4514 			case 2: but += REALBUTS*2; break;
4515 			case 4: but += REALBUTS*3; break;
4516 			case 3: but += REALBUTS*4; break;
4517 			case 5: but += REALBUTS*5; break;
4518 			case 6: but += REALBUTS*6; break;
4519 			case 7: but += REALBUTS*7; break;
4520 		}
4521 		buttonPressed( e->pos(), but );
4522     } else QWidget::wheelEvent( e );
4523 
4524 #ifdef ETRACE
4525 	etrace(GTRACE, "} GraphicsDraw::wheelEvent\n");
4526 #endif
4527 }
4528 
4529 /*
4530  * routine to load the global "el_curwindowframe" and "el_topwindowpart".
4531  * Returns TRUE if the frame was just entered.
4532  */
gra_setcurrentwindowframe(WINDOWFRAME * wf)4533 static BOOLEAN gra_setcurrentwindowframe(WINDOWFRAME *wf)
4534 {
4535 	WINDOWPART *w;
4536 	REGISTER BOOLEAN changed;
4537 
4538 	changed = FALSE;
4539 	if (wf != el_curwindowframe)
4540 	{
4541 		if ((el_curwindowframe == NOWINDOWFRAME || !el_curwindowframe->floating) &&
4542 			(wf == NOWINDOWFRAME || !wf->floating)) changed = TRUE;
4543 	}
4544 	el_curwindowframe = wf;
4545 	if (wf == NOWINDOWFRAME) return(changed);
4546 
4547 	/* ignore floating windows */
4548 	if (wf->floating) return(changed);
4549 
4550 	/* see if the change of window frame invalidates the current window */
4551 	if (el_curwindowpart == NOWINDOWPART || el_curwindowpart->frame != wf)
4552 	{
4553 		/* must choose new window (if not broadcasting) */
4554 		if (db_broadcasting == 0)
4555 		{
4556 			for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
4557 			{
4558 				if (w->frame == wf)
4559 				{
4560 					(void)setvalkey((INTBIG)us_tool, VTOOL, us_current_window_key, (INTBIG)w,
4561 						VWINDOWPART|VDONTSAVE);
4562 					(void)setval((INTBIG)el_curlib, VLIBRARY, "curnodeproto",
4563 						(INTBIG)w->curnodeproto, VNODEPROTO);
4564 					break;
4565 				}
4566 			}
4567 		}
4568 	}
4569 	return(changed);
4570 }
4571 
translatekey(QKeyEvent * e,INTBIG * special)4572 int EApplication::translatekey(QKeyEvent *e, INTBIG *special)
4573 {
4574 	int state;
4575 	char *par[1];
4576 
4577 #ifdef ETRACE
4578 	etrace(GTRACE, "  translatekey: ascii=%#o key=%#o state=%x accepted=%d\n",
4579 	       e->ascii(), e->key(), e->state(), e->isAccepted());
4580 	etrace(GTRACE, "  translatekey: ascii=%#o key=%x state=%x accepted=%d\n",
4581 	       e->ascii(), e->key(), e->state(), e->isAccepted());
4582 #endif
4583 	gra_lastbuttonstate = e->stateAfter();
4584 	*special = 0;
4585 #if 1
4586 	if (e->ascii() >= ' ' && e->ascii() < 0177 && (e->state() & ControlButton) == 0) return(e->ascii());
4587 #endif
4588 	if (e->key() > 0 && e->key() < 0200) state = e->key(); else
4589 	{
4590 		switch (e->key())
4591 		{
4592 			case Key_BackSpace:state = BACKSPACEKEY;   break;
4593 			case Key_Tab:      state = 011;            break;
4594 			//case XK_Linefeed:  state = 012;            break;
4595 			case Key_Return:   state = 015;            break;
4596 			case Key_Escape:   state = ESCKEY;         break;
4597 			case Key_Delete:   state = 0177;           break;
4598 			case Key_Enter:    state = 015;            break;
4599 
4600 			case Key_End:
4601 				/* shift to end of messages window */
4602 #if 0
4603 				tp = XmTextGetLastPosition(gra_messageswidget);
4604 				XmTextSetSelection(gra_messageswidget, tp, tp, 0);
4605 				XmTextSetInsertionPosition(gra_messageswidget, tp);
4606 				XmTextShowPosition(gra_messageswidget, tp);
4607 #endif
4608 				e->accept();
4609 #ifdef ETRACE
4610 				etrace(GTRACE, "  EApplication::translatekey } special\n");
4611 #endif
4612 				return(0);
4613 			case Key_F14:
4614 				us_undo(0, par);
4615 				e->accept();
4616 #ifdef ETRACE
4617 				etrace(GTRACE, "  EApplication::translatekey } special\n");
4618 #endif
4619 				return(0);
4620 			case Key_F16:
4621 				par[0] = "copy";
4622 				us_text(1, par);
4623 				e->accept();
4624 #ifdef ETRACE
4625 				etrace(GTRACE, "  EApplication::translatekey } special\n");
4626 #endif
4627 				return(0);
4628 			case Key_F18:
4629 				par[0] = "paste";
4630 				us_text(1, par);
4631 				e->accept();
4632 #ifdef ETRACE
4633 				etrace(GTRACE, "  EApplication::translatekey } special\n");
4634 #endif
4635 				return(0);
4636 			case Key_F20:
4637 				par[0] = "cut";
4638 				us_text(1, par);
4639 				e->accept();
4640 #ifdef ETRACE
4641 				etrace(GTRACE, "  EApplication::translatekey } special\n");
4642 #endif
4643 				return(0);
4644 
4645 			case Key_Left:
4646 				state = 0;
4647 				*special = SPECIALKEYDOWN|(SPECIALKEYARROWL<<SPECIALKEYSH);
4648 				if ((e->state() & ShiftButton) != 0) *special |= SHIFTDOWN;
4649 				break;
4650 			case Key_Right:
4651 				state = 0;
4652 				*special = SPECIALKEYDOWN|(SPECIALKEYARROWR<<SPECIALKEYSH);
4653 				if ((e->state() & ShiftButton) != 0) *special |= SHIFTDOWN;
4654 				break;
4655 			case Key_Up:
4656 				state = 0;
4657 				*special = SPECIALKEYDOWN|(SPECIALKEYARROWU<<SPECIALKEYSH);
4658 				if ((e->state() & ShiftButton) != 0) *special |= SHIFTDOWN;
4659 				break;
4660 			case Key_Down:
4661 				state = 0;
4662 				*special = SPECIALKEYDOWN|(SPECIALKEYARROWD<<SPECIALKEYSH);
4663 				if ((e->state() & ShiftButton) != 0) *special |= SHIFTDOWN;
4664 				break;
4665 
4666 			case Key_F1:
4667 				state = 0;
4668 				*special = SPECIALKEYDOWN|(SPECIALKEYF1<<SPECIALKEYSH);
4669 				break;
4670 			case Key_F2:
4671 				state = 0;
4672 				*special = SPECIALKEYDOWN|(SPECIALKEYF2<<SPECIALKEYSH);
4673 				break;
4674 			case Key_F3:
4675 				state = 0;
4676 				*special = SPECIALKEYDOWN|(SPECIALKEYF3<<SPECIALKEYSH);
4677 				break;
4678 			case Key_F4:
4679 				state = 0;
4680 				*special = SPECIALKEYDOWN|(SPECIALKEYF4<<SPECIALKEYSH);
4681 				break;
4682 			case Key_F5:
4683 				state = 0;
4684 				*special = SPECIALKEYDOWN|(SPECIALKEYF5<<SPECIALKEYSH);
4685 				break;
4686 			case Key_F6:
4687 				state = 0;
4688 				*special = SPECIALKEYDOWN|(SPECIALKEYF6<<SPECIALKEYSH);
4689 				break;
4690 			case Key_F7:
4691 				state = 0;
4692 				*special = SPECIALKEYDOWN|(SPECIALKEYF7<<SPECIALKEYSH);
4693 				break;
4694 			case Key_F8:
4695 				state = 0;
4696 				*special = SPECIALKEYDOWN|(SPECIALKEYF8<<SPECIALKEYSH);
4697 				break;
4698 			case Key_F9:
4699 				state = 0;
4700 				*special = SPECIALKEYDOWN|(SPECIALKEYF9<<SPECIALKEYSH);
4701 				break;
4702 			case Key_F10:
4703 				state = 0;
4704 				*special = SPECIALKEYDOWN|(SPECIALKEYF10<<SPECIALKEYSH);
4705 				break;
4706 			case Key_F11:
4707 				state = 0;
4708 				*special = SPECIALKEYDOWN|(SPECIALKEYF11<<SPECIALKEYSH);
4709 				break;
4710 			case Key_F12:
4711 				state = 0;
4712 				*special = SPECIALKEYDOWN|(SPECIALKEYF12<<SPECIALKEYSH);
4713 				break;
4714 
4715 			default:           state = 0;     break;
4716 		}
4717 	}
4718 	if (state == 0 && *special == 0) return(0);
4719 
4720 	if ((e->state() & ControlButton) != 0)
4721 	{
4722 		if (gra_messages_typingin == 0)
4723 		{
4724 			*special |= ACCELERATORDOWN;
4725 			state = tolower(state);
4726 		} else
4727 		{
4728 			if (state >= 'a' && state <= 'z') state -= 'a' - 1; else
4729 				if (state >= 'A' && state <= 'Z') state -= 'A' - 1;
4730 		}
4731 	}
4732 	return(state);
4733 }
4734 
recalcSize()4735 void GraphicsDraw::recalcSize()
4736 {
4737 	int i;
4738 
4739 	/* allocate QImage for the offscreen buffer */
4740 	QImage newImage;
4741 	if (!newImage.create( width(), height(), 8, 256 )) return;
4742 	newImage.fill( 0 );
4743 	for (i = 0; i < 256; i++) newImage.setColor( i, gra_colortable[i] );
4744 	image = newImage;
4745 	wf->rowstart = newImage.jumpTable();
4746 
4747 #ifdef ETRACE
4748 	etrace(GTRACE, "  gra_recalcsize: wf=%d swid=%d shei=%d\n",
4749 	       wf->windindex, width(), height());
4750 #endif
4751 	wf->swid = width();
4752 	wf->shei = height();
4753 	wf->revy = wf->shei - 1;
4754 }
4755 
4756 /* error events */
gra_sigill_trap(void)4757 RETSIGTYPE gra_sigill_trap(void)
4758 {
4759 	(void)signal(SIGILL, (SIGNALCAST)gra_sigill_trap);
4760 	error(_("FATAL ERROR: An illegal instruction has been trapped"));
4761 }
4762 
gra_sigfpe_trap(void)4763 RETSIGTYPE gra_sigfpe_trap(void)
4764 {
4765 	(void)signal(SIGFPE, (SIGNALCAST)gra_sigfpe_trap);
4766 	error(_("FATAL ERROR: A numerical error has occurred"));
4767 }
4768 
gra_sigbus_trap(void)4769 RETSIGTYPE gra_sigbus_trap(void)
4770 {
4771 	(void)signal(SIGBUS, (SIGNALCAST)gra_sigbus_trap);
4772 	error(_("FATAL ERROR: A bus error has occurred"));
4773 }
4774 
gra_sigsegv_trap(void)4775 RETSIGTYPE gra_sigsegv_trap(void)
4776 {
4777 	(void)signal(SIGSEGV, (SIGNALCAST)gra_sigsegv_trap);
4778 	error(_("FATAL ERROR: A segmentation violation has occurred"));
4779 }
4780 
4781 /*************************** SESSION LOGGING ROUTINES ***************************/
4782 
4783 /* Session Playback */
4784 
4785 /*
4786  * routine to create a session logging file
4787  */
logstartrecord(void)4788 void logstartrecord(void)
4789 {
4790 #ifdef ETRACE
4791 	etrace(GTRACE, "{}logstartrecord\n");
4792 #endif
4793 }
4794 
4795 /*
4796  * routine to begin playback of session logging file "file".  The routine
4797  * returns true if there is an error.  If "all" is nonzero, playback
4798  * the entire file with no prompt.
4799  */
logplayback(char * file)4800 BOOLEAN logplayback(char *file)
4801 {
4802 #ifdef ETRACE
4803 	etrace(GTRACE, "{}logplayback: file=%s result=1\n", file);
4804 #else
4805 	Q_UNUSED( file );
4806 #endif
4807 	return(TRUE);
4808 }
4809 
4810 /*
4811  * routine to terminate session logging
4812  */
logfinishrecord(void)4813 void logfinishrecord(void)
4814 {
4815 #ifdef ETRACE
4816 	etrace(GTRACE, "{}logfinishrecord\n");
4817 #endif
4818 }
4819 
4820 /****************************** MENUS ******************************/
4821 
getacceleratorstrings(char ** acceleratorstring,char ** acceleratorprefix)4822 void getacceleratorstrings(char **acceleratorstring, char **acceleratorprefix)
4823 {
4824 #ifdef MACOS
4825 	*acceleratorstring = "Cmd";
4826 	*acceleratorprefix = "Cmd-";
4827 #else
4828 	*acceleratorstring = "Ctrl";
4829 	*acceleratorprefix = "Ctrl-";
4830 #endif
4831 }
4832 
getinterruptkey(void)4833 char *getinterruptkey(void)
4834 {
4835 #ifdef MACOS
4836 	return(_("Command-."));
4837 #else
4838 	return(_("Control-C in Messages Window"));
4839 #endif
4840 }
4841 
nativepopupmenu(POPUPMENU ** menuptr,BOOLEAN header,INTBIG left,INTBIG top)4842 INTBIG nativepopupmenu(POPUPMENU **menuptr, BOOLEAN header, INTBIG left, INTBIG top)
4843 {
4844 	INTBIG i, j, submenuindex, submenus;
4845 	POPUPMENUITEM *mi, *submi;
4846 	POPUPMENU *menu, **subpmlist;
4847 	REGISTER WINDOWFRAME *wf;
4848 	REGISTER USERCOM *uc;
4849 	INTBIG menuresult;
4850 
4851 	menu = *menuptr;
4852 	wf = el_curwindowframe;
4853 	QWidget *parent = wf != NOWINDOWFRAME ? wf->draw->parentWidget() : gra->mainWidget();
4854 	EPopupMenu qmenu( parent, *menuptr );
4855 	if (header)
4856 	{
4857 		qmenu.insertItem( QString::fromLocal8Bit( menu->header ), -1 );
4858 		qmenu.insertSeparator();
4859 	}
4860 
4861 	/* count the number of submenus */
4862 	submenus = 0;
4863 	subpmlist = 0;
4864 	for(j=0; j<menu->total; j++)
4865 	{
4866 		mi = &menu->list[j];
4867 		if (*mi->attribute != 0 && mi->response != NOUSERCOM &&
4868 			mi->response->menu != NOPOPUPMENU) submenus++;
4869 	}
4870 	if (submenus > 0)
4871 	{
4872 		subpmlist = (POPUPMENU **)emalloc(submenus * (sizeof (POPUPMENU *)), us_tool->cluster);
4873 		if (subpmlist == 0) return(-1);
4874 	}
4875 
4876 	/* load the menus */
4877 	submenus = 0;
4878 	for(j=0; j<menu->total; j++)
4879 	{
4880 		mi = &menu->list[j];
4881 		mi->changed = FALSE;
4882 		if (*mi->attribute == 0)
4883 		{
4884 			qmenu.insertSeparator();
4885 		} else
4886 		{
4887 			uc = mi->response;
4888 			if (uc != NOUSERCOM && uc->menu != NOPOPUPMENU)
4889 			{
4890 				QPopupMenu *submenu = new QPopupMenu( &qmenu );
4891 				if (submenu == 0) return(-1);
4892 				qmenu.insertItem( QString::fromLocal8Bit( mi->attribute ), submenu, j );
4893 				subpmlist[submenus] = uc->menu;
4894 				submenus++;
4895 				for(i=0; i<uc->menu->total; i++)
4896 				{
4897 					submi = &uc->menu->list[i];
4898 					submenu->insertItem( QString::fromLocal8Bit( submi->attribute ), (submenus<<16) | i );
4899 				}
4900 			} else
4901 			{
4902 				QString qstr = QString::fromLocal8Bit( mi->attribute );
4903 				if (mi->value)
4904 				{
4905 					qstr += "\t" + QString::fromLocal8Bit( mi->value );
4906 				}
4907 				qmenu.insertItem( qstr, j );
4908 			}
4909 		}
4910 	}
4911 
4912 	QPoint pos;
4913 	if (left >= 0 && top >= 0 && el_curwindowframe != NOWINDOWFRAME)
4914 	{
4915 		pos = el_curwindowframe->draw->mapToGlobal( QPoint( left, el_curwindowframe->revy - top ) );
4916 	}
4917 	else pos = QCursor::pos();
4918 	menuresult = qmenu.exec( pos );
4919 	if (menuresult >= 0)
4920 	{
4921 		submenuindex = menuresult >> 16;
4922 		if (submenuindex != 0) *menuptr = subpmlist[submenuindex-1];
4923 	}
4924 	if (submenus > 0)
4925 	{
4926 		efree((char *)subpmlist);
4927 	}
4928 	if (menuresult < 0) return(-1);
4929 	return(menuresult & 0xFFFF);
4930 }
4931 
EPopupMenu(QWidget * parent,struct Ipopupmenu * menu)4932 EPopupMenu::EPopupMenu( QWidget *parent, struct Ipopupmenu *menu )
4933 	: QPopupMenu( parent ), menu( menu )
4934 {
4935 }
4936 
keyPressEvent(QKeyEvent * e)4937 void EPopupMenu::keyPressEvent( QKeyEvent *e )
4938 {
4939 	int i;
4940 	for(i=0; i<menu->total; i++)
4941 	{
4942 		if (isItemActive( i )) break;
4943 	}
4944 	if (i < menu->total)
4945 	{
4946 		POPUPMENUITEM *mi = &menu->list[i];
4947 		USERCOM *uc = mi->response;
4948 		if (*mi->attribute != 0 && (uc == NOUSERCOM || uc->menu == NOPOPUPMENU) &&
4949 			mi->value != 0 && mi->maxlen > 0)
4950 		{
4951 			int key = e->key();
4952 			BOOLEAN changed = FALSE;
4953 			if ((e->state() & ControlButton) && key == Key_U)
4954 			{ /* clear */
4955 				mi->value[0] = 0;
4956 				changed = TRUE;
4957 			} else if ((e->state() & ControlButton) && key == Key_H ||
4958 				!e->state() && (key == Key_Backspace || key == Key_Delete))
4959 			{ /* backspace */
4960 				INTBIG len = estrlen(mi->value);
4961 				if (len > 0) mi->value[len - 1] = 0;
4962 				changed = TRUE;
4963 			} else if (!e->state() && e->text().length() == 1 && e->text()[0] >= ' ')
4964 			{ /* append */
4965 				if (!mi->changed) mi->value[0] = 0;
4966 				INTBIG len = estrlen(mi->value);
4967 				if (len < mi->maxlen)
4968 				{
4969 					char *str = EApplication::localize( e->text() );
4970 					mi->value[len] = *str;
4971 					mi->value[len + 1] = 0;
4972 				}
4973 				changed = TRUE;
4974 			}
4975 			if (changed)
4976 			{
4977 				QString qstr = QString::fromLocal8Bit( mi->attribute );
4978 				if (mi->value)
4979 				{
4980 					qstr += "\t" + QString::fromLocal8Bit( mi->value );
4981 				}
4982 				changeItem( qstr, i );
4983 				mi->changed = TRUE;
4984 				return;
4985 			}
4986 		}
4987 	}
4988 	QPopupMenu::keyPressEvent( e );
4989 }
4990 
nativemenuload(INTBIG count,char * par[])4991 void nativemenuload(INTBIG count, char *par[])
4992 {
4993 	REGISTER INTBIG i;
4994 	REGISTER WINDOWFRAME *wf;
4995 
4996 	/* remember the top-level pulldown menus */
4997 	for(i=0; i<count; i++) gra_pulldowns_[i] = us_getpopupmenu(par[i]);
4998 	gra_pulldownmenucount_ = count;
4999 
5000 	/* build the pulldown menu bar */
5001 #ifdef USEMDI
5002 	gra->mw->pulldownmenuload();
5003 #else
5004 	for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
5005 	{
5006 		if (wf->floating) continue;
5007 		/* load menus into this window */
5008 		EMainWindow *qwin = (EMainWindow*)wf->draw->parentWidget();
5009 		qwin->pulldownmenuload();
5010 	}
5011 #  ifdef MESSMENU
5012 	EMainWindow *ewin = (EMainWindow*)gra->messages->parentWidget();
5013 	ewin->pulldownmenuload();
5014 #  endif
5015 #endif
5016 }
5017 
nativemenurename(POPUPMENU * pm,INTBIG pindex)5018 void nativemenurename(POPUPMENU *pm, INTBIG pindex)
5019 {
5020 	REGISTER WINDOWFRAME *wf;
5021 
5022 #ifdef ETRACE_
5023 	POPUPMENUITEM *mi = &pm->list[pindex];
5024 	etrace(GTRACE, "{ nativemenurename %s %d '%s'\n", pm->name, pindex,
5025 	       mi->attribute != 0 ? mi->attribute : "");
5026 #endif
5027 	/* build the pulldown menu bar */
5028 #ifdef USEMDI
5029 	gra->mw->nativemenurename( pm, pindex );
5030 #else
5031 	for(wf = el_firstwindowframe; wf != NOWINDOWFRAME; wf = wf->nextwindowframe)
5032 	{
5033 		if (wf->floating) continue;
5034 		/* load menus into this window */
5035 		EMainWindow *qwin = (EMainWindow*)wf->draw->parentWidget();
5036 		qwin->nativemenurename( pm, pindex );
5037 	}
5038 #  ifdef MESSMENU
5039 	EMainWindow *ewin = (EMainWindow*)gra->messages->parentWidget();
5040 	ewin->nativemenurename( pm, pindex );
5041 #  endif
5042 #endif
5043 #ifdef ETRACE_
5044 	etrace(GTRACE, "} nativemenurename\n");
5045 #endif
5046 }
5047 
EMainWindow(QWidget * parent,char * name,WFlags f,BOOLEAN status)5048 EMainWindow::EMainWindow( QWidget *parent, char *name, WFlags f, BOOLEAN status )
5049 	: QMainWindow( parent, name, f )
5050 {
5051     pulldownmenus = 0;
5052     pulldowns = 0;
5053 	pulldownmenucount = 0;
5054     if ( status )
5055 	{
5056         for (int i = 0; i < gra_indicatorcount; i++)
5057 		{
5058             statusItems[i] = new EStatusItem( statusBar() );
5059 			STATUSFIELD *sf = gra_statusfields[i];
5060 			statusBar()->addWidget( statusItems[i], sf->endper - sf->startper );
5061 			statusItems[i]->setText( gra_statusfieldtext[i] );
5062 		}
5063     }
5064 }
5065 
~EMainWindow()5066 EMainWindow::~EMainWindow()
5067 {
5068 	if (pulldownmenus != 0) efree((char*)pulldownmenus);
5069 	if (pulldowns != 0)
5070 	{
5071 		for (int i = 0; i < pulldownmenucount; i++)
5072 		{
5073 			if (pulldowns[i] != NOSTRING) efree(pulldowns[i]);
5074 		}
5075 		efree((char*)pulldowns);
5076 	}
5077 }
5078 
pulldownmenuload()5079 void EMainWindow::pulldownmenuload()
5080 {
5081 	menuBar()->clear();
5082 	for(int i=0; i<gra_pulldownmenucount_; i++)
5083 	{
5084 		POPUPMENU *pm = gra_pulldowns_[i];
5085 		if (pm == NOPOPUPMENU) continue;
5086 		INTSML menuindex = pulldownindex(pm);
5087 		if (menuindex < 0) continue;
5088 		QPopupMenu *menu = pulldownmenus[menuindex];
5089 		if (menu != NULL)
5090 			menuBar()->insertItem( QString::fromLocal8Bit( pm->header ), menu );
5091 	}
5092 }
5093 
nativemenurename(POPUPMENU * pm,INTBIG pindex)5094 void EMainWindow::nativemenurename(POPUPMENU *pm, INTBIG pindex)
5095 {
5096 	Q_UNUSED( pindex );
5097 
5098 	int i;
5099 
5100 	/* find this pulldown menu */
5101 	for(i=0; i<pulldownmenucount; i++)
5102 		if (pulldowns[i] != NOSTRING && namesame(pulldowns[i], pm->name) == 0) break;
5103 	if (i >= pulldownmenucount) return;
5104 
5105 	pulldownmenus[i]->clear();
5106 	makepdmenu( pm, i);
5107 }
5108 
5109 /*
5110 * Routine to create a pulldown menu from popup menu "pm".
5111 * Returns an index to the table of pulldown menus (-1 on error).
5112 */
pulldownindex(POPUPMENU * pm)5113 INTSML EMainWindow::pulldownindex(POPUPMENU *pm)
5114 {
5115     REGISTER INTBIG i, pindex;
5116     QPopupMenu **newpulldownmenus;
5117     char **newpulldowns;
5118 
5119     /* see if it is in the list already */
5120     for(i=0; i<pulldownmenucount; i++)
5121 	    if (pulldowns[i] != NOSTRING && namesame(pulldowns[i], pm->name) == 0) return(i);
5122 
5123     /* allocate new space with one more */
5124     newpulldownmenus = (QPopupMenu **)emalloc((pulldownmenucount+1) *
5125 	    (sizeof (QPopupMenu *)), us_tool->cluster);
5126     if (newpulldownmenus == 0) return(-1);
5127     newpulldowns = (char **)emalloc((pulldownmenucount+1) *
5128 	    (sizeof (char *)), us_tool->cluster);
5129     if (newpulldowns == 0) return(-1);
5130 
5131     /* copy former arrays then delete them */
5132     for(i=0; i<pulldownmenucount; i++)
5133     {
5134 	    newpulldownmenus[i] = pulldownmenus[i];
5135 	    newpulldowns[i] = pulldowns[i];
5136     }
5137     if (pulldownmenucount != 0)
5138     {
5139 	    efree((char *)pulldownmenus);
5140 	    efree((char *)pulldowns);
5141     }
5142 
5143     pulldownmenus = newpulldownmenus;
5144     pulldowns = newpulldowns;
5145 
5146     pindex = pulldownmenucount++;
5147     pulldowns[pindex] = NOSTRING;
5148     pulldownmenus[pindex] = new QPopupMenu( this );
5149     if (pulldownmenus[pindex] == 0)
5150 	    return(-1);
5151     connect( pulldownmenus[pindex], SIGNAL(activated(int)), SLOT(menuAction(int)));
5152     (void)allocstring(&pulldowns[pindex], pm->name, us_tool->cluster);
5153     makepdmenu( pm, pindex);
5154      return(pindex);
5155 }
5156 
5157 /*
5158  * Routine to create pulldown menu number "value" from the popup menu in "pm" and return
5159  * the menu handle.
5160  */
makepdmenu(POPUPMENU * pm,INTSML value)5161 void EMainWindow::makepdmenu(POPUPMENU *pm, INTSML value)
5162 {
5163 	QPopupMenu *menu = pulldownmenus[value];
5164 	char *pt;
5165 
5166 	/* build the actual menu */
5167 	for(int i=0; i<pm->total; i++)
5168 	{
5169 		POPUPMENUITEM *mi = &pm->list[i];
5170 		USERCOM *uc = mi->response;
5171 		int id = value*(1 << 16) + i;
5172 		if (uc->active < 0)
5173 		{
5174 			if (*mi->attribute == 0)
5175 			{
5176 				/* separator */
5177 				menu->insertSeparator();
5178 			} else
5179 			{
5180 				/* dimmed item (DIM IT!!!) */
5181 				menu->insertItem( QString::fromLocal8Bit( mi->attribute ), id );
5182 				menu->setItemEnabled( id, FALSE );
5183 			}
5184 			continue;
5185 		}
5186 
5187 		/* see if this command is another menu */
5188 		if (uc->menu != NOPOPUPMENU)
5189 		{
5190 			int submenuindex = pulldownindex(uc->menu);
5191 			QPopupMenu *submenu = pulldownmenus[submenuindex];
5192 			if (submenu != 0) menu->insertItem( QString::fromLocal8Bit( mi->attribute ), submenu, id );
5193 			continue;
5194 		}
5195 
5196 		/* see if there is a check */
5197 		int checked = -1;
5198 		char myline[256];
5199 		strcpy( myline, mi->attribute );
5200 		int len = strlen(myline) - 1;
5201 		if (myline[len] == '<')
5202 		{
5203 			myline[len] = 0;
5204 			if (myline[0] == '>')
5205 			{
5206 				checked = 1;
5207 				strcpy(myline, &myline[1]);
5208 			} else
5209 			{
5210 				checked = 0;
5211 			}
5212 		}
5213 
5214 		/* get command title and accelerator */
5215 		for(pt = myline; *pt != 0; pt++) if (*pt == '/' || *pt == '\\') break;
5216 		if (*pt != 0)
5217 		{
5218 			INTSML key;
5219 			INTBIG special;
5220 			(void)us_getboundkey(pt, &key, &special);
5221 #ifdef MACOSX
5222 			esnprintf(pt, 50, x_("     %s"), us_describeboundkey(key, special, 1));
5223 #else
5224 			esnprintf(pt, 50, x_("\t%s"), us_describeboundkey(key, special, 1));
5225 #endif
5226 		}
5227 #ifdef ETRACE
5228 		etrace(GTRACE, "  set menu entry '%s'\n", myline );
5229 #endif
5230 		menu->insertItem( QString::fromLocal8Bit( myline ) , id );
5231 		if (checked != -1) menu->setItemChecked( id, checked > 0 );
5232 	}
5233 }
5234 
menuAction(int id)5235 void EMainWindow::menuAction( int id )
5236 {
5237 	/* handle menu events */
5238 	INTSML low = id >> 16;
5239 	INTSML high = id & 0xFFFF;
5240 	BOOLEAN verbose;
5241 	static INTSML ntry = 0;
5242 #ifdef ETRACE
5243 	etrace(GTRACE, "{ menuAction: %s %d %d\n", stateNames[gra_state], low, high);
5244 #endif
5245 	if (gra_state != S_USER && ntry < 2)
5246 	{
5247 		ttyputmsg(_("menu disabled in input mode, state=%d, ntry=%d"), gra_state,ntry);
5248 		ttybeep(SOUNDBEEP, TRUE);
5249 #ifdef ETRACE
5250 		etrace(GTRACE, "} menuAction: ignored\n");
5251 #endif
5252 		ntry++;
5253 		return;
5254 	}
5255 	ntry = 0;
5256 	POPUPMENU *pm = us_getpopupmenu(pulldowns[low]);
5257 	if (high >= 0 && high < pm->total)
5258 	{
5259 		us_state |= DIDINPUT;
5260 		us_state &= ~GOTXY;
5261 #ifdef ETRACE
5262 		etrace(GTRACE, "  menuAction: DIDINPUT GOTXY\n");
5263 #endif
5264 		setdefaultcursortype(NULLCURSOR);
5265 		us_forceeditchanges();
5266 		if ((us_tool->toolstate&ECHOBIND) != 0) verbose = TRUE; else
5267 			verbose = FALSE;
5268 		us_execute(pm->list[high].response, verbose, TRUE, TRUE);
5269 		db_setcurrenttool(us_tool);
5270 		setactivity(pm->list[high].attribute);
5271 		gra->toolTimeSlice();
5272 	}
5273 #ifdef ETRACE
5274 	etrace(GTRACE, "}  menuAction\n");
5275 #endif
5276 }
5277 
addStatusItem(int stretch,char * str)5278 void EMainWindow::addStatusItem( int stretch, char *str )
5279 {
5280 	EStatusItem *statusItem = new EStatusItem( statusBar() );
5281 	statusItem->setText( str );
5282 	statusItems[gra_indicatorcount] = statusItem;
5283 	statusItem->show();
5284 	statusBar()->addWidget( statusItem, stretch );
5285 }
5286 
removeStatusItem(int i)5287 void EMainWindow::removeStatusItem( int i )
5288 {
5289 	EStatusItem *statusItem = statusItems[i];
5290 	statusBar()->removeWidget( statusItem );
5291 	delete statusItem;
5292 	for(int j=i+1; j<gra_indicatorcount; j++)
5293 	{
5294 		statusItems[j-1] = statusItems[j];
5295 		statusItems[j] = 0;
5296 	}
5297 }
5298 
changeStatusItem(int i,char * str)5299 void EMainWindow::changeStatusItem( int i, char *str )
5300 {
5301 	EStatusItem *statusItem = statusItems[i];
5302 
5303 	/* load the string */
5304 	statusItem->setText( str );
5305 }
5306 
EStatusItem(QWidget * parent,char * name)5307 EStatusItem::EStatusItem( QWidget *parent, char *name )
5308     : QFrame( parent, name )
5309 {
5310 }
5311 
setText(const QString & text)5312 void EStatusItem::setText( const QString &text )
5313 {
5314     stext = text;
5315 	update( contentsRect() );
5316 }
5317 
drawContents(QPainter * p)5318 void EStatusItem::drawContents( QPainter *p )
5319 {
5320 #ifdef MACOSX
5321 	QFont curfont = p->font();
5322 	int size = curfont.pointSize();
5323 	if (size != 9)
5324 	{
5325 		curfont.setPointSize(9);
5326 		p->setFont(curfont);
5327 	}
5328 #endif
5329     p->drawText( contentsRect(), AlignAuto | AlignVCenter | SingleLine, stext );
5330 }
5331 
5332 /****************************** PRINTING ******************************/
5333 
5334 /* call this routine to print the current window */
printewindow(void)5335 void printewindow(void)
5336 {
5337 	REGISTER WINDOWPART *win;
5338 	REGISTER WINDOWFRAME *oldWf, *wf;
5339 	INTBIG lx, hx, ly, hy, i, margin, marginpixels;
5340 	REGISTER VARIABLE *var;
5341 	static QPrinter *printer = 0;
5342 	QPainter p;
5343 	QRect r;
5344 	QRgb white, oldbackground;
5345 
5346 	win = el_curwindowpart;
5347 	if (win == NOWINDOWPART)
5348 	{
5349 		ttyputerr(_("No current window to print"));
5350 		return;
5351 	}
5352 	oldWf = win->frame;
5353 
5354 	if (printer == 0)
5355 		printer = new QPrinter( QPrinter::PrinterResolution );
5356 /*	printer->setPageSize(QPrinter::Custom); */
5357 	if (printer->setup(gra->mw))
5358 	{
5359 		QPaintDeviceMetrics pdm( printer );
5360 		if (!p.begin(printer)) return;
5361 
5362 		/* determine margins */
5363 		var = getval((INTBIG)io_tool, VTOOL, VFRACT, x_("IO_postscript_margin"));
5364 		if (var == NOVARIABLE) margin = WHOLE/4*3; else
5365 			margin = var->addr;
5366 		marginpixels = muldiv(margin, pdm.logicalDpiX(), WHOLE);
5367 		/* ttyputmsg(M_("Printer width=%d height=%d margin=%d"), pdm.width(), pdm.height(), marginpixels); */
5368 
5369 		INTBIG saveslx = win->screenlx;
5370 		INTBIG saveshx = win->screenhx;
5371 		INTBIG savesly = win->screenly;
5372 		INTBIG saveshy = win->screenhy;
5373 		INTBIG saveulx = win->uselx;
5374 		INTBIG saveuhx = win->usehx;
5375 		INTBIG saveuly = win->usely;
5376 		INTBIG saveuhy = win->usehy;
5377 
5378 		wf = (WINDOWFRAME *)emalloc((sizeof (WINDOWFRAME)), us_tool->cluster);
5379 		if (wf == 0) return;
5380 		win->frame = wf;
5381 		wf->draw = 0;
5382 		wf->starttime = 0;
5383 		wf->offscreendirty = FALSE;
5384 		wf->copyleft = wf->copyright = wf->copytop = wf->copybottom = 0;
5385 		wf->floating = FALSE;
5386 		wf->swid = pdm.width();
5387 		wf->shei = pdm.height();
5388 		wf->revy = wf->shei - 1;
5389 		wf->nextwindowframe = NOWINDOWFRAME;
5390 		wf->firstvar = NOVARIABLE;
5391 		wf->numvar = 0;
5392 		QImage image;
5393 		if (!image.create( pdm.width(), pdm.height(), 8, 256))
5394 		{
5395 			efree((CHAR *)wf);
5396 			return;
5397 		}
5398 		image.fill( 0 );
5399 		white = qRgb(255, 255, 255);
5400 		image.setColor( 0, white);
5401 		for (i = 1; i < 256; i++) image.setColor( i, gra_colortable[i] );
5402 		wf->rowstart = image.jumpTable();
5403 
5404 		win->uselx = marginpixels;
5405 		win->usehx = wf->swid - marginpixels;
5406 		win->usely = marginpixels;
5407 		win->usehy = wf->shei - marginpixels;
5408 
5409 		INTBIG wlx, whx, wly, why;
5410 		INTBIG slx, shx, sly, shy;
5411 		NODEPROTO *np = win->curnodeproto;
5412 		if ((win->state&WINDOWTYPE) == WAVEFORMWINDOW || np == NONODEPROTO)
5413 		{
5414 			wlx = win->screenlx;
5415 			whx = win->screenhx;
5416 			wly = win->screenly;
5417 			why = win->screenhy;
5418 		} else
5419 		{
5420 			(void)io_getareatoprint(np, &wlx, &whx, &wly, &why, FALSE);
5421 			us_squarescreen(win, NOWINDOWPART, FALSE, &wlx, &whx, &wly, &why, 1);
5422 		}
5423 
5424 		win->screenlx = slx = wlx;
5425 		win->screenhx = shx = whx;
5426 		win->screenly = sly = wly;
5427 		win->screenhy = shy = why;
5428 		computewindowscale(win);
5429 
5430 		/* redraw the window in the larger buffer */
5431 		gra_noflush = TRUE;
5432 		if ((win->state&WINDOWTYPE) == WAVEFORMWINDOW)
5433 		{
5434 			(*win->redisphandler)(win);
5435 		} else
5436 		{
5437 			us_redisplaynow(win, TRUE);
5438 			us_endchanges(win);
5439 		}
5440 		gra_noflush = FALSE;
5441 		(void)us_makescreen(&slx, &sly, &shx, &shy, win);
5442 
5443 		/* restore the normal state of the window */
5444 		win->frame = oldWf;
5445 		win->screenlx = saveslx;
5446 		win->screenhx = saveshx;
5447 		win->screenly = savesly;
5448 		win->screenhy = saveshy;
5449 		win->uselx = saveulx;
5450 		win->usehx = saveuhx;
5451 		win->usely = saveuly;
5452 		win->usehy = saveuhy;
5453 		computewindowscale(win);
5454 
5455 		r.rTop() = 0; r.rBottom() = wf->shei - 1;
5456 		r.rLeft() = 0; r.rRight() = wf->swid - 1;
5457 #if 0
5458 		/* printer->newPage(); */
5459 		lx = win->uselx;   hx = win->usehx;
5460 		ly = wf->revy - win->usehy; hy = wf->revy - win->usely;
5461 
5462 		r.rTop() = ly;   r.rBottom() = hy;
5463 		r.rLeft() = lx;  r.rRight() = hx;
5464 
5465 		/* make background color be white */
5466 
5467 		oldbackground = wf->draw->image.color(0);
5468 		wf->draw->image.setColor(0, white);
5469 #endif
5470 
5471 		/* draw the image */
5472 		p.drawImage(r.topLeft(), image, r);
5473 		p.end();
5474 
5475 		efree((CHAR *)wf);
5476 	}
5477 }
5478