comparison anagram/vaclgui/vaclgui.cpp @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:13d2b8934445
1 /*
2 * AnaGram, A System for Syntax Directed Programming
3 * Copyright 1997-2002 Parsifal Software. All Rights Reserved.
4 * See the file COPYING for license and usage terms.
5 *
6 * vaclgui.cpp
7 */
8
9 //#include <iaccel.hpp>
10 #include <iapp.hpp>
11 #include <icoordsy.hpp>
12 #include <iexcept.hpp>
13 #include <ifont.hpp>
14 //#include <igroupbx.hpp>
15 #include <iiconctl.hpp>
16 //#include <iinfoa.hpp>
17 #include <imsgbox.hpp>
18 #include <ipainevt.hpp>
19 #include <ipainhdr.hpp>
20 //#include <iprofile.hpp>
21 #include <irefcnt.hpp>
22
23 #include "action.h"
24 #include "agcstack.h"
25 #include "aglib.h"
26 #include "agrect.hpp"
27 #include "agstring.h"
28 #include "assert.h"
29 #include "engdef.h"
30 #include "ctrlpanel.hpp"
31 #include "base.h"
32 #include "bpu.h"
33 #include "help.h"
34 #include "multiline.hpp"
35 #include "operations.h"
36 #include "textfile.h"
37 #include "sums-defs.h"
38 #include "vaclgui-res.h"
39 #include "vaclgui.hpp"
40 #include "version.h"
41
42 //#define INCLUDE_LOGGING
43 #include "log.h"
44
45
46 #define DLL
47
48
49 ActionWindow *pActionWindow = 0;
50
51 IPoint cascadeIncrement;
52 IPoint cascadeOffset(0,0);
53 IPoint cascadeOrigin(0,0);
54 AgString commandLineFile;
55 IPointerHandle iconHandle;
56 AgAction idAction;
57 text_file inputFile;
58 IFont menuFont;
59 int messageBoxShowing = 0;
60
61
62 // declared in base.h
63 int nextChildId(void) {
64 //LOGSECTION("nextChildId");
65 static int next = 0x1000;
66 //LOGV(next);
67 return next++;
68 }
69
70 void messageBeep() {
71 LOGSECTION("messageBeep");
72 MessageBeep(MB_ICONEXCLAMATION);
73 }
74
75 AgQuadrant findQuadrant(IWindow *w) {
76 RECT r;
77 SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
78 AgRectangle desktop(r);
79 cint sz = desktop.size()/2;
80 AgQuadrant quad = upperLeft;
81 AgRectangle wRect(w);
82 int i;
83 int area[4] = {0, 0, 0, 0};
84 for (i = 0; i < 4; i++) {
85 AgQuadrant corner = (AgQuadrant) i;
86 AgQuadrant quadrant = (AgQuadrant) (i^3);
87 AgRectangle test(desktop.position(corner), sz, quadrant);
88 area[i] = test.intersection(wRect).area();
89 if (area[i] > area[quad]) {
90 quad = (AgQuadrant) i;
91 }
92 }
93 return quad;
94 }
95
96 static const struct {
97 AgQuadrant corner, quadrant;
98 } placement[8] = {
99 { lowerLeft, lowerRight },
100 { lowerRight, lowerLeft },
101 { upperLeft, upperRight },
102 { upperRight, upperLeft },
103 { upperRight, lowerRight },
104 { lowerRight, upperRight },
105 { upperLeft, lowerLeft },
106 { lowerLeft, upperLeft }
107 };
108
109 static cint positionWindow(cint measure, LayoutRef reference, cint sz) {
110 LOGSECTION("positionWindow");
111 int i;
112 int area[8];
113 AgRectangle test[8];
114 for (i = 0; i < 8; i++) {
115 AgQuadrant corner = placement[i].corner;
116 AgQuadrant quadrant = placement[i].quadrant;
117 LOGV(i) LCV(corner) LCV(quadrant);
118
119 test[i] = AgRectangle(reference.position(corner), sz, quadrant);
120 LOGV(reference.position(corner));
121 LOGV(test[i].position());
122 test[i].limit(measure);
123 LOGV(test[i].position());
124 area[i] = reference.overlap(test[i]);
125 LOGV(test[i].position()) LCV(test[i].size()) LCV(area[i]);
126 }
127 int minArea = area[0];
128 int optimalPlacement = 0;
129 for (i = 1; i < 8; i++) {
130 if (area[i] >= minArea) {
131 continue;
132 }
133 minArea = area[i];
134 optimalPlacement = i;
135 }
136 LOGV(minArea) LCV(optimalPlacement);
137 return test[optimalPlacement].position(upperLeft);
138 }
139
140 IRectangle adjustPos(IRectangle &r) {
141 RECT rd;
142 SystemParametersInfo(SPI_GETWORKAREA, 0, &rd, 0);
143 IRectangle desktop(rd.left, rd.top, rd.right, rd.bottom);
144 ISize newSize = r.size().minimum(desktop.size());
145 newSize = newSize.maximum(ISize(100, 100));
146 r.sizeTo(newSize);
147 IPoint where = r.maxXMaxY().minimum(desktop.maxXMaxY());
148 where -= newSize;
149 r.moveTo(where);
150 where = r.minXMinY().maximum(IPoint(0, 0));
151 r.moveTo(where);
152 return r;
153 }
154
155 class Damaged : public AgFrame {
156 private:
157 MultiLineText message;
158
159 public:
160 Damaged(const char *failure);
161 ~Damaged();
162 void showme();
163 };
164
165 Damaged::Damaged(const char *failure)
166 : AgFrame(IFrameWindow::border
167 | dialogBackground
168 | IFrameWindow::windowList
169 | IFrameWindow::systemMenu)
170 , message(this)
171 {
172 LOGSECTION("Damaged");
173 AgString f1 = "Initialization failure: ";
174 AgString f2 = failure;
175 AgString f3 = code_segment("broken");
176 AgString msg = f1.concat(f2).concat("\n\v").concat(f3);
177 LOGV(msg);
178 message.setText(msg.pointer());
179 IFont textFont = IFont("Arial", 9);
180 message.setFont(textFont);
181 int leading = textFont.maxSize().height() + textFont.externalLeading();
182 LOGV(leading);
183 message.setVTab(leading/2);
184 }
185
186 Damaged::~Damaged() {
187 pActionWindow->close();
188 }
189
190 void Damaged::showme() {
191 LOGSECTION("Damaged::show");
192 ISize frameSize = frameRectFor(IRectangle(message.minimumSize())).size();
193 LOGV(frameSize.asString());
194 setClient(&message);
195 sizeTo(frameSize);
196 IPoint where = (IPair) place(IWindow::desktopWindow()->size(),
197 frameSize, 11);
198 LOGV(where.asString());
199 moveTo(where);
200 show().setFocus();
201 }
202
203 class SplashTimer : public ITimerFn {
204 private:
205 IFrameWindow *window;
206 ITimer &timer;
207 AgAction finish;
208
209 public:
210 SplashTimer(IFrameWindow *, ITimer &);
211 SplashTimer(IFrameWindow *, ITimer &, AgAction);
212 void timerExpired(unsigned long timerId);
213 };
214
215 SplashTimer::SplashTimer(IFrameWindow *window_,
216 ITimer &timer_)
217 : window(window_)
218 , timer(timer_)
219 {}
220
221 SplashTimer::SplashTimer(IFrameWindow *window_,
222 ITimer &timer_,
223 AgAction f)
224 : window(window_)
225 , timer(timer_)
226 , finish(f)
227 {}
228
229 void SplashTimer::timerExpired(unsigned long) {
230 LOGSECTION("SplashTimer::timerExpired");
231 timer.stop();
232 window->close();
233 LOGS("splash window closed");
234 finish.performDeferred();
235 }
236
237 class ReleaseSplash
238 : public IFrameWindow
239 , public IPaintHandler
240 {
241 private:
242 ISetCanvas canvas;
243 ISetCanvas top;
244 IIconControl myicon;
245 IStaticText logo;
246 ICanvas balance;
247 IStaticText progName;
248 MultiLineText copyright;
249 //IStaticText licenseBox;
250 //MultiLineText licensee;
251 static ITimer timer;
252
253 public:
254 ReleaseSplash();
255 ~ReleaseSplash();
256 Boolean paintWindow(IPaintEvent &event);
257 static void makeReleaseSplash();
258 };
259
260 ReleaseSplash::~ReleaseSplash() {
261 IPaintHandler::stopHandlingEventsFor(&canvas);
262 IPaintHandler::stopHandlingEventsFor(&top);
263 IPaintHandler::stopHandlingEventsFor(&balance);
264 }
265
266 Boolean ReleaseSplash::paintWindow(IPaintEvent &event) {
267 LOGSECTION("ReleaseSplash::paintWindow");
268 LOGV(event.rect().asString());
269 event.clearBackground(IGUIColor::dialogBgnd);
270 return false;
271 }
272
273 ITimer ReleaseSplash::timer;
274
275 ReleaseSplash::ReleaseSplash()
276 : IFrameWindow(nextChildId(),
277 AgFrame::frameParent,
278 AgFrame::frameOwner,
279 IRectangle(),
280 dialogBackground | dialogBorder)
281 , canvas(nextChildId(),this, this, IRectangle(),
282 ISetCanvas::verticalDecks
283 | ISetCanvas::packTight
284 | ISetCanvas::centerAlign
285 | IWindow::clipChildren
286 | IWindow::visible)
287 , top(nextChildId(), &canvas, &canvas, IRectangle(),
288 ISetCanvas::horizontalDecks
289 | ISetCanvas::packTight
290 | ISetCanvas::centerVerticalAlign
291 | IWindow::clipChildren
292 | IWindow::visible
293 )
294 , myicon(nextChildId(), &top, &top, iconHandle,IRectangle(),
295 IIconControl::classDefaultStyle | IIconControl::fillBackground)
296 , logo(nextChildId(), &top, &top)
297 , balance(nextChildId(), &top, &top)
298 , progName(nextChildId(), &canvas, &canvas)
299 , copyright(&canvas)
300 //, licenseBox(nextChildId(), &canvas, &canvas)
301 //, licensee(&canvas, IRectangle(),
302 // IStaticText::classDefaultStyle
303 // | IStaticText::border3D)
304 {
305 IPaintHandler::handleEventsFor(&canvas);
306 IPaintHandler::handleEventsFor(&top);
307 IPaintHandler::handleEventsFor(&balance);
308 //myicon.setBackgroundColor(IGUIColor::dialogBgnd);
309 logo.setFont(IFont("Arial", 20));
310 logo.font().setBold();
311 logo.setText("AnaGram");
312 IFont textFont("Arial",8);
313 progName.setFont(IFont("Arial",12));
314 progName.font().setBold();
315 progName.setText(BASEVERSIONSTRING);
316 copyright.setFont(IFont("Arial", 8));
317 //
318 // This used to have a literal iso-latin-1 copyright char in it.
319 // However, I've been compelled to remove it, including even from
320 // this comment, not because any compiler rejects it (though they
321 // would technically be within their rights) but because Red Hat's
322 // foolish and reckless default locale settings and/or Red Hat's
323 // custom patch set seem to render Red Hat-based versions of Emacs
324 // incapable of touching the file without mangling it.
325 //
326 // I am not terribly surprised to discover this. RH seems to do a
327 // lot of work to make sure they can put the 'sux' in 'linsux'.
328 //
329 // (i18n is a fine thing, but it has to *work*, especially since
330 // non-English speakers can't just shut it all off and do without.)
331 //
332 // Fortunately, the copyright character is not legally necessary.
333 //
334 copyright.setText("Copyright 1993-2002 Parsifal Software. "
335 "All Rights Reserved.\n"
336 "Copyright 2006, 2007 David A. Holland. "
337 "All Rights Reserved.\n"
338 "\n"
339 "This version of AnaGram is free software.\n"
340 "There is NO WARRANTY.\n"
341 "See \"license\" in the help system for details.\n");
342 copyright.setMinimumSize(copyright.calcMinimumSize());
343
344 //licenseBox.setFont(textFont);
345 //licenseBox.setText("This copy of AnaGram is registered to:");
346
347 //licensee.setFont(textFont);
348 //licensee.setText(licenseeText().pointer());
349 //LOGV(licenseBox.font().name()) LCV(licenseBox.font().pointSize());
350 //LOGV(licensee.font().name()) LCV(licensee.font().pointSize());
351 //int leading = textFont.maxSize().height() + textFont.externalLeading();
352 //licensee.setMargin(leading, leading);
353 //licensee.setVTab(leading/2);
354
355 canvas.setDeckCount(1);
356 top.setDeckCount(1);
357 setClient(&canvas);
358 //myicon.sizeTo(myicon.minimumSize());
359 //balance.sizeTo(myicon.minimumSize());
360 balance.setMinimumSize(myicon.minimumSize());
361 //logo.sizeTo(logo.minimumSize());
362 //top.sizeTo(top.minimumSize());
363 //licenseBox.sizeTo(licenseBox.minimumSize());
364
365 //ISize minSize = licenseBox.minimumSize();
366 //ISize licenseeSize = licensee.calcMinimumSize();
367 //if (licenseeSize.width() < minSize.width()) {
368 // licenseeSize.setWidth(minSize.width());
369 //}
370 //licensee.setMinimumSize(licenseeSize);
371
372 ISize size = canvas.minimumSize();
373 canvas.sizeTo(size);
374 IRectangle r = frameRectFor(IRectangle(size));
375 ISize windowSize = r.size();
376 sizeTo(windowSize);
377 ISize desktopSize = IWindow::desktopWindow()->size();
378 ISize margin = (desktopSize - windowSize)/2;
379 moveTo((IPoint) margin);
380 }
381
382 void ReleaseSplash::makeReleaseSplash() {
383 LOGSECTION("Splash::makeReleaseSplash");
384 ReleaseSplash *window = new ReleaseSplash;
385 window->setAutoDeleteObject();
386 window->show().refresh(IWindow::immediate);
387 #ifdef INCLUDE_LOGGING
388 int posFlag =
389 #endif
390 SetWindowPos(window->handle(),
391 HWND_TOPMOST,
392 0,0,0,0,
393 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
394 #ifdef INCLUDE_LOGGING
395 if (posFlag == 0) {
396 LOGV(GetLastError());
397 }
398 #endif
399
400 IReference<ITimerFn> timerFn(new SplashTimer(window, timer));
401 window->timer.start(timerFn, 4000);
402 }
403
404 void bailOut(const char *problem) {
405 LOGSECTION("bailOut");
406 LOGV(problem);
407 LOGSTACK;
408 if (controlPanel->timer.isStarted()) {
409 controlPanel->timer.stop();
410 }
411 IMessageBox messageBox(0);
412 messageBox.setTitle("AnaGram");
413 char msg[200];
414 sprintf(msg, "%s\nUnexpected program termination", problem);
415 messageBoxShowing++;
416 messageBox.show(msg, IMessageBox::catastrophic);
417 messageBoxShowing--;
418 abort();
419 }
420
421 //void abortProgram() {
422 // pActionWindow->close();
423 //}
424
425 static void setup() {
426 LOGSECTION("setup");
427
428 init_parser();
429
430 const char *failure = checksums_ok();
431 LOGS("checksums_ok call returned");
432 LOGV(failure);
433
434 if (failure) {
435 Damaged *failwindow = new Damaged(failure);
436 failwindow->setAutoDeleteObject();
437
438 idAction = actionObject(failwindow, Damaged::showme);
439 }
440 else {
441 idAction = actionObject(ControlPanel::makeControlPanel);
442 }
443
444 idAction.performDeferred();
445 }
446
447 void agGui(char *f) {
448 LOGSECTION("agGui");
449 LOGV((void *) agGui);
450
451 AgString file(f);
452 try {
453 commandLineFile = file;
454 LOGV(commandLineFile);
455 ICoordinateSystem::setApplicationOrientation(
456 ICoordinateSystem::originUpperLeft);
457
458 iconHandle = IResourceLibrary().loadIcon(IDI_ICON, 0);
459 ActionWindow actionWindow;
460 pActionWindow = &actionWindow;
461 AgAction::startup();
462 AgFrame::frameOwner = pActionWindow;
463 AgFrame::frameParent = IWindow::desktopWindow();
464 engdef_init();
465 help_init();
466 defer(ReleaseSplash::makeReleaseSplash);
467 defer(setup);
468
469 LOGS("Starting program");
470 IApplication::current().run();
471 LOGS("Program complete");
472 }
473 catch(IException & IFLOG(ie)) {
474 AgFrame::windowRegistry.clearActive();
475 LOGSECTION_ON("catch(IException)");
476 LOGSTACK;
477 LOGEXCEPTION(ie);
478 LOGS("Returned from logging exception");
479 assert(0);
480 /*
481 IMessageBox messageBox(0);
482 LOGS("Created message box");
483 messageBox.setTitle("AnaGram");
484 LOGS("title set");
485 messageBox.show(
486 "AnaGram: Unexpected program termination",
487 IMessageBox::catastrophic);
488 LOGS("Returned from showing message");
489 */
490 }
491 catch(Problem p) {
492 AgFrame::windowRegistry.clearActive();
493 LOGSECTION("catch(Problem)");
494 LOGV(p.msg);
495 LOGSTACK;
496 assert(0);
497 /*
498 IMessageBox messageBox(0);
499 messageBox.setTitle("AnaGram");
500 char msg[200];
501 sprintf(msg, "Unexpected program termination\n%s", p.msg);
502 messageBoxShowing++;
503 messageBox.show(msg, IMessageBox::catastrophic);
504 messageBoxShowing--;
505 */
506 }
507 catch(...) {
508 AgFrame::windowRegistry.clearActive();
509 LOGSECTION_ON("catch(...)");
510 LOGSTACK;
511 assert(0);
512 /*
513 IMessageBox messageBox(0);
514 messageBox.setTitle("AnaGram...");
515 messageBoxShowing++;
516 messageBox.show(
517 "AnaGram: Unexpected program termination",
518 IMessageBox::catastrophic);
519 messageBoxShowing--;
520 */
521 }
522 }
523
524 #if 0 /* was: ifndef DLL */
525
526 /**************************************************************/
527 /* historic main() program entry point */
528 /**************************************************************/
529 int main(int argc, char *argv[]) {
530 init(argv[0]);
531
532 int buildSwitch = 0;
533 int i;
534 AgString file;
535 for (i = 1; i < argc; i++) {
536 switch (argv[i][0]) {
537 case '/':
538 case '-':
539 switch (argv[i][1]) {
540 case 'b':
541 case 'B':
542 buildSwitch = 1;
543 LOGS("set buildSwitch");
544 break;
545 }
546 break;
547 default:
548 file = argv[i];
549 break;
550 }
551 }
552 if (buildSwitch) {
553 return commandLineBuild(file.pointer());
554 }
555 agGui(file.pointer());
556 return 0;
557 }
558
559 #endif /* 0 */
560
561 IPoint placeOnDesktop(ISize s, int ij) {
562 RECT r;
563 SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
564 ISize desktopSize(r.right - r.left, r.bottom - r.top);
565 return (IPair) place(desktopSize, s, ij);
566 }
567
568 IPoint placeRelative(ISize s, IWindow *window) {
569 RECT r;
570 SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
571 ISize desktopSize(r.right - r.left, r.bottom - r.top);
572
573 AgRectangle ref(window->position(), window->size());
574 return (IPair) positionWindow(desktopSize, ref, s);
575 }
576
577 IPoint placeWindow(ISize s, LayoutRef ref) {
578 RECT r;
579 SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
580 ISize desktopSize(r.right - r.left, r.bottom - r.top);
581 return (IPair) positionWindow(desktopSize, ref, s);
582 }
583