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);
+}
+