Mercurial > ~dholland > hg > ag > index.cgi
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/anagram/vaclgui/vaclgui.cpp Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,583 @@ +/* + * AnaGram, A System for Syntax Directed Programming + * Copyright 1997-2002 Parsifal Software. All Rights Reserved. + * See the file COPYING for license and usage terms. + * + * vaclgui.cpp + */ + +//#include <iaccel.hpp> +#include <iapp.hpp> +#include <icoordsy.hpp> +#include <iexcept.hpp> +#include <ifont.hpp> +//#include <igroupbx.hpp> +#include <iiconctl.hpp> +//#include <iinfoa.hpp> +#include <imsgbox.hpp> +#include <ipainevt.hpp> +#include <ipainhdr.hpp> +//#include <iprofile.hpp> +#include <irefcnt.hpp> + +#include "action.h" +#include "agcstack.h" +#include "aglib.h" +#include "agrect.hpp" +#include "agstring.h" +#include "assert.h" +#include "engdef.h" +#include "ctrlpanel.hpp" +#include "base.h" +#include "bpu.h" +#include "help.h" +#include "multiline.hpp" +#include "operations.h" +#include "textfile.h" +#include "sums-defs.h" +#include "vaclgui-res.h" +#include "vaclgui.hpp" +#include "version.h" + +//#define INCLUDE_LOGGING +#include "log.h" + + +#define DLL + + +ActionWindow *pActionWindow = 0; + +IPoint cascadeIncrement; +IPoint cascadeOffset(0,0); +IPoint cascadeOrigin(0,0); +AgString commandLineFile; +IPointerHandle iconHandle; +AgAction idAction; +text_file inputFile; +IFont menuFont; +int messageBoxShowing = 0; + + +// declared in base.h +int nextChildId(void) { + //LOGSECTION("nextChildId"); + static int next = 0x1000; + //LOGV(next); + return next++; +} + +void messageBeep() { + LOGSECTION("messageBeep"); + MessageBeep(MB_ICONEXCLAMATION); +} + +AgQuadrant findQuadrant(IWindow *w) { + RECT r; + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + AgRectangle desktop(r); + cint sz = desktop.size()/2; + AgQuadrant quad = upperLeft; + AgRectangle wRect(w); + int i; + int area[4] = {0, 0, 0, 0}; + for (i = 0; i < 4; i++) { + AgQuadrant corner = (AgQuadrant) i; + AgQuadrant quadrant = (AgQuadrant) (i^3); + AgRectangle test(desktop.position(corner), sz, quadrant); + area[i] = test.intersection(wRect).area(); + if (area[i] > area[quad]) { + quad = (AgQuadrant) i; + } + } + return quad; +} + +static const struct { + AgQuadrant corner, quadrant; +} placement[8] = { + { lowerLeft, lowerRight }, + { lowerRight, lowerLeft }, + { upperLeft, upperRight }, + { upperRight, upperLeft }, + { upperRight, lowerRight }, + { lowerRight, upperRight }, + { upperLeft, lowerLeft }, + { lowerLeft, upperLeft } +}; + +static cint positionWindow(cint measure, LayoutRef reference, cint sz) { + LOGSECTION("positionWindow"); + int i; + int area[8]; + AgRectangle test[8]; + for (i = 0; i < 8; i++) { + AgQuadrant corner = placement[i].corner; + AgQuadrant quadrant = placement[i].quadrant; + LOGV(i) LCV(corner) LCV(quadrant); + + test[i] = AgRectangle(reference.position(corner), sz, quadrant); + LOGV(reference.position(corner)); + LOGV(test[i].position()); + test[i].limit(measure); + LOGV(test[i].position()); + area[i] = reference.overlap(test[i]); + LOGV(test[i].position()) LCV(test[i].size()) LCV(area[i]); + } + int minArea = area[0]; + int optimalPlacement = 0; + for (i = 1; i < 8; i++) { + if (area[i] >= minArea) { + continue; + } + minArea = area[i]; + optimalPlacement = i; + } + LOGV(minArea) LCV(optimalPlacement); + return test[optimalPlacement].position(upperLeft); +} + +IRectangle adjustPos(IRectangle &r) { + RECT rd; + SystemParametersInfo(SPI_GETWORKAREA, 0, &rd, 0); + IRectangle desktop(rd.left, rd.top, rd.right, rd.bottom); + ISize newSize = r.size().minimum(desktop.size()); + newSize = newSize.maximum(ISize(100, 100)); + r.sizeTo(newSize); + IPoint where = r.maxXMaxY().minimum(desktop.maxXMaxY()); + where -= newSize; + r.moveTo(where); + where = r.minXMinY().maximum(IPoint(0, 0)); + r.moveTo(where); + return r; +} + +class Damaged : public AgFrame { +private: + MultiLineText message; + +public: + Damaged(const char *failure); + ~Damaged(); + void showme(); +}; + +Damaged::Damaged(const char *failure) + : AgFrame(IFrameWindow::border + | dialogBackground + | IFrameWindow::windowList + | IFrameWindow::systemMenu) + , message(this) +{ + LOGSECTION("Damaged"); + AgString f1 = "Initialization failure: "; + AgString f2 = failure; + AgString f3 = code_segment("broken"); + AgString msg = f1.concat(f2).concat("\n\v").concat(f3); + LOGV(msg); + message.setText(msg.pointer()); + IFont textFont = IFont("Arial", 9); + message.setFont(textFont); + int leading = textFont.maxSize().height() + textFont.externalLeading(); + LOGV(leading); + message.setVTab(leading/2); +} + +Damaged::~Damaged() { + pActionWindow->close(); +} + +void Damaged::showme() { + LOGSECTION("Damaged::show"); + ISize frameSize = frameRectFor(IRectangle(message.minimumSize())).size(); + LOGV(frameSize.asString()); + setClient(&message); + sizeTo(frameSize); + IPoint where = (IPair) place(IWindow::desktopWindow()->size(), + frameSize, 11); + LOGV(where.asString()); + moveTo(where); + show().setFocus(); +} + +class SplashTimer : public ITimerFn { +private: + IFrameWindow *window; + ITimer &timer; + AgAction finish; + +public: + SplashTimer(IFrameWindow *, ITimer &); + SplashTimer(IFrameWindow *, ITimer &, AgAction); + void timerExpired(unsigned long timerId); +}; + +SplashTimer::SplashTimer(IFrameWindow *window_, + ITimer &timer_) + : window(window_) + , timer(timer_) +{} + +SplashTimer::SplashTimer(IFrameWindow *window_, + ITimer &timer_, + AgAction f) + : window(window_) + , timer(timer_) + , finish(f) +{} + +void SplashTimer::timerExpired(unsigned long) { + LOGSECTION("SplashTimer::timerExpired"); + timer.stop(); + window->close(); + LOGS("splash window closed"); + finish.performDeferred(); +} + +class ReleaseSplash + : public IFrameWindow + , public IPaintHandler +{ +private: + ISetCanvas canvas; + ISetCanvas top; + IIconControl myicon; + IStaticText logo; + ICanvas balance; + IStaticText progName; + MultiLineText copyright; + //IStaticText licenseBox; + //MultiLineText licensee; + static ITimer timer; + +public: + ReleaseSplash(); + ~ReleaseSplash(); + Boolean paintWindow(IPaintEvent &event); + static void makeReleaseSplash(); +}; + +ReleaseSplash::~ReleaseSplash() { + IPaintHandler::stopHandlingEventsFor(&canvas); + IPaintHandler::stopHandlingEventsFor(&top); + IPaintHandler::stopHandlingEventsFor(&balance); +} + +Boolean ReleaseSplash::paintWindow(IPaintEvent &event) { + LOGSECTION("ReleaseSplash::paintWindow"); + LOGV(event.rect().asString()); + event.clearBackground(IGUIColor::dialogBgnd); + return false; +} + +ITimer ReleaseSplash::timer; + +ReleaseSplash::ReleaseSplash() + : IFrameWindow(nextChildId(), + AgFrame::frameParent, + AgFrame::frameOwner, + IRectangle(), + dialogBackground | dialogBorder) + , canvas(nextChildId(),this, this, IRectangle(), + ISetCanvas::verticalDecks + | ISetCanvas::packTight + | ISetCanvas::centerAlign + | IWindow::clipChildren + | IWindow::visible) + , top(nextChildId(), &canvas, &canvas, IRectangle(), + ISetCanvas::horizontalDecks + | ISetCanvas::packTight + | ISetCanvas::centerVerticalAlign + | IWindow::clipChildren + | IWindow::visible + ) + , myicon(nextChildId(), &top, &top, iconHandle,IRectangle(), + IIconControl::classDefaultStyle | IIconControl::fillBackground) + , logo(nextChildId(), &top, &top) + , balance(nextChildId(), &top, &top) + , progName(nextChildId(), &canvas, &canvas) + , copyright(&canvas) + //, licenseBox(nextChildId(), &canvas, &canvas) + //, licensee(&canvas, IRectangle(), + // IStaticText::classDefaultStyle + // | IStaticText::border3D) +{ + IPaintHandler::handleEventsFor(&canvas); + IPaintHandler::handleEventsFor(&top); + IPaintHandler::handleEventsFor(&balance); + //myicon.setBackgroundColor(IGUIColor::dialogBgnd); + logo.setFont(IFont("Arial", 20)); + logo.font().setBold(); + logo.setText("AnaGram"); + IFont textFont("Arial",8); + progName.setFont(IFont("Arial",12)); + progName.font().setBold(); + progName.setText(BASEVERSIONSTRING); + copyright.setFont(IFont("Arial", 8)); + // + // This used to have a literal iso-latin-1 copyright char in it. + // However, I've been compelled to remove it, including even from + // this comment, not because any compiler rejects it (though they + // would technically be within their rights) but because Red Hat's + // foolish and reckless default locale settings and/or Red Hat's + // custom patch set seem to render Red Hat-based versions of Emacs + // incapable of touching the file without mangling it. + // + // I am not terribly surprised to discover this. RH seems to do a + // lot of work to make sure they can put the 'sux' in 'linsux'. + // + // (i18n is a fine thing, but it has to *work*, especially since + // non-English speakers can't just shut it all off and do without.) + // + // Fortunately, the copyright character is not legally necessary. + // + copyright.setText("Copyright 1993-2002 Parsifal Software. " + "All Rights Reserved.\n" + "Copyright 2006, 2007 David A. Holland. " + "All Rights Reserved.\n" + "\n" + "This version of AnaGram is free software.\n" + "There is NO WARRANTY.\n" + "See \"license\" in the help system for details.\n"); + copyright.setMinimumSize(copyright.calcMinimumSize()); + + //licenseBox.setFont(textFont); + //licenseBox.setText("This copy of AnaGram is registered to:"); + + //licensee.setFont(textFont); + //licensee.setText(licenseeText().pointer()); + //LOGV(licenseBox.font().name()) LCV(licenseBox.font().pointSize()); + //LOGV(licensee.font().name()) LCV(licensee.font().pointSize()); + //int leading = textFont.maxSize().height() + textFont.externalLeading(); + //licensee.setMargin(leading, leading); + //licensee.setVTab(leading/2); + + canvas.setDeckCount(1); + top.setDeckCount(1); + setClient(&canvas); + //myicon.sizeTo(myicon.minimumSize()); + //balance.sizeTo(myicon.minimumSize()); + balance.setMinimumSize(myicon.minimumSize()); + //logo.sizeTo(logo.minimumSize()); + //top.sizeTo(top.minimumSize()); + //licenseBox.sizeTo(licenseBox.minimumSize()); + + //ISize minSize = licenseBox.minimumSize(); + //ISize licenseeSize = licensee.calcMinimumSize(); + //if (licenseeSize.width() < minSize.width()) { + // licenseeSize.setWidth(minSize.width()); + //} + //licensee.setMinimumSize(licenseeSize); + + ISize size = canvas.minimumSize(); + canvas.sizeTo(size); + IRectangle r = frameRectFor(IRectangle(size)); + ISize windowSize = r.size(); + sizeTo(windowSize); + ISize desktopSize = IWindow::desktopWindow()->size(); + ISize margin = (desktopSize - windowSize)/2; + moveTo((IPoint) margin); +} + +void ReleaseSplash::makeReleaseSplash() { + LOGSECTION("Splash::makeReleaseSplash"); + ReleaseSplash *window = new ReleaseSplash; + window->setAutoDeleteObject(); + window->show().refresh(IWindow::immediate); +#ifdef INCLUDE_LOGGING + int posFlag = +#endif + SetWindowPos(window->handle(), + HWND_TOPMOST, + 0,0,0,0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); +#ifdef INCLUDE_LOGGING + if (posFlag == 0) { + LOGV(GetLastError()); + } +#endif + + IReference<ITimerFn> timerFn(new SplashTimer(window, timer)); + window->timer.start(timerFn, 4000); +} + +void bailOut(const char *problem) { + LOGSECTION("bailOut"); + LOGV(problem); + LOGSTACK; + if (controlPanel->timer.isStarted()) { + controlPanel->timer.stop(); + } + IMessageBox messageBox(0); + messageBox.setTitle("AnaGram"); + char msg[200]; + sprintf(msg, "%s\nUnexpected program termination", problem); + messageBoxShowing++; + messageBox.show(msg, IMessageBox::catastrophic); + messageBoxShowing--; + abort(); +} + +//void abortProgram() { +// pActionWindow->close(); +//} + +static void setup() { + LOGSECTION("setup"); + + init_parser(); + + const char *failure = checksums_ok(); + LOGS("checksums_ok call returned"); + LOGV(failure); + + if (failure) { + Damaged *failwindow = new Damaged(failure); + failwindow->setAutoDeleteObject(); + + idAction = actionObject(failwindow, Damaged::showme); + } + else { + idAction = actionObject(ControlPanel::makeControlPanel); + } + + idAction.performDeferred(); +} + +void agGui(char *f) { + LOGSECTION("agGui"); + LOGV((void *) agGui); + + AgString file(f); + try { + commandLineFile = file; + LOGV(commandLineFile); + ICoordinateSystem::setApplicationOrientation( + ICoordinateSystem::originUpperLeft); + + iconHandle = IResourceLibrary().loadIcon(IDI_ICON, 0); + ActionWindow actionWindow; + pActionWindow = &actionWindow; + AgAction::startup(); + AgFrame::frameOwner = pActionWindow; + AgFrame::frameParent = IWindow::desktopWindow(); + engdef_init(); + help_init(); + defer(ReleaseSplash::makeReleaseSplash); + defer(setup); + + LOGS("Starting program"); + IApplication::current().run(); + LOGS("Program complete"); + } + catch(IException & IFLOG(ie)) { + AgFrame::windowRegistry.clearActive(); + LOGSECTION_ON("catch(IException)"); + LOGSTACK; + LOGEXCEPTION(ie); + LOGS("Returned from logging exception"); + assert(0); +/* + IMessageBox messageBox(0); + LOGS("Created message box"); + messageBox.setTitle("AnaGram"); + LOGS("title set"); + messageBox.show( + "AnaGram: Unexpected program termination", + IMessageBox::catastrophic); + LOGS("Returned from showing message"); +*/ + } + catch(Problem p) { + AgFrame::windowRegistry.clearActive(); + LOGSECTION("catch(Problem)"); + LOGV(p.msg); + LOGSTACK; + assert(0); +/* + IMessageBox messageBox(0); + messageBox.setTitle("AnaGram"); + char msg[200]; + sprintf(msg, "Unexpected program termination\n%s", p.msg); + messageBoxShowing++; + messageBox.show(msg, IMessageBox::catastrophic); + messageBoxShowing--; +*/ + } + catch(...) { + AgFrame::windowRegistry.clearActive(); + LOGSECTION_ON("catch(...)"); + LOGSTACK; + assert(0); +/* + IMessageBox messageBox(0); + messageBox.setTitle("AnaGram..."); + messageBoxShowing++; + messageBox.show( + "AnaGram: Unexpected program termination", + IMessageBox::catastrophic); + messageBoxShowing--; +*/ + } +} + +#if 0 /* was: ifndef DLL */ + +/**************************************************************/ +/* historic main() program entry point */ +/**************************************************************/ +int main(int argc, char *argv[]) { + init(argv[0]); + + int buildSwitch = 0; + int i; + AgString file; + for (i = 1; i < argc; i++) { + switch (argv[i][0]) { + case '/': + case '-': + switch (argv[i][1]) { + case 'b': + case 'B': + buildSwitch = 1; + LOGS("set buildSwitch"); + break; + } + break; + default: + file = argv[i]; + break; + } + } + if (buildSwitch) { + return commandLineBuild(file.pointer()); + } + agGui(file.pointer()); + return 0; +} + +#endif /* 0 */ + +IPoint placeOnDesktop(ISize s, int ij) { + RECT r; + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + ISize desktopSize(r.right - r.left, r.bottom - r.top); + return (IPair) place(desktopSize, s, ij); +} + +IPoint placeRelative(ISize s, IWindow *window) { + RECT r; + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + ISize desktopSize(r.right - r.left, r.bottom - r.top); + + AgRectangle ref(window->position(), window->size()); + return (IPair) positionWindow(desktopSize, ref, s); +} + +IPoint placeWindow(ISize s, LayoutRef ref) { + RECT r; + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + ISize desktopSize(r.right - r.left, r.bottom - r.top); + return (IPair) positionWindow(desktopSize, ref, s); +} +