diff anagram/vaclgui/ctrlpanel.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/ctrlpanel.cpp	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,2147 @@
+/*
+ * AnaGram, A System for Syntax Directed Programming
+ * Copyright 1993-2002 Parsifal Software. All Rights Reserved.
+ * See the file COPYING for license and usage terms.
+ *
+ * ctrlpanel.cpp
+ */
+
+#include <direct.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include "port.h"
+
+#include <icritsec.hpp>
+#include <imsgbox.hpp>
+
+#include "about.hpp"
+#include "agcstack.h"
+#include "agfiledialog.hpp"
+#include "readprofile.h"
+#include "agrect.hpp"
+#include "anom.h"
+#include "bpe3.h"
+#include "charsdc.h"
+#include "conflictdc.h"
+#include "config.h"
+#include "coveragedc.h"
+#include "ctrlpanel.hpp"
+#include "dc.h"
+#include "dpanel.hpp"
+#include "error.h"
+#include "errordc.h"
+#include "file.h"
+#include "fileview.hpp"
+#include "ftview.hpp"
+#include "gtview.hpp"
+#include "helpview.hpp"
+#include "items.h"
+#include "keytabdc.h"
+#include "keyword.h"
+#include "openfile.hpp"
+#include "operations.h"
+#include "p.h"
+#include "symtabdc.h"
+#include "textfile.h"
+#include "tokentabdc.h"
+#include "proctabdc.h"
+#include "profile-defs.h"
+#include "q1a.h"
+#include "rproc.h"
+#include "ruletabdc.h"
+#include "vaclgui.hpp"
+#include "version.h"
+#include "wm1.h"
+
+//#define INCLUDE_LOGGING
+#include "log.h"
+
+
+#define TILDE '&'
+
+
+ControlPanel  *controlPanel = 0;
+IPoint         controlPanelLocation(-1, -1);
+
+IRectangle     syntaxFileRect;
+int            syntaxFileId = 0;
+
+
+int                  ControlPanel::helpCursorSet = 0;
+IPointerHandle       ControlPanel::helpCursor;
+IPointerHandle       ControlPanel::activeCursor;
+ISystemPointerHandle ControlPanel::waitCursor(ISystemPointerHandle::wait);
+
+static IGraphicPushButton::Style
+  buttonStyle =   IGraphicPushButton::sizeToGraphic
+                | IGraphicPushButton::tabStop
+                | IWindow::visible;
+
+
+static void showWhatsNew() {
+  AgHelpWindow::showHelpCentered("What's New");
+}
+
+ControlPanel::ControlPanel(unsigned long windowId)
+  : IFrameWindow(windowId, AgFrame::frameParent, 0, IRectangle(),
+		   IFrameWindow::titleBar
+		 | IFrameWindow::systemMenu
+		 | IFrameWindow::minimizeButton
+		 //| IFrameWindow::border
+		 | IFrameWindow::dialogBackground
+		 | IFrameWindow::windowList
+		 | IFrameWindow::sizingBorder
+		 | IFrameWindow::noMoveWithOwner)
+  , menuBar(windowId, this)
+  , systemMenu(this)
+  , systemMenuFont(menuFont = systemMenu.font())
+  , canvas(nextChildId(), this, this, IRectangle(),
+	     ISetCanvas::verticalDecks
+	   | ISetCanvas::leftAlign
+	   | ISetCanvas::packEven
+	   | IWindow::clipChildren
+	   | visible)
+  , buttonCanvas(nextChildId(), &canvas, &canvas, IRectangle(),
+		   ISetCanvas::horizontalDecks
+		 | ISetCanvas::centerVerticalAlign
+		 | IWindow::clipChildren
+		 | ISetCanvas::leftAlign
+		 | ISetCanvas::packTight 
+		 | visible)
+  , agButton(IDI_BMP_AG, &buttonCanvas, &buttonCanvas,
+	     IDI_BMP_AG, IRectangle(), buttonStyle)
+  , bpButton(IDI_BMP_BP, &buttonCanvas, &buttonCanvas,
+	     IDI_BMP_BP, IRectangle(), buttonStyle)
+  , ftButton(IDI_BMP_FT, &buttonCanvas, &buttonCanvas,
+	     IDI_BMP_FT, IRectangle(), buttonStyle)
+  , gtButton(IDI_BMP_GT, &buttonCanvas, &buttonCanvas,
+	     IDI_BMP_GT, IRectangle(), buttonStyle)
+  , warnButton(IDI_BMP_WARN, &buttonCanvas, &buttonCanvas,
+	       IDI_BMP_WARN, IRectangle(), buttonStyle)
+  , confButton(IDI_BMP_CONF, &buttonCanvas, &buttonCanvas,
+	       IDI_BMP_CONF, IRectangle(), buttonStyle)
+  , helpButton(IDI_BMP_HELPICON, &buttonCanvas, &buttonCanvas,
+	       IDI_BMP_HELPICON, IRectangle(), buttonStyle)
+  , statusControl(IDI_STATUS, &buttonCanvas, &buttonCanvas, IRectangle(),
+		    IStaticText::defaultStyle()
+		  | IStaticText::border3D)
+  , statusControlHelp(&statusControl, "Status Indicator")
+  , searchCanvas(nextChildId(), &canvas, &canvas, IRectangle(),
+		   ISetCanvas::horizontalDecks
+		 | ISetCanvas::leftAlign
+		 | ISetCanvas::packTight
+		 | IWindow::clipChildren
+		 | visible)
+  , searchKeyBox(IDI_SEARCH_KEY, &searchCanvas, "Size of Search key space")
+  , searchKeyHelp(&searchKeyBox, "Search Key")
+  , findNextButton(IDI_BMP_FINDNEXT, &searchCanvas, &searchCanvas,
+		   IDI_BMP_FINDNEXT, IRectangle(), buttonStyle)
+  , findPrevButton(IDI_BMP_FINDPREV, &searchCanvas, &searchCanvas,
+		   IDI_BMP_FINDPREV, IRectangle(), buttonStyle)
+  , flyText(nextChildId(), this)
+  , flyOver(&flyText)
+  , openFileName()
+  //, busyFlag(false)
+  , windowTitle(this, "AnaGram")
+  , autobuildFlag(0)
+  , showSyntaxFlag(1)
+  , showStatsFlag(1)
+  , stayOnTopFlag(1)
+  //, minimized(0)
+  , topmostFlag(0)
+  , textColorChange(this, onTextColorChange)
+  , linkColorChange(this, onLinkColorChange)
+  , traversedColorChange(this, onTraversedColorChange)
+  , quitAction(actionObject(this, quit))
+  , accelerator(IDW_FRAME_WINDOW, this)
+  , helpRequested(0)
+{
+  LOGSECTION("ControlPanel::ControlPanel");
+  controlPanel = this;
+
+  AgString initializer = AgFetchProfile("initializationData");
+  LOGS("profile retrieved");
+  if (initializer.exists() && initializeFrom(initializer.pointer())) {
+    LOGS("initialization problem");
+    IMessageBox messageBox(controlPanel);
+    messageBox.setTitle("AnaGram");
+    messageBoxShowing++;
+    messageBox.show("Error initializing from registry",
+		    IMessageBox::information);
+    messageBoxShowing--;
+  }
+  LOGV(recentFiles.size());
+
+  analyzeThread.adjustPriority(-1);
+
+  waitCursor = ISystemPointerHandle(ISystemPointerHandle::wait);
+
+  searchKeyBox.enterAction = actionObject(this, findNext);
+
+  flyOver.setHelpText(handle(), IDI_BMP_AG);
+
+  helpCursor = IPointerHandle(LoadCursor(0, IDC_HELP));
+
+  textColorChange.attach(&ColorSpec::helpText);
+  linkColorChange.attach(&ColorSpec::helpLink);
+  traversedColorChange.attach(&ColorSpec::helpUsedLink);
+
+  buttonCanvas.setDeckCount(1);
+  searchCanvas.setDeckCount(1);
+  canvas.setDeckCount(1);
+  buttonCanvas.setText("");
+
+  LOGV(agButton.size().asString());
+
+  ISize padSize = buttonCanvas.pad();
+  padSize.setWidth(4);
+  buttonCanvas.setPad(padSize);
+
+  buttonCanvas.setMargin(ISize(4, 2));
+
+  searchCanvas.setMargin(ISize(4, 2));
+
+  padSize = searchCanvas.pad();
+  padSize.setWidth(4);
+  searchCanvas.setPad(padSize);
+
+  ISize margin = canvas.margin();
+  margin.setHeight(0);
+  canvas.setMargin(margin);
+
+  padSize = canvas.pad();
+  padSize.setHeight(0);
+  canvas.setPad(padSize);
+
+  setClient(&canvas);       // Set canvas control for client area
+
+
+  // Set self as command event handler
+
+  flyOver.handleEventsFor(&buttonCanvas);
+  flyOver.handleEventsFor(&searchCanvas);
+  IFrameWindow::removeDefaultHandler();
+  IFrameHandler::handleEventsFor(this);
+  ICommandHandler::handleEventsFor(this);
+  IMouseHandler::handleEventsFor(this);
+  IPaintHandler::handleEventsFor(&canvas);
+  IPaintHandler::handleEventsFor(&buttonCanvas);
+  IPaintHandler::handleEventsFor(&searchCanvas);
+  IKeyboardHandler::handleEventsFor(this);
+  //IResizeHandler::handleEventsFor(this);
+  LOGS("Command handler attached");
+
+  userHandler = new AgUserHandler;
+  userHandler->handleEventsFor(this);
+  AgHelpHandler::handleEventsFor(this);
+
+  IMenuHandler::handleEventsFor(this);
+  IFocusHandler::handleEventsFor(&searchCanvas);
+  IFocusHandler::handleEventsFor(&searchKeyBox);
+
+  systemMenu.deleteItem(ISystemMenu::idMaximize);
+  //systemMenu.deleteItem(ISystemMenu::idSize);
+  systemMenu.disableItem(ISystemMenu::idRestore);
+
+  statusControl.setFont(IFont("Arial", 8));
+
+  menuBar.disableMinimumSizeCaching();
+  static const int menuIdList[] = {
+    IDM_FILE, IDM_BROWSE, IDM_OPTIONS, IDM_WINDOWS, IDM_HELP, 0
+  };
+  int i;
+  int menuWidth = 0;
+  for (i = 0; menuIdList[i]; i++) {
+    int itemWidth = menuBar.itemRect(menuIdList[i]).width();
+    LOGV(itemWidth);
+    menuWidth += itemWidth;
+  }
+  LOGV(menuWidth);
+
+  int statusWidth = statusControl.font().textWidth("   Analyzed   ");
+  ISize minSize(statusWidth, agButton.minimumSize().height());
+  statusControl.setMinimumSize(minSize);
+
+  statusControl.setAlignment(IStaticText::centerCenter);
+  setStatus();
+
+  int minWidth = buttonCanvas.minimumSize().width();
+  if (minWidth < menuWidth) {
+    statusWidth += menuWidth - minWidth;
+    minSize.setWidth(statusWidth);
+    statusControl.setMinimumSize(minSize);
+    minWidth = menuWidth;
+  }
+  minSize = searchKeyBox.minimumSize();
+  minWidth -= 2*agButton.size().width();
+  minWidth -= 2*searchCanvas.pad().width();
+  minWidth -= 2*searchCanvas.margin().width();
+
+  minSize.setWidth(minWidth);
+  searchKeyBox.setMinimumSize(minSize);
+
+  LOGV(menuFont.name()) LCV(menuFont.pointSize());
+  LOGV(font().name()) LCV(font().pointSize());
+
+  LOGS("Menu handler attached");
+
+  // Set application icon
+  //setIcon(IDI_ICON);
+  //iconHandle = icon();
+  setIcon(iconHandle);
+
+  LOGS("Icon set");
+  IRectangle desktopRect = desktopWindow()->rect();
+
+  int titleBarHeight = 24;
+  cascadeIncrement = IPoint(titleBarHeight, titleBarHeight);
+  cascadeOrigin = IPoint(0, 0);
+
+  int verticalOffset = 0;
+
+  LOGV(cascadeOrigin.asString());
+
+  cascadeOffset = cascadeOrigin;
+
+  minSize = canvas.minimumSize();
+  LOGV(minSize);
+  IRectangle frameRect = frameRectFor(IRectangle(IPoint(0, 0), minSize));
+  IRectangle clientRect = clientRectFor(frameRect);
+  //minimumSize = frameRect.size();
+  LOGV(frameRect.asString());
+  cint measure = desktopRect.size();
+  cint panelSize = frameRect.size();
+  IPoint where = controlPanelLocation;
+  LOGV(where);
+  if (where.x() < 0) {
+    where = (IPair) place(measure, panelSize, 20);
+  }
+  LOGV(where);
+  frameRect.moveTo(where);
+  frameRect = adjustPos(frameRect);
+  LOGV(frameRect.asString());
+  //sizeTo(frameRect.size());
+  //moveTo(where);
+  moveSizeTo(frameRect);
+  LOGV(menuBar.size().asString());
+  LOGV(canvas.position()) LCV(canvas.size()) LCV(size());
+  LOGV(menuBar.itemRect(IDM_FILE).asString());
+  LOGV(menuBar.itemRect(IDM_HELP).asString());
+/*
+  i = menuWidth = 0;
+  for (i = 0; menuIdList[i]; i++) {
+    menuWidth += menuBar.itemRect(menuIdList[i]).width();
+  }
+  LOGV(menuWidth);
+*/
+
+  //maxDataPanelWidth = where.x();
+
+  verticalOffset += frameRect.size().height();
+
+// Set focus to this window and show
+  setFocus();
+  show();
+
+  if (commandLineFile.exists()) {
+    defer(this, openCommandLineFile);
+  }
+  if (!initializer.exists() || lastVersion < INTVERSION) {
+    defer(showWhatsNew);
+  }
+}
+
+void closeActionWindow() {
+  LOGSECTION("closeActionWindow");
+  pActionWindow->close();
+}
+
+
+/***********************************************************/
+/* Application main window destructor.  It stops the event */
+/* handling and deletes any objects on the heap.           */
+/***********************************************************/
+ControlPanel :: ~ControlPanel ()
+{
+  LOGSECTION("ControlPanel::~ControlPanel");
+  flyOver.stopHandlingEventsFor(&buttonCanvas);
+  flyOver.stopHandlingEventsFor(&searchCanvas);
+  ICommandHandler::stopHandlingEventsFor(this);
+  IFrameHandler::stopHandlingEventsFor(this);
+  IMenuHandler::stopHandlingEventsFor(this);
+  IMouseHandler::stopHandlingEventsFor(this);
+  userHandler->stopHandlingEventsFor(this);
+  AgHelpHandler::stopHandlingEventsFor(this);
+  IPaintHandler::stopHandlingEventsFor(&canvas);
+  IPaintHandler::stopHandlingEventsFor(&buttonCanvas);
+  IPaintHandler::stopHandlingEventsFor(&searchCanvas);
+  IFocusHandler::stopHandlingEventsFor(&searchCanvas);
+  IFocusHandler::stopHandlingEventsFor(&searchKeyBox);
+  IKeyboardHandler::stopHandlingEventsFor(this);
+  //IResizeHandler::stopHandlingEventsFor(this);
+  delete userHandler;
+  controlPanel = 0;
+  defer(closeActionWindow);
+}
+
+/*
+Boolean ControlPanel::windowResize(IResizeEvent &event){
+  LOGSECTION("ControlPanel::windowResize");
+  ok_ptr(this);
+
+  if (event.controlWindow() != this) {
+    return false;
+  }
+  LOGV(event.newSize().asString());
+  if (!isVisible()) {
+    return false;
+  }
+  if (!(event.newSize() >= minimumSize)) {
+    sizeTo(minimumSize);
+    return true;
+  }
+  //canvas.sizeTo(clientRectFor(IRectangle(IPoint(), event.newSize())).size());
+  LOGV(id());
+  return false;
+}
+*/
+
+Boolean ControlPanel::ComboBox::enter(IControlEvent &event) {
+  LOGSECTION("ControlPanel::ComboBox::enter");
+  LOGV(listShowing);
+  if (listShowing) {
+    unsigned s = selection();
+    LOGV(s) LCV(IComboBox::notFound);
+    if (s == IComboBox::notFound) {
+      return false;
+    }
+    IString text = itemText(s);
+    LOGV((char *) text);
+    setText(text);
+    listShowing = 0;
+    return false;
+  }
+  else {
+    LOGV(selection());
+    LOGV(IComboBox::notFound);
+    LOGV(isListShowing());
+    LOGV(hasChanged());
+    enterAction.perform();
+    IString contents = text();
+    if (contents.length() == 0) {
+      return false;
+    }
+    int n = count();
+    while (n--) {
+      if (itemText(n) == contents) {
+      	remove(n);
+      	break;
+      }
+    }
+    addAsFirst(contents);
+    n = count();
+    LOGV(count());
+    if (n < 8 && n > minimumRows()) {
+      setMinimumRows(8);
+    }
+    LOGV(minimumRows());
+  }
+  return true;
+}
+
+Boolean ControlPanel::ComboBox::listShown(IControlEvent &event) {
+  LOGSECTION("ControlPanel::ComboBox::listShown");
+  listShowing = 1;
+  return false;
+}
+
+void ControlPanel::idSyntaxFile(AgString name) {
+  LOGSECTION("ControlPanel::idSyntaxFile");
+  openFileName = infile_name = name;   // Store selected file name
+  errorReportFile = AgString();
+  openFileTimestamp = getFileTimestamp(name.pointer());
+  AgString settingsFileName
+    = openFileName.lastCut("\\/").leftI().concat("*.syn");
+  restoreDirectory();
+/*
+  char drive[_MAX_DRIVE];
+  _splitpath(openFileName.pointer(), drive, NULL, NULL, NULL);
+  _chdrive(toupper(drive[0]) - 'A' + 1);
+  LOGV(directoryName.pointer());
+  chdir(directoryName.pointer());
+  work_dir_name = directoryName;
+*/
+  AgString fileName = openFileName.lastCut("\\/").rightX();
+
+  simple_file_name = fileName.lastCut('.').leftX();
+
+  LOGV(fileName.pointer());
+  LOGV(simple_file_name.pointer());
+}
+
+void ControlPanel::restoreDirectory() {
+  LOGSECTION("ControlPanel::restoreDirectory");
+  AgString directoryName
+    = openFileName.lastCut("\\/").leftX();
+  if (directoryName[directoryName.size() - 1] == ':') {
+    directoryName.concat("\\");
+  }
+  char drive[_MAX_DRIVE];
+  _splitpath(openFileName.pointer(), drive, NULL, NULL, NULL);
+  _chdrive(toupper(drive[0]) - 'A' + 1);
+  LOGV(directoryName.pointer());
+  chdir(directoryName.pointer());
+  work_dir_name = directoryName;
+}
+
+void ControlPanel::loadSyntaxFile() {
+  LOGSECTION("ControlPanel::loadSyntaxFile");
+
+  inputFile = text_file(openFileName);
+  reset_parser();
+  errorList.reset();
+
+  setStatus();
+  windowTitle.setViewText(simple_file_name.pointer());
+  if (showSyntaxFlag) {
+    syntaxFileId = nextChildId();
+    FileWindow *fileWindow = new FileWindow(syntaxFileId, inputFile,
+					    syntaxFileRect);
+    fileWindow->enableCursorBar();
+    fileWindow->setAutoDeleteObject();
+    fileWindow->syntaxDependent = 1;
+    LOGV(syntax_state);
+    if (syntaxFileRect.area() <= 0) {
+      AgQuadrant quad = findQuadrant(controlPanel);
+      if (quad == lowerRight) {
+	quad = upperRight;
+      }
+      else {
+	quad = lowerRight;
+      }
+      AgRectangle bestRect(
+        AgRectangle::desktop().position(quad),
+        fileWindow->size(),
+        opposite(quad)
+      );
+      IPoint where = (IPair) bestRect.position();
+      fileWindow->moveTo(where);
+      LOGV(where.asString());
+    }
+    //cascadeOffset -= cascadeIncrement;
+    fileWindow->show();
+  }
+}
+
+void ControlPanel::makeControlPanel() {
+  LOGSECTION("makeControlPanel");
+  controlPanel = new ControlPanel(IDW_FRAME_WINDOW);
+  controlPanel->setAutoDeleteObject();
+  LOGS("Control panel complete");
+  if (errorList.size()) {
+    defer(controlPanel, showErrors);
+  }
+}
+
+ControlPanel &ControlPanel::makeTopmost() {
+  LOGSECTION_OFF("ControlPanel::makeTopmost");
+  if (!stayOnTopFlag || topmostFlag++) {
+    return *this;
+  }
+
+  SetWindowPos(
+    handle(),
+    HWND_TOP,        //HWND_TOPMOST,
+    0,0,0,0,
+    SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+
+  topmostFlag = 0;
+  return *this;
+}
+
+void ControlPanel::monitor(IThread &thread) {
+  LOGSECTION_OFF("ControlPanel::monitor");
+  StatisticsWindow *window = 
+    (StatisticsWindow *) AgFrame::windowRegistry.find("Statistical Summary");
+  if (window == NULL) {
+    window = new StatisticsWindow();
+    window->setAutoDeleteObject();
+    IPoint where = (IPair) placeRelative(window->size(), controlPanel);
+    window->moveTo(where);
+  }
+  window->show().setFocus();
+  {
+    ICritSec cookie;
+    analyzeThreadActive = 1;
+  }
+  IReference<ITimerFn> timerFn = new TimerFn(timer, *window, thread);
+  timer.start(timerFn, 250);
+}
+
+void ControlPanel::onLinkColorChange() {
+  LOGSECTION("ControlPanel::onLinkColorChange");
+  ColorSpec::helpText.bg() = ColorSpec::helpLink.bg();
+  ColorSpec::helpUsedLink.bg() = ColorSpec::helpLink.bg();
+}
+
+void ControlPanel::onTextColorChange() {
+  LOGSECTION("ControlPanel::onTextColorChange");
+  ColorSpec::helpLink.bg() = ColorSpec::helpText.bg();
+  ColorSpec::helpUsedLink.bg() = ColorSpec::helpText.bg();
+}
+
+void ControlPanel::onTraversedColorChange() {
+  LOGSECTION("ControlPanel::onTraversedColorChange");
+  ColorSpec::helpText.bg() = ColorSpec::helpUsedLink.bg();
+  ColorSpec::helpLink.bg() = ColorSpec::helpUsedLink.bg();
+}
+
+void ControlPanel::openCommandLineFile() {
+  LOGSECTION("ControlPanel::openCommandLineFile");
+  char *p = commandLineFile.pointer();
+  LOGV(p);
+  FILE *file = fopen(p, "r");
+  if (file == 0) {
+    char *q = strrchr(p, '\\');
+    if (q == 0) {
+      q = p;
+    }
+    LOGV(q);
+    if (strrchr(q, '.') == 0) {
+      commandLineFile = commandLineFile.concat(".syn");
+      p = commandLineFile.pointer();
+      LOGV(p);
+      file = fopen(p, "r");
+    }
+  }
+  if (file == 0) {
+    AgString msg = AgString::format("Cannot open %s", 
+				    commandLineFile.pointer());
+    IMessageBox messageBox(controlPanel);
+    messageBoxShowing++;
+    messageBox.show(msg.pointer(), IMessageBox::information);
+    messageBoxShowing--;
+    return;
+  }
+  fclose(file);
+  activeCursor = waitCursor;
+  resetCursor();
+  LOGS("Wait cursor set");
+
+  AgString fullpath(_MAX_PATH);
+  _fullpath(fullpath.pointer(), commandLineFile.pointer(), _MAX_PATH);
+  idSyntaxFile(fullpath);
+  monitor(analyzeThread);
+  loadSyntaxFile();
+  //analyzeThread.adjustPriority(-20);
+  //analyzeThread.start(new AnalyzeGrammarFn(this));
+  *buildErrorMsg = 0;
+  rememberFile(fullpath);
+  if (autobuildFlag) {
+    IReference<IThreadFn> fn = new BuildParserFn(this);
+    analyzeThread.start(fn);
+  }
+  else {
+    IReference<IThreadFn> fn = new AnalyzeGrammarFn(this);
+    analyzeThread.start(fn);
+  }
+}
+
+char *ControlPanel::removeTilde(char *s) {
+  char *copy = s;
+  char *t = s;
+  while (*s) {
+    if (*s != TILDE) {
+      *t++ = *s;
+    }
+    s++;
+  }
+  *t = 0;
+  return copy;
+}
+
+void ControlPanel::selectMenuItem(long id) {
+  menuBar.selectItem(id);
+}
+
+void ControlPanel::setStatus() {
+  LOGSECTION("ControlPanel::setStatus");
+  LOGV(simple_file_name);
+  LOGV(syntax_state);
+  LOGV(syntaxStateString[syntax_state]);
+  statusControl.setText(syntaxStateString[syntax_state]);
+}
+
+void ControlPanel::showErrors() {
+  dc_ref error_display = new error_display_dc;
+  error_display->des->d_size.y = errorList.size();
+  AgDataViewPlug *connector = new AgDataViewPlug(error_display);
+  error_display->windowConnector = connector;
+  AgDataPanel* newPanel = new AgDataPanel(connector);
+  cascadeOffset -= cascadeIncrement;
+  AgRectangle rect(controlPanel->position(), controlPanel->size());
+  LayoutRef ref(rect);
+  IPoint warningPos = placeWindow(newPanel->size(), ref);
+  newPanel->moveTo(warningPos);
+  newPanel->setAutoDeleteObject();
+  newPanel->show().setFocus();
+}
+
+void ControlPanel::TimerFn::timerExpired(unsigned long) {
+  LOGSECTION_ON("Timer expired");
+  LOGV((int) &window);
+  LOGV((int) AgFrame::windowRegistry.find("Statistical Summary"));
+  LOGV(messageBoxShowing);
+  if (messageBoxShowing) {
+    timer.stop();
+    return;
+  }
+  int windowExists(&window == 
+		   AgFrame::windowRegistry.find("Statistical Summary"));
+  if (windowExists) {
+    //LOGSECTION("Critical section");
+    ICritSec cookie;
+    window.updateDisplay();
+  }
+  {
+    //LOGSECTION("Critical section");
+    ICritSec cookie;
+    controlPanel->setStatus();
+  }
+  if (!thread.isStarted() || !analyzeThreadActive) {
+    timer.stop();
+    LOGS("Timer stopped");
+    LOGV(controlPanel->showStatsFlag) LCV(windowExists);
+    IPoint warningPos;
+    if (windowExists && !controlPanel->showStatsFlag) {
+      AgFrame::windowRegistry.remove(window.id());
+      window.close();
+      windowExists = false;
+    }
+    else if (windowExists) {
+      window.setFocus();
+    }
+    ControlPanel::activeCursor = IPointerHandle();
+    controlPanel->resetCursor();
+    LOGS("Cursor set to default");
+    LOGV(errorList.size());
+    IFrameWindow *errorWindow = AgFrame::windowRegistry.find("Warnings");
+    if (errorWindow != NULL) {
+      AgFrame::windowRegistry.remove(errorWindow->id());
+      errorWindow->close();
+    }
+/*
+    AgDataPanel *errorWindow = (AgDataPanel *) AgFrame::windowRegistry.find("Warnings");
+    if (errorWindow != NULL) {
+      LOGS("errorWindow exists");
+      errorWindow->dataView->reset();
+      errorWindow->show().setFocus();
+    }
+    else if (errorList.size()) {
+*/
+    if (errorList.size()) {
+      //pop_up_window(new error_display_dc);
+      dc_ref error_display = new error_display_dc;
+      error_display->des->d_size.y = errorList.size();
+      AgDataViewPlug *connector = new AgDataViewPlug(error_display);
+      error_display->windowConnector = connector;
+      AgDataPanel* newPanel = new AgDataPanel(connector);
+      cascadeOffset -= cascadeIncrement;
+      AgRectangle rect(controlPanel->position(), controlPanel->size());
+      LayoutRef ref(rect);
+      if (windowExists) {
+        rect = AgRectangle(window.position(), window.size());
+        ref.merge(rect);
+      }
+      warningPos = placeWindow(newPanel->size(), ref);
+      newPanel->moveTo(warningPos);
+      newPanel->setAutoDeleteObject();
+      newPanel->show().setFocus();
+    }
+    if (*buildErrorMsg) {
+      IMessageBox messageBox(controlPanel);
+      LOGS("Showing message Box");
+      messageBoxShowing++;
+      messageBox.show(buildErrorMsg, IMessageBox::information);
+      messageBoxShowing--;
+      *buildErrorMsg = 0;
+      LOGS("Done showing message box");
+    }
+    LOGV(thread.variable("Error Message"));
+    if (*(char *) thread.variable("Error Message")) {
+      controlPanel->quitAction.performDeferred();
+    }
+  }
+  LOGV(analyzeThreadActive) LCV(thread.isStarted());
+}
+
+Boolean ControlPanel::showHelp(IEvent &event) {
+  LOGSECTION("ControlPanel::showHelp");
+  helpRequested = 1;
+  return AgHelpWindow::showHelp(selectedMenuText);
+}
+
+Boolean ControlPanel::gotFocus(IControlEvent &event) {
+  LOGSECTION("ControlPanel::gotFocus");
+  LOGV((int) event.controlWindow()) LCV((int) &searchKeyBox);
+  if (event.controlWindow() != &searchKeyBox) return false;
+  if (helpCursorSet) {
+    ControlPanel::helpCursorSet = 0;
+    AgHelpWindow::showHelp("Search Key");
+    ControlPanel::resetCursor();
+    return true;
+  }
+  agButton.disableDefault();
+  return true;
+}
+
+Boolean ControlPanel::virtualKeyPress(IKeyboardEvent &event) {
+  LOGSECTION("ControlPanel::virtualKeyPress");
+  LOGV((int) event.virtualKey());
+  LOGV(event.isShiftDown()) LCV(event.isCtrlDown()) LCV(event.isAltDown());
+  switch (event.virtualKey()) {
+    case IKeyboardEvent::f8: {
+      if (event.isShiftDown() || event.isCtrlDown() || event.isAltDown()) {
+	return false;
+      }
+
+      int first = 0, last = AgFrame::windowRegistry.size();
+      while (first < last) {
+	LOGV(AgFrame::windowRegistry[first].id)
+	  LCV(AgFrame::windowRegistry[first].title.pointer());
+	if (AgFrame::windowRegistry[first].isActive) {
+	  LOGS("found it");
+	  AgFrame::windowRegistry[first].window->setFocus();
+	  break;
+	}
+	first++;
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+Boolean ControlPanel::paintWindow(IPaintEvent &event) {
+  LOGSECTION("ControlPanel::paintWindow");
+  LOGV(event.rect().asString());
+  event.clearBackground(IGUIColor::dialogBgnd);
+  return false;
+}
+
+
+Boolean ControlPanel::mouseClicked(IMouseClickEvent &event) {
+  LOGSECTION("ControlPanel::mouseClicked");
+  //IWindow *controlWindow = event.controlWindow();
+  //LOGV(controlWindow->id());
+  LOGV(buttonCanvas.id());
+  LOGV(event.mouseAction());
+  IWindow *window = windowWithHandle(event.windowUnderPointer());
+  LOGV(window ? window->id(): 0);
+  if (window) switch (window->id()) {
+    case IDI_BMP_AG      :
+    case IDI_BMP_BP      :
+    case IDI_BMP_FT      :
+    case IDI_BMP_GT      :
+    case IDI_BMP_WARN    :
+    case IDI_BMP_CONF    :
+    case IDI_BMP_HELPICON:
+    case IDI_BMP_FINDNEXT:
+    case IDI_BMP_FINDPREV:
+    case IDI_SEARCH_KEY  :
+    return false;
+  }
+  helpCursorSet = 0;
+  resetCursor();
+  return false;
+}
+
+void ControlPanel::resetCursor() {
+  LOGSECTION("ControlPanel::resetCursor");
+  int n = AgFrame::windowRegistry.size();
+  while (n--) {
+    AgFrame *frame = AgFrame::windowRegistry[n].window;
+    frame->setMousePointer(activeCursor);
+  }
+  if (controlPanel) {
+    controlPanel->setMousePointer(activeCursor);
+  }
+  LOGS("Cursor reset");
+}
+
+ControlPanel &ControlPanel::close() {
+  LOGSECTION("ControlPanel::close");
+  closeRect = rect();
+  IFrameWindow::close();
+  return *this;
+}
+
+void ControlPanel::quit() {
+  LOGSECTION("ControlPanel::quit");
+  LOGV(analyzeThreadActive);
+  if (analyzeThread.isStarted() || analyzeThreadActive) {
+    analyzeThread.stop();
+    {
+      ICritSec cookie;
+      analyzeThreadActive = 0;
+      quitAction.performDeferred();
+    }
+    return;
+  }
+  int n = AgFrame::windowRegistry.size();
+  if (n) {
+    closeWindows();
+    defer(reset_parser);
+    quitAction.performDeferred();
+    return;
+  }
+  gatherProfile();
+  close();
+  controlPanel = 0;
+}
+
+/***********************************************************/
+/* ControlPanel main window command event handler             */
+/***********************************************************/
+
+Boolean ControlPanel::systemCommand(ICommandEvent &event) {
+  LOGSECTION("ControlPanel::systemCommand");
+  LOGV(event.commandId());
+  int commandId = event.commandId() & 0xfff0;
+  LOGV(commandId);
+  if (messageBoxShowing) {
+    messageBeep();
+    return true;
+  }
+  if (commandId == ISystemMenu::idClose) {
+    LOGSECTION("ISystemMenu::idClose");
+    quitAction.performDeferred();
+    return true;
+  }
+  else if (commandId == ISystemMenu::idMinimize) {
+    hideWindows();
+    systemMenu.disableItem(ISystemMenu::idMinimize);
+    systemMenu.disableItem(ISystemMenu::idMove);
+    systemMenu.enableItem(ISystemMenu::idRestore);
+  }
+  else if (commandId == ISystemMenu::idRestore) {
+    LOGSECTION("ISystemMenu::idRestore");
+    restoreWindows();
+    systemMenu.enableItem(ISystemMenu::idMinimize);
+    systemMenu.enableItem(ISystemMenu::idMove);
+    systemMenu.disableItem(ISystemMenu::idRestore);
+    return false;
+  }
+  return false;
+}
+
+Boolean ControlPanel::deactivated(IFrameEvent &event) {
+  LOGSECTION_OFF("ControlPanel::deactivated");
+  if (event.controlWindow() != this) {
+    return false;
+  }
+  AgFrame::activeWindowCount--;
+  LOGV(AgFrame::activeWindowCount);
+  return false;
+}
+
+Boolean ControlPanel::activated(IFrameEvent &event) {
+  LOGSECTION("ControlPanel::activated");
+  if (event.controlWindow() != this) {
+    return false;
+  }
+  AgFrame::activeWindowCount++;
+  LOGV(AgFrame::activeWindowCount);
+  IWindowHandle previous((void *) event.parameter2());
+  IWindow *previousWindow = windowWithHandle(previous);
+  LOGV((int) previousWindow);
+  if (previousWindow == 0) {
+    int k = AgFrame::windowRegistry.size();
+    while (k--) {
+      if (!AgFrame::windowRegistry[k].isActive) {
+	continue;
+      }
+      LOGV(k);
+      AgFrame::windowRegistry[k].window->setFocus();
+      break;
+    }
+  }
+  setFocus();
+  if (isMinimized()) {
+    return false;
+  }
+  //if (!minimized) return false;
+  //minimized = false;
+  int n = AgFrame::windowRegistry.size();
+  for (int i = 0; i< n; i++) {
+    AgFrame *window = AgFrame::windowRegistry[i].window;
+    LOGV(AgFrame::windowRegistry[i].isShowing);
+    LOGV(AgFrame::windowRegistry[i].title.pointer());
+    if (AgFrame::windowRegistry[i].isShowing) {
+      window->show();
+    }
+  }
+  return false;
+}
+
+void ControlPanel::findNext() {
+  LOGSECTION("ControlPanel::findNext");
+  AgString key = (char *) searchKeyBox.text();
+  LOGV(key);
+  int n = AgFrame::windowRegistry.size();
+  LOGV(n);
+  AgFrame *window = 0;
+  while (n--) {
+    if (AgFrame::windowRegistry[n].isActive) {
+      window = AgFrame::windowRegistry[n].window;
+      break;
+    }
+  }
+  LOGV((int) window);
+  if (window == 0) {
+    messageBeep();
+    return;
+  }
+  LOGV((int) window);
+  if (!window->isVisible() || key.size() == 0) {
+    messageBeep();
+    return;
+  }
+  window->setFocus();
+  LOGS("focus has been set");
+  if (!window->findNext(key)) {
+    messageBeep();
+  }
+  n = searchKeyBox.count();
+  while (n--) {
+    if (searchKeyBox.itemText(n) == key.pointer()) {
+      searchKeyBox.remove(n);
+      break;
+    }
+  }
+  searchKeyBox.addAsFirst(key.pointer());
+  searchKeyBox.setText(key.pointer());
+  searchKeyBox.selectRange();
+}
+
+void ControlPanel::findPrev() {
+  LOGSECTION("ControlPanel::findPrev");
+  AgString key = (char *) searchKeyBox.text();
+  LOGV(key);
+  int n = AgFrame::windowRegistry.size();
+  AgFrame *window = 0;
+  while (n--) {
+    if (AgFrame::windowRegistry[n].isActive) {
+      window = AgFrame::windowRegistry[n].window;
+      break;
+    }
+  }
+  if (window == 0) {
+    messageBeep();
+    return;
+  }
+  LOGV((int) window);
+  if (!window->isVisible() || key.size() == 0) {
+    messageBeep();
+    return;
+  }
+  window->setFocus();
+  LOGS("focus has been set");
+  if (!window->findPrev(key)) messageBeep();
+  n = searchKeyBox.count();
+  while (n--) {
+    if (searchKeyBox.itemText(n) == key.pointer()) {
+      searchKeyBox.remove(n);
+      break;
+    }
+  }
+  searchKeyBox.addAsFirst(key.pointer());
+  searchKeyBox.setText(key.pointer());
+  searchKeyBox.selectRange();
+}
+
+static AgString ascii(int x) {
+  char buf[20];
+  itoa(x, buf, 10);
+  return buf;
+}
+
+void ControlPanel::gatherProfile() {
+  LOGSECTION("ControlPanel::gatherProfile");
+  AgCharStack charStack;
+  ColorDialog::stackSettings(charStack);
+  FontDialog::stackSettings(charStack);
+  charStack << "Autobuild=" << ascii(autobuildFlag) << '\n';
+  charStack << "ShowStatistics=" << ascii(showStatsFlag) << '\n';
+  charStack << "ShowSyntax=" << ascii(showSyntaxFlag) << '\n';
+  charStack << "StayOnTop=" << ascii(stayOnTopFlag) << '\n';
+  charStack << "cpLoc=" << position().asString() << '\n';
+  IString r = syntaxFileRect.asString();
+  char *q = strchr((char *)r, '(');
+  charStack << "sfRect=" << q << '\n';
+  int n = recentFiles.size();
+  int i = n - 6;
+  if (i < 0) i = 0;
+  while (i < n) {
+    charStack << "RecentFile:" << recentFiles[i] << '\n';
+    i++;
+  }
+  charStack << "Version=" << ascii(INTVERSION) << "\n";
+  charStack << "endInitializationData";
+  AgString string = charStack.popString();
+  LOGV(string);
+  AgStoreProfile("initializationData", string.pointer());
+}
+
+void ControlPanel::rememberFile(AgString fileName) {
+  LOGSECTION("ControlPanel::rememberFile");
+  LOGV(fileName);
+  int n = recentFiles.size();
+  for (int i = 0; i < n; i++) {
+    if (recentFiles[i].iEq(fileName)) {
+      n--;
+      while (i < n) {
+        recentFiles[i] = recentFiles[i+1];
+        i++;
+      }
+      recentFiles[i] = fileName;
+      LOGV(i) LCV(n);
+      return;
+    }
+  }
+  LOGS("Not there, add it");
+  if (n >= 12) {
+    for (i = 0; i < 11; i++) recentFiles[i] = recentFiles[i+1];
+    recentFiles[i] = fileName;
+    return;
+  }
+  recentFiles.push(fileName);
+  LOGV(recentFiles.size());
+}
+
+Boolean ControlPanel::command(ICommandEvent &cmdEvent) {
+  IResourceLibrary  resLib;
+
+  LOGSECTION("ControlPanel::command");
+  LOGV(cmdEvent.commandId());
+
+  LOGV(helpCursorSet);
+  if (analyzeThreadActive) return true;
+  if (messageBoxShowing) {
+    messageBeep();
+    return true;
+  }
+  if (helpCursorSet) {
+    //setMousePointer(activeCursor);
+    activeCursor = IPointerHandle();
+    resetCursor();
+    helpCursorSet = 0;
+    AgString topic;
+    LOGV(ControlPanel::selectedMenuText);
+    if (!ControlPanel::selectedMenuText.exists()) {
+      switch (cmdEvent.commandId()) {
+        case IDI_BMP_AG       : selectedMenuText = "Analyze Grammar"; break;
+        case IDI_BMP_BP       : selectedMenuText = "Build Parser"; break;
+        case IDI_BMP_FT       : selectedMenuText = "File Trace"; break;
+        case IDI_BMP_GT       : selectedMenuText = "Grammar Trace"; break;
+        case IDI_BMP_WARN     : selectedMenuText = "Warnings"; break;
+        case IDI_BMP_CONF     : selectedMenuText = "Conflicts"; break;
+        case IDI_BMP_HELPICON : selectedMenuText = "Help Cursor"; break;
+        case IDI_BMP_FINDNEXT : selectedMenuText = "Find Next"; break;
+        case IDI_BMP_FINDPREV : selectedMenuText = "Find Previous"; break;
+      }
+    }
+    LOGV(selectedMenuText);
+    AgHelpWindow::showHelp(selectedMenuText);
+    selectedMenuText.discardData();
+    return true;
+  }
+  if (ControlPanel::selectedMenuText.exists()) {
+    selectedMenuText.discardData();
+  }
+  switch (cmdEvent.commandId()) {
+    case IDI_BMP_HELPICON: {
+      //MouseDrop *mouseDrop = new MouseDrop(this);
+      setMousePointer(helpCursor);
+      helpCursorSet = 1;
+      int n = AgFrame::windowRegistry.size();
+      while (n--) {
+        AgFrame *frame = AgFrame::windowRegistry[n].window;
+        if (frame->helpCursorSupported) {
+	  frame->setMousePointer(helpCursor);
+	}
+      }
+      return true;
+    }
+    case IDI_BMP_AG:
+    case IDM_ANALYZE: {
+      // Create and show File open dialog
+      LOGSECTION("IDM_ANALYZE");
+      AgFileDialog dialog(this);
+      dialog.setFilter("Syntax Files\0*.syn\0All Files\0*.*\0");
+      dialog.setTitle("Analyze Grammar");
+      dialog.setExt("syn");
+      if (dialog.showModally()) {
+        //IPointerHandle pointerHandle = mousePointer();
+        LOGSECTION("Starting fileread and analysis");
+        //ISystemPointerHandle waitPointer(ISystemPointerHandle::wait);
+        activeCursor = waitCursor;
+        //setMousePointer(waitCursor);
+        resetCursor();
+        LOGS("Wait cursor set");
+        //close_syntax_windows();
+        //reset_parser();
+        LOGS("Parser reset");
+        //logWindows();
+
+        closeSyntaxWindows();
+        AgString fileName = dialog.fileName();
+        idSyntaxFile(fileName);
+        *buildErrorMsg = 0;
+        monitor(analyzeThread);
+        loadSyntaxFile();
+        rememberFile(fileName);
+        IReference<IThreadFn> fn = new AnalyzeGrammarFn(this);
+        analyzeThread.start(fn);
+      }
+      return true;
+    }
+    case IDM_REANALYZE: {
+      LOGSECTION("IDM_REANALYZE");
+      activeCursor = waitCursor;
+      resetCursor();
+      closeSyntaxWindows();
+      idSyntaxFile(openFileName);
+      *buildErrorMsg = 0;
+      monitor(analyzeThread);
+      loadSyntaxFile();
+      IReference<IThreadFn> fn = new AnalyzeGrammarFn(this);
+      analyzeThread.start(fn);
+      return true;
+    }
+    case IDI_BMP_BP:
+    case IDM_BUILD_PARSER: {
+      LOGSECTION("IDM_BUILD_PARSER");
+      AgFileDialog dialog(this);
+      dialog.setFilter("Syntax Files\0*.syn\0All Files\0*.*\0");
+      dialog.setTitle("Build Parser");
+      dialog.setExt("syn");
+      if (!dialog.showModally()) {
+	return true;
+      }
+      activeCursor = waitCursor;
+      resetCursor();
+      closeSyntaxWindows();
+      AgString fileName = dialog.fileName();
+      idSyntaxFile(fileName);
+      monitor(analyzeThread);
+      loadSyntaxFile();
+      buildErrorMsg[0] = 0;
+      rememberFile(fileName);
+      IReference<IThreadFn> fn = new BuildParserFn(this);
+      analyzeThread.start(fn);
+
+      return true;
+
+    }
+    case IDM_REBUILD: {
+      LOGSECTION("IDM_REBUILD");
+      restoreDirectory();
+      activeCursor = waitCursor;
+      closeSyntaxWindows();
+      idSyntaxFile(openFileName);
+      monitor(analyzeThread);
+      loadSyntaxFile();
+      buildErrorMsg[0] = 0;
+      IReference<IThreadFn> fn = new BuildParserFn(this);
+      analyzeThread.start(fn);
+      return true;
+    }
+    case IDM_BUILD: {
+      LOGSECTION("IDM_BUILD");
+      restoreDirectory();
+      monitor(analyzeThread);
+      activeCursor = waitCursor;
+      resetCursor();
+      *buildErrorMsg = 0;
+      IReference<IThreadFn> fn = new BuildParserFn(this);
+      analyzeThread.start(fn);
+      return true;
+    }
+    case IDM_COPY: {
+      IClipboard clipboard(handle());
+      clipboard.empty();
+      int n = AgFrame::windowRegistry.size();
+      while (n--) {
+	if (AgFrame::windowRegistry[n].isActive) {
+	  LOGS("found it");
+          AgFrame::windowRegistry[n].window->copyTo(clipboard);
+	  break;
+	}
+      }
+      return true;
+    }
+    case IDM_EXIT: {
+      LOGSECTION("IDM_EXIT");
+      if (analyzeThread.isStarted()) {
+	analyzeThread.stop();
+      }
+      quitAction.performDeferred();
+      return true;
+    }
+    case IDI_BMP_WARN: {
+      LOGSECTION("IDI_BMP_WARN");
+      if (errorList.size()) {
+	pop_up_window(new error_display_dc);
+      }
+      else {
+	messageBeep();
+      }
+      return 1;
+    }
+    case IDI_BMP_CONF: {
+      LOGSECTION("IDI_BMP_CONF");
+      if (unres_con->nt) {
+	pop_up_window(new unres_con_dc);
+      }
+      else {
+	messageBeep();
+      }
+      return 1;
+    }
+    case IDM_ERROR_TRACE: {
+      LOGSECTION("IDM_ERROR_TRACE");
+      AgFileDialog dialog(this);
+      dialog.setFilter("Trace Files\0*.etr\0All Files\0*.*\0");
+      dialog.setTitle("Select Error Trace File");
+      dialog.setExt("etr");
+      if (dialog.showModally()) {
+        etr_file_name = dialog.fileName();
+        FILE *ag_file = fopen(etr_file_name.pointer(), "r");
+        LOGV(etr_file_name.pointer());
+        LOGV((int) ag_file);
+        if (ag_file == 0) {
+          AgString msg = AgString::format("Cannot open %s",
+					  etr_file_name.pointer());
+          IMessageBox messageBox(controlPanel);
+          messageBoxShowing++;
+          messageBox.show(msg.pointer(), IMessageBox::information);
+          messageBoxShowing--;
+          return true;
+        }
+        if (getFileTimestamp(etr_file_name.pointer()) < openFileTimestamp) {
+          IMessageBox messageBox(controlPanel);
+          messageBoxShowing++;
+          if (messageBox.show("Trace file is older than syntax",
+			      IMessageBox::okCancelButton) 
+	      == IMessageBox::cancel) {
+	    return true;
+	  }
+          messageBoxShowing--;
+        }
+        LOGV(etr_file_name.pointer());
+        LOGV((int) &etr_file_name);
+        tsd *et = build_et(ag_file);
+        fclose(ag_file);
+        GTWindow *trace = new GTWindow(et, "Error Trace", etr_file_name);
+        delete_tsd(et);
+        trace->setAutoDeleteObject();
+      }
+      return true;
+    }
+    case IDI_BMP_GT:
+      if (syntax_state < syntax_analyzed) {
+        messageBeep();
+        return true;
+      }
+    case IDM_GRAMMAR_TRACE: {
+      if (syntax_state < syntax_analyzed) {
+	return true;
+      }
+      LOGSECTION("IDM_GRAMMAR_TRACE");
+      //GTWindow *trace = new GTWindow(0);
+      GTWindow *trace = new GTWindow(0, "Grammar Trace");
+      trace->setAutoDeleteObject();
+      return true;
+    }
+    case IDI_BMP_FT:
+      if (syntax_state < syntax_analyzed) {
+        messageBeep();
+        return true;
+      }
+    case IDM_FILE_TRACE: {
+      if (syntax_state < syntax_analyzed) {
+	return true;
+      }
+      LOGSECTION("IDM_FILE_TRACE");
+      // Create and show File open dialog
+      AgFileDialog dialog(this);
+      //char buf[200];
+      //if (strcmp(test_file_mask, "*.*") == 0) {
+      if (test_file_mask == "*.*") {
+        dialog.setFilter("All Files\0*.*\0");
+      }
+      else {
+        char buf[200];
+        sprintf(buf, "Test Files%c%s%cAll Files%c*.*%c", 0, 
+		test_file_mask.pointer(), 0, 0, 0);
+        LOGV(buf);
+        dialog.setFilter(buf);
+/*
+        sss("Test Files");
+        acs(0);
+        ass(test_file_mask.pointer());
+        acs(0);
+        ass("All Files");
+        acs(0);
+        ass("*.*");
+        acs(0);
+        acs(0);
+        dialog.setFilter(string_base);
+        rcs();
+*/
+      }
+      dialog.setTitle("Select Test File");
+      AgString ext = test_file_mask.lastCut('.').rightX();
+      if (!ext.firstCut('*').exists()) {
+        dialog.setExt(ext.pointer());
+      }
+      if (dialog.showModally()) {
+        AgString fileName = dialog.fileName();
+        LOGV(fileName.pointer());
+
+        int flags = (test_file_binary ? O_BINARY : O_TEXT) | O_RDONLY;
+        FileTraceWindow *trace = new FileTraceWindow(fileName, flags);
+        trace->setAutoDeleteObject();
+      }
+      return true;
+    }
+    case IDM_EDIT_FIND:
+      searchKeyBox.setFocus();
+      return true;
+    case IDM_EDIT_FINDNEXT:
+    case IDI_BMP_FINDNEXT: {
+      LOGSECTION("IDI_BMP_FINDNEXT");
+      findNext();
+      return true;
+    }
+    case IDM_EDIT_FINDPREV:
+    case IDI_BMP_FINDPREV: {
+      LOGSECTION("IDI_BMP_FINDPREV");
+      findPrev();
+      return true;
+    }
+    case IDM_AUTOBUILD: {
+      autobuildFlag = !autobuildFlag;
+      return true;
+    }
+    case IDM_SHOW_SYNTAX: {
+      showSyntaxFlag = !showSyntaxFlag;
+      return true;
+    }
+    case IDM_SHOW_STATS: {
+      LOGSECTION("IDM_SHOW_STATS");
+      showStatsFlag = !showStatsFlag;
+      return true;
+    }
+    case IDM_STAY_ON_TOP: {
+      stayOnTopFlag = !stayOnTopFlag;
+      return true;
+    }
+    case IDM_COLORS: {
+      LOGSECTION("IDM_COLORS");
+      ColorDialog *dialog =
+	(ColorDialog *) AgFrame::windowRegistry.find("Set Colors");
+      if (dialog == 0) {
+        dialog = new ColorDialog;
+        dialog->setAutoDeleteObject();
+      }
+      dialog->show();
+      dialog->mySetFocus();
+      return true;
+    }
+    case IDM_FONT: {
+      LOGSECTION("IDM_FONT");
+      FontDialog *dialog = 
+	(FontDialog *) AgFrame::windowRegistry.find("Set Fonts");
+      if (dialog == 0) {
+        dialog = new FontDialog;
+        dialog->setAutoDeleteObject();
+      }
+      dialog->show();
+      dialog->mySetFocus();
+      return true;
+    }
+    case IDM_HELP_PROG_DEV: {
+      AgHelpWindow::showHelp("Program Development");
+      return true;
+    }
+    case IDM_HELP_START: {
+      //AgHelpWindow *helpWindow = 
+      //  new AgHelpWindow(controlPanel, "Getting Started");
+      //AgHelpWindow *helpWindow = new AgHelpWindow("Getting Started");
+      //helpWindow->setAutoDeleteObject();
+      AgHelpWindow::showHelp("Getting Started");
+      return true;
+    }
+    case IDM_HELP_NEW: {
+      AgHelpWindow::showHelp("What's New");
+      return true;
+    }
+    case IDM_HELP_LICENSE: {
+      AgHelpWindow::showHelp("License");
+      return true;
+    }
+    case IDM_HELP_INDEX: {
+      LOGSECTION("IDM_HELP_INDEX");
+      help_index_dc *help_index = new help_index_dc;
+      AgDataViewPlug *connector = new AgDataViewPlug(help_index);
+      help_index->windowConnector = connector;
+      AgDataPanel *helpWindow = new AgDataPanel(connector);
+      helpWindow->dataView->setEnterAction(
+	actionObject(helpWindow->dataView, AgDataView::showHelp)
+      );
+      helpWindow->setAutoDeleteObject();
+      helpWindow->show().setFocus();
+      return true;
+    }
+    case IDM_HELP_USING: {
+      AgHelpWindow::showHelp("Using Help");
+      return true;
+    }
+    case IDM_HELP_PRODINFO: {
+      LOGSECTION("IDM_HELP_PRODINFO");
+      AgFrame *productInfo = AgFrame::windowRegistry.find("About AnaGram");
+      if (productInfo == 0) {
+        productInfo = new AboutBox();
+        productInfo->setAutoDeleteObject();
+        IPoint where = (IPair) place(IWindow::desktopWindow()->size(),
+				     productInfo->size(), 11);
+        productInfo->moveTo(where);
+      }
+      productInfo->show().setFocus();
+      LOGS("About box should be showing");
+      return true;
+    }
+    case IDM_CHAR_MAP:
+      pop_up_window(new char_map_dc);
+      return true;
+    case IDM_CHAR_SETS:
+      pop_up_window(new char_set_dc);
+      return true;
+    case IDM_UNRES_CON:
+      pop_up_window(new unres_con_dc);
+      return true;
+    case IDM_CONFIG_PARAM:
+      LOGS("Select config params");
+      pop_up_window(new param_table_dc);
+      return true;
+    case IDM_ANOMALY_TABLE:
+      pop_up_window(new anomaly_table_dc);
+      return true;
+    case IDM_KEYWORD_TABLE:
+      pop_up_window(new keyword_table_dc);
+      return true;
+    case IDM_PARTITION_SETS:
+      pop_up_window(new partition_table_dc);
+      return true;
+    case IDM_PROC_TABLE:
+      pop_up_window(new proc_table_dc);
+      return true;
+    case IDM_RES_CON:
+      pop_up_window(new res_con_dc);
+      return true;
+    case IDM_RULE_TABLE:
+      pop_up_window(new rule_table_dc);
+      return true;
+    case IDM_STATE_TABLE:
+      pop_up_window(new state_table_dc);
+      return true;
+    case IDM_SYMBOL_TABLE:
+      pop_up_window(new symbol_table_dc);
+      return true;
+    case IDM_TRACE_COUNTS:
+      //pop_up_window(new rule_count_dc("Trace Coverage", trace_counts));
+      pop_up_window(new rule_count_dc("Trace Coverage", traceCounts));
+      return true;
+    case IDM_TOKEN_TABLE:
+      pop_up_window(new token_table_dc);
+      return true;
+    case IDM_ERROR_TABLE: {
+      pop_up_window(new error_display_dc);
+      return true;
+    }
+    case IDM_RULE_COUNTS: {
+      LOGSECTION("IDM_RULE_COUNTS");
+      AgFileDialog dialog(this);
+      dialog.setFilter("Coverage Files\0*.nrc\0All Files\0*.*\0");
+      dialog.setTitle("Select Rule Coverage File");
+      dialog.setExt("nrc");
+      if (dialog.showModally()) {
+        AgString fileName = dialog.fileName();
+        FILE *ag_file = fopen(fileName.pointer(), "r");
+        LOGV(fileName.pointer());
+        LOGV((int) ag_file);
+        if (ag_file == 0) {
+          AgString msg = AgString::format("Cannot open %s",
+					  fileName.pointer());
+          IMessageBox messageBox(controlPanel);
+          messageBoxShowing++;
+          messageBox.show(msg.pointer(), IMessageBox::information);
+          messageBoxShowing--;
+          return true;
+        }
+        fclose(ag_file);
+        if (getFileTimestamp(fileName.pointer()) < openFileTimestamp) {
+          IMessageBox messageBox(controlPanel);
+          messageBoxShowing++;
+          IMessageBox::Response response = 
+	    messageBox.show("Coverage file is older than syntax",
+			    IMessageBox::okCancelButton);
+          messageBoxShowing--;
+          if (response == IMessageBox::cancel) {
+	    return true;
+	  }
+        }
+        LOGV(fileName.pointer());
+        dc_ref windowData = read_counts(fileName);
+        if (windowData.exists()) {
+          pop_up_window(read_counts(fileName));
+          return true;
+        }
+        IMessageBox messageBox(controlPanel);
+        messageBoxShowing++;
+        messageBox.show("Not a valid coverage file",
+			IMessageBox::okButton);
+        messageBoxShowing--;
+      }
+      return true;
+    }
+    case IDM_STATISTICS: {
+      LOGSECTION("IDM_STATISTICS");
+      if (AgFrame::windowRegistry.action("Statistical Summary")) {
+	return true;
+      }
+      AgFrame *window = new StatisticsWindow();
+      window->setAutoDeleteObject();
+      window->positionFrame();
+      window->show().setFocus();
+      return true;
+    }
+    case IDM_SYNTAX_FILE: {
+      LOGSECTION("IDM_SYNTAX_FILE");
+      if (AgFrame::windowRegistry.action(syntaxFileId)) {
+	return true;
+      }
+      LOGS("Not in registry");
+      syntaxFileId = nextChildId();
+      FileWindow *fileWindow = new FileWindow(syntaxFileId, inputFile,
+					      syntaxFileRect);
+      fileWindow->enableCursorBar();
+      fileWindow->setAutoDeleteObject();
+      fileWindow->syntaxDependent = 1;
+      //IPoint where = (IPair) place(IWindow::desktopWindow()->size(), 
+      //                             fileWindow->size(), 22);
+      if (syntaxFileRect.area() <= 0) {
+        AgQuadrant quad = findQuadrant(controlPanel);
+        if (quad == lowerRight) {
+	  quad = upperRight;
+	}
+        else {
+	  quad = lowerRight;
+	}
+        AgRectangle bestRect(
+          AgRectangle::desktop().position(quad),
+          fileWindow->size(),
+          opposite(quad)
+        );
+        IPoint where = (IPair) bestRect.position();
+        fileWindow->moveTo(where);
+      }
+      //cascadeOffset -= cascadeIncrement;
+      fileWindow->show().setFocus();
+      LOGS("file created");
+      return true;
+    }
+    case IDM_CASCADE: {
+      LOGSECTION("IDM_CASCADE");
+      int n = AgFrame::windowRegistry.size();
+      AgFrame::windowRegistry.cascadeFlag++;
+      LOGV(n);
+      if (n == 0) {
+	return true;
+      }
+      cascadeOffset = cascadeOrigin;
+      for (int i = 0; i < n; i++) {
+        WindowRecord &windowRecord = AgFrame::windowRegistry[i];
+        LOGV(windowRecord.title.pointer());
+        LOGV(cascadeOffset.asString());
+        windowRecord.window->positionFrame();
+        windowRecord.window->show().mySetFocus();
+        windowRecord.isActive = 0;
+      }
+      if (n) {
+	AgFrame::windowRegistry[n-1].isActive = 1;
+      }
+      AgFrame::windowRegistry.cascadeFlag--;
+      return true;
+    }
+    case IDM_CLOSE_WINDOWS: {
+      closeWindows();
+      return true;
+    }
+    case IDM_HIDE_WINDOWS: {
+      hideWindows();
+      return true;
+    }
+    case IDM_RESTORE_WINDOWS: {
+      restoreWindows();
+      return true;
+    }
+    default: {
+      LOGSECTION("defaultCommand");
+      LOGV(cmdEvent.commandId());
+      LOGV(IDM_RECENT_FILES);
+      unsigned fileIndex = cmdEvent.commandId() - IDM_RECENT_FILES;
+      LOGV(fileIndex);
+      LOGV(recentFiles.size());
+      if (fileIndex < recentFiles.size()) {
+        LOGSECTION("RecentFile");
+        AgString fileName = recentFiles[fileIndex];
+        FILE *f = fopen(fileName.pointer(), "r");
+	if (f == 0) {
+	  char msg[MAX_PATH+100];
+	  sprintf(msg, "Cannot open %s", fileName.pointer());
+	  IMessageBox messageBox(controlPanel);
+	  messageBoxShowing++;
+	  messageBox.show(msg, IMessageBox::information);
+	  messageBoxShowing--;
+	  return true;
+	}
+        fclose(f);
+        LOGS("Starting fileread and analysis");
+        activeCursor = waitCursor;
+        resetCursor();
+        closeSyntaxWindows();
+        idSyntaxFile(fileName);
+        monitor(analyzeThread);
+        loadSyntaxFile();
+        buildErrorMsg[0] = 0;
+        LOGV((int) &analyzeThread);
+        LOGV((int) &IThread::current());
+        rememberFile(fileName);
+        if (autobuildFlag) {
+          IReference<IThreadFn> fn = new BuildParserFn(this);
+          analyzeThread.start(fn);
+        }
+        else {
+          IReference<IThreadFn> fn = new AnalyzeGrammarFn(this);
+          analyzeThread.start(fn);
+        }
+        return true;
+      }
+      if (AgFrame::windowRegistry.action(cmdEvent.commandId())) {
+	return true;
+      }
+    }
+  } /* end switch */
+  return false;
+}
+
+
+Boolean ControlPanel::menuSelected(IMenuEvent &event) {
+  LOGSECTION_OFF("ControlPanel::menuSelected");
+  IMenuItem menuItem = event.menuItem();
+  selectedMenuText = removeTilde(menuItem.text());
+  LOGV(selectedMenuText.pointer());
+  selectedMenuText = selectedMenuText.lastCut(':').leftX();
+  char *menuName[] = {"Action", "Browse", "Options", "Windows", "Help"};
+  for (int i = 0; i < 5; i++) {
+    if (selectedMenuText == menuName[i]) {
+      break;
+    }
+  }
+  if (i < 5) {
+    selectedMenuText = selectedMenuText.concat(" Menu");
+  }
+  LOGV(selectedMenuText.pointer());
+  return false;
+}
+
+AgString ControlPanel::selectedMenuText;
+
+Boolean ControlPanel::menuShowing(IMenuEvent &event, ISubmenu &submenu) {
+  LOGSECTION_OFF("ControlPanel::menuShowing");
+  LOGV(event.menuItemId());
+  AgFrame::menuShowingFlag = 1;
+  LOGV(AgFrame::menuShowingFlag);
+  switch (event.menuItemId()) {
+    case IDM_OPTIONS: {
+      submenu.checkItem(IDM_AUTOBUILD, autobuildFlag);
+      submenu.checkItem(IDM_SHOW_SYNTAX, showSyntaxFlag);
+      submenu.checkItem(IDM_SHOW_STATS, showStatsFlag);
+      submenu.checkItem(IDM_STAY_ON_TOP, stayOnTopFlag);
+      return true;
+    }
+  }
+  if (helpCursorSet) {
+    return true;
+  }
+  switch (event.menuItemId()) {
+    case IDM_FILE: {
+      LOGSECTION_OFF("File Menu Showing");
+      LOGV(syntax_state);
+      if (simple_file_name.exists()) {
+        IMenuItem item = submenu.menuItem(IDM_BUILD);
+        AgString text = AgString::format("Bui%cld %s", TILDE, 
+					 simple_file_name.pointer());
+        item.setText(text.pointer());
+        submenu.setItem(item);
+        LOGV(text.pointer());
+        LOGV((char *) item.text());
+      }
+      if (syntax_state == syntax_analyzed ||
+	  (syntax_state > syntax_reset && syntax_state < syntax_analyzed &&
+	   getFileTimestamp(openFileName.pointer()) > openFileTimestamp)) {
+        LOGV("syntax analyzed");
+      }
+      else {
+	submenu.disableItem(IDM_BUILD);
+      }
+      if (simple_file_name.exists()) {
+        IMenuItem item = submenu.menuItem(IDM_REBUILD);
+        AgString text = AgString::format("Rebuil%cd %s", TILDE,
+					 simple_file_name.pointer());
+        item.setText(text.pointer());
+        submenu.setItem(item);
+        LOGV(text.pointer());
+        LOGV((char *) item.text());
+      }
+      if (syntax_state == engine_built) {
+        if (getFileTimestamp(openFileName.pointer()) <= openFileTimestamp) {
+	  submenu.disableItem(IDM_REBUILD);
+	}
+      }
+      else {
+	submenu.disableItem(IDM_REBUILD);
+      }
+      if (simple_file_name.exists()) {
+        AgString text = AgString::format("%cReanalyze %s", TILDE, 
+					 simple_file_name.pointer());
+        IMenuItem item = submenu.menuItem(IDM_REANALYZE);
+        item.setText(text.pointer());
+        submenu.setItem(item);
+        LOGV(text.pointer());
+        LOGV((char *) item.text());
+      }
+      if (syntax_state > syntax_reset) {
+        if (getFileTimestamp(openFileName.pointer()) <= openFileTimestamp) {
+          submenu.disableItem(IDM_REANALYZE);
+        }
+      }
+      else {
+	submenu.disableItem(IDM_REANALYZE);
+      }
+
+      if (!error_trace || syntax_state < syntax_analyzed) {
+	submenu.disableItem(IDM_ERROR_TRACE);
+      }
+      if (syntax_state < syntax_analyzed) {
+	submenu.disableItem(IDM_GRAMMAR_TRACE);
+      }
+      LOGV(char_set_dict->nsx);
+      if (syntax_state < syntax_analyzed
+	  || char_set_dict->nsx <= 1
+	  || badRecursionFlag) {
+	submenu.disableItem(IDM_FILE_TRACE);
+      }
+
+      if (recentFiles.size() == 0) {
+	return true;
+      }
+      LOGV(recentFiles.size());
+      submenu.addSeparator(1000);
+      int i;
+      int nFiles = recentFiles.size();
+      int n = nFiles;
+      for (i = 1; i <= n; i++) {
+	AgString fileName = recentFiles[nFiles-i];
+	int length = fileName.size();
+        char text[_MAX_PATH + 10];
+	if (length > 35) {
+	  char head[30];
+	  strncpy(head, fileName.pointer(), 15);
+	  head[15] = 0;
+	  sprintf(text, "%c%d. %s ... %s", TILDE, i, head,
+		  fileName.pointer() + length - 15);
+	}
+        else {
+	  sprintf(text, "%c%d. %s", TILDE, i, fileName.pointer());
+	}
+        submenu.addText(IDM_RECENT_FILES + nFiles-i, text);
+      }
+      return true;
+    }
+    case IDM_BROWSE: {
+      LOGSECTION_OFF("IDM_BROWSE");
+      if (syntax_state < syntax_analyzed) {
+        submenu.disableItem(IDM_RES_CON);
+        submenu.disableItem(IDM_UNRES_CON);
+        submenu.disableItem(IDM_STATE_TABLE);
+        submenu.disableItem(IDM_ANOMALY_TABLE);
+      }
+      else {
+        if (key_mess->nt == 0) {
+	  submenu.disableItem(IDM_ANOMALY_TABLE);
+	}
+        if (unres_con->nt == 0) {
+	  submenu.disableItem(IDM_UNRES_CON);
+	}
+        if (prr->nt == 0) {
+	  submenu.disableItem(IDM_RES_CON);
+	}
+      }
+      if (syntax_state < syntax_parsed) {
+        submenu.disableItem(IDM_CHAR_MAP);
+        submenu.disableItem(IDM_CHAR_SETS);
+        submenu.disableItem(IDM_RULE_TABLE);
+        submenu.disableItem(IDM_PROC_TABLE);
+        submenu.disableItem(IDM_RULE_COUNTS);
+        submenu.disableItem(IDM_TOKEN_TABLE);
+        submenu.disableItem(IDM_SYMBOL_TABLE);
+        submenu.disableItem(IDM_TRACE_COUNTS);
+        submenu.disableItem(IDM_KEYWORD_TABLE);
+        submenu.disableItem(IDM_PARTITION_SETS);
+        submenu.disableItem(IDM_STATISTICS);
+      }
+      else {
+        if (n_chars == 0) {
+	  submenu.disableItem(IDM_CHAR_MAP);
+	}
+        if (char_set_dict->nsx <= 1) {
+	  submenu.disableItem(IDM_CHAR_SETS);
+	}
+        if (Keyword::count() <= 1) {
+	  submenu.disableItem(IDM_KEYWORD_TABLE);
+	}
+        if (part_dict->nsx <= 1) {
+	  submenu.disableItem(IDM_PARTITION_SETS);
+	}
+        if (Procedure::count() <= 1) {
+	  submenu.disableItem(IDM_PROC_TABLE);
+	}
+        if (!rule_coverage) {
+	  submenu.disableItem(IDM_RULE_COUNTS);
+	}
+        if (!traceCounts.exists()) {
+	  submenu.disableItem(IDM_TRACE_COUNTS);
+	}
+      }
+
+      int disableFlag = true;
+      LOGS("disable syntax file selection");
+      LOGV(disableFlag);
+      if (simple_file_name.exists()) {
+        AgString text = AgString::format("Syntax %cFile - %s", TILDE, 
+					 simple_file_name.pointer());
+        IMenuItem item = submenu.menuItem(IDM_SYNTAX_FILE);
+        item.setText(text.pointer());
+        submenu.setItem(item);
+        LOGV(text.pointer());
+        disableFlag = 0;
+      }
+      LOGV(disableFlag);
+      if (disableFlag) {
+	submenu.disableItem(IDM_SYNTAX_FILE);
+      }
+      LOGS("disableFlag set");
+
+      if (errorList.size() == 0) {
+	submenu.disableItem(IDM_ERROR_TABLE);
+      }
+      return true;
+    }
+    case IDM_WINDOWS: {
+      LOGSECTION_OFF("IDM_WINDOWS");
+      int ln;
+      int n = AgFrame::windowRegistry.size();
+      LOGV(n);
+      if (n == 0) {
+        submenu.disableItem(IDM_CASCADE);
+        submenu.disableItem(IDM_CLOSE_WINDOWS);
+        submenu.disableItem(IDM_HIDE_WINDOWS);
+        submenu.disableItem(IDM_RESTORE_WINDOWS);
+        submenu.disableItem(IDM_COPY);
+        return true;
+      }
+      else {
+        int i, k;
+        for (i = k = 0; i < n; i++) {
+          if (!AgFrame::windowRegistry[i].window->isVisible()) {
+	    k++;
+	  }
+        }
+        if (k == 0) {
+	  submenu.disableItem(IDM_RESTORE_WINDOWS);
+	}
+
+        for (i = k = 0; i < n; i++) {
+          if (AgFrame::windowRegistry[i].window->isVisible()) {
+	    k++;
+	  }
+        }
+        if (k == 0) {
+	  submenu.disableItem(IDM_HIDE_WINDOWS);
+	}
+      }
+
+      AgFrame *activeWindow = 0;
+      while (n--) {
+	if (AgFrame::windowRegistry[n].isActive) {
+	  activeWindow = AgFrame::windowRegistry[n].window;
+	  break;
+	}
+      }
+      LOGV((int) activeWindow);
+      if (activeWindow) {
+	LOGV(activeWindow->copyTitle());
+      }
+      int disableFlag = 
+	(activeWindow == 0) || !activeWindow->copyTitle().exists();
+      if (disableFlag) {
+	submenu.disableItem(IDM_COPY);
+      }
+      else {
+        char buf[200];
+        sprintf(buf, "Co%cpy %s", TILDE, activeWindow->copyTitle().pointer());
+        IMenuItem item = submenu.menuItem(IDM_COPY);
+        item.setDisabled(disableFlag);
+        item.setText(buf);
+        submenu.setItem(item);
+      }
+      submenu.addSeparator(10000);
+      int itemHeight = submenu.itemRect(IDM_COPY).size().height();
+      LOGV(submenu.itemRect(IDM_COPY).asString()) LCV(itemHeight);
+      if (itemHeight == 0) {
+        itemHeight = submenu.font().maxCharHeight();
+        LOGV(itemHeight);
+      }
+      int magicNumber = IWindow::desktopWindow()->size().height()/itemHeight;
+      LOGV(magicNumber);
+
+      n = AgFrame::windowRegistry.size();
+      for (ln = 0; ln < n; ln++) {
+        WindowRecord &windowRecord = AgFrame::windowRegistry[ln];
+        int view = windowRecord.window->windowTitle.viewNumber();
+        AgString title = windowRecord.title;
+        if (view) {
+          char buf[10];
+          sprintf(buf, ":%d", view);
+          title = windowRecord.title.concat(buf);
+        }
+        submenu.addText(windowRecord.id, title.pointer());
+        //submenu.checkItem(windowRecord.id, windowRecord.isActive);
+
+        IMenuItem item(windowRecord.id);
+        item.setText(title.pointer());
+        item.setChecked(windowRecord.isActive);
+        if ((ln + 7) % magicNumber == 0) {
+          item.setLayout(IMenuItem::splitWithSeparatorLayout);
+        }
+        submenu.setItem(item);
+        LOGV(windowRecord.title.pointer());
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+Boolean ControlPanel::menuEnded(IMenuEvent &event) {
+  LOGSECTION("ControlPanel::menuEnded");
+  LOGV(selectedMenuText);
+  AgFrame::menuShowingFlag = 0;
+  LOGV(AgFrame::menuShowingFlag);
+  if (helpRequested) {
+    AgHelpWindow::showHelp(selectedMenuText);
+    helpRequested = 0;
+  }
+  if (!helpCursorSet) {
+    selectedMenuText.discardData();
+  }
+  return false;
+}
+
+void ControlPanel::closeWindows() {
+  LOGSECTION("ControlPanel::closeWindows");
+  int n = AgFrame::windowRegistry.size();
+  LOGV(n);
+  AgStack<AgFrame*> windowStack;
+  for (int i = 0; i< n; i++) {
+    AgFrame *window = AgFrame::windowRegistry[i].window;
+    windowStack.push(window);
+    LOGV(AgFrame::windowRegistry[i].title.pointer());
+    window->closeModalDialog();
+    window->closeAction.performDeferred();
+  }
+  while(windowStack.size()) {
+    AgFrame *window = windowStack.pop();
+    AgFrame::windowRegistry.remove(window->id());
+  }
+  cascadeOffset = cascadeOrigin;
+}
+
+void ControlPanel::hideWindows() {
+  LOGSECTION("ControlPanel::hideWindows");
+  int n = AgFrame::windowRegistry.size();
+  for (int i = 0; i< n; i++) {
+    AgFrame *window = AgFrame::windowRegistry[i].window;
+    LOGV(AgFrame::windowRegistry[i].title.pointer());
+    AgFrame::windowRegistry[i].isShowing = window->isVisible();
+    window->hide();
+    AgFrame::windowRegistry[i].isActive = 0;
+  }
+}
+
+void ControlPanel::restoreWindows() {
+  LOGSECTION("ControlPanel::restoreWindows");
+  int n = AgFrame::windowRegistry.size();
+  int i;
+  int active = AgFrame::windowRegistry.size();
+  for (i = 0; i< n; i++) {
+    LOGV(AgFrame::windowRegistry[i].isShowing);
+    LOGV(AgFrame::windowRegistry[i].title.pointer());
+    AgFrame::windowRegistry[i].window->IWindow::show();
+    AgFrame::windowRegistry[i].isShowing = 0;
+    if (AgFrame::windowRegistry[i].isActive) {
+      active = i;
+    }
+  }
+  n = AgFrame::windowRegistry.size();
+  if (active && active < n) {
+    AgFrame::windowRegistry[active].window->mySetFocus();
+  }
+}
+
+void ControlPanel::closeSyntaxWindows() {
+  LOGSECTION("ControlPanel::closeSyntaxWindows");
+  int n = AgFrame::windowRegistry.size();
+  AgStack<AgFrame*> windowStack;
+  for (int i = 0; i < n; i++) {
+    AgFrame *window = AgFrame::windowRegistry[i].window;
+    if (!window->syntaxDependent) {
+      continue;
+    }
+    window->closeModalDialog();
+    window->closeAction.performDeferred();
+    windowStack.push(window);
+  }
+  while(windowStack.size()) {
+    AgFrame *window = windowStack.pop();
+    AgFrame::windowRegistry.remove(window->id());
+  }
+
+  if (AgFrame::windowRegistry.size() == 0) {
+    cascadeOffset = cascadeOrigin;
+  }
+}