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, ­, 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