view anagram/vaclgui/ctrlpanel.cpp @ 14:a02e9434072e

Fix friend declaration for gcc10. XXX: did not check it against the IBM compiler, might end up needing XXX: to be conditional.
author David A. Holland
date Tue, 31 May 2022 00:59:42 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * 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;
  }
}