diff anagram/vaclgui/ftview.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/ftview.cpp	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,1355 @@
+/*
+ * AnaGram, A System for Syntax Directed Programming
+ * Copyright 1997-2002 Parsifal Software. All Rights Reserved.
+ * See the file COPYING for license and usage terms.
+ *
+ * ftview.cpp
+ */
+
+//#include <imsgbox.hpp>
+//#include <itbarcnr.hpp>
+
+#include "agstring.h"
+#include "agview.hpp"
+#include "arrays.h"
+#include "ctrlpanel.hpp"
+#include "data.h"
+#include "dc.h"
+#include "dvplug.hpp"
+#include "ftpar.h"
+#include "ftview.hpp"
+#include "helpview.hpp"
+#include "myalloc.h"
+#include "p.h"
+#include "rule.h"
+#include "vaclgui.hpp"
+
+//#define INCLUDE_LOGGING
+#include "log.h"
+
+
+#define PARSE_FILE  "&Parse File"
+#define SINGLE_STEP "&Single step"
+#define RELOAD      "Re&load"
+#define RESET       "&Reset"
+#define HELP        "&Help"
+#define SYNCH_PARSE "&Synch Parse"
+
+//void logChildren(IWindow *window) {
+//  LOGSECTION("logChildren");
+//  LOGV(window->id());
+//  IWindow::ChildCursor cursor(*window);
+//  for (cursor.setToFirst(); cursor.isValid(); cursor.setToNext()) {
+//    IWindow child(window->childAt(cursor));
+//    LOGS("  ") LV(child.id());
+//  }
+//}
+
+FileTraceView::FileTraceView(FileTraceWindow *frame_,
+			     text_file text_,
+			     AgString fileName_)
+  : ICanvas(nextChildId(), frame_, frame_, IRectangle(),
+	      ICanvas::classDefaultStyle
+	    | IWindow::clipChildren)
+  , mainSplitter(nextChildId(), this, this, IRectangle(),
+		   ISplitCanvas::horizontal
+		 | IWindow::visible)
+  , tracePanels(nextChildId(), &mainSplitter, &mainSplitter, IRectangle(),
+		ISplitCanvas::classDefaultStyle)
+  , leftPanel(nextChildId(), &tracePanels, &tracePanels, IRectangle(),
+	      visible)
+  , rightPanel(nextChildId(), &tracePanels, &tracePanels, IRectangle(),
+	       visible)
+  , stackView(&leftPanel)
+  , fileView(&rightPanel, text_, fileName_)
+  , fileTitle(nextChildId(), &rightPanel, &rightPanel)
+  , fileName(fileName_)
+  , textFile(text_)
+  , bottomPanel(nextChildId(), &mainSplitter, &mainSplitter, IRectangle(),
+		  ISplitCanvas::vertical
+		| visible)
+  , reductionChoiceView(&bottomPanel)
+  , ruleView(&bottomPanel)
+  , frame(frame_)
+  , dataColorChange(this, onColorChange)
+  , fontChange(this, onFontChange)
+  , focusControl(FileTraceWindow::fileTab)
+  , activePanel(FileTraceWindow::fileTab)
+  , fileViewHelp(&rightPanel, "Test File")
+{
+  LOGSECTION("FileTraceView::FileTraceView");
+
+  LOGV((int) &mainSplitter);
+  LOGV((int) &tracePanels);
+  LOGV((int) &leftPanel);
+  LOGV((int) &rightPanel);
+  LOGV((int) &bottomPanel);
+  LOGV((int) &stackView);
+  LOGV((int) &fileView);
+  LOGV((int) &reductionChoiceView);
+  LOGV((int) &ruleView);
+  LOGV((int) &this);
+
+  LOGV(id()) LCV(handle().asDebugInfo());
+  LOGV(leftPanel.id()) LCV((int) &leftPanel) 
+    LCV(leftPanel.handle().asDebugInfo());
+  LOGV(rightPanel.id()) LCV((int) &rightPanel)
+    LCV(rightPanel.handle().asDebugInfo());
+  LOGV(stackView.id()) LCV((int) &stackView)
+    LCV(stackView.handle().asDebugInfo());
+  LOGV(fileView.id()) LCV((int) &fileView)
+    LCV(fileView.handle().asDebugInfo());
+  LOGV(fileTitle.id()) LCV((int) &fileTitle)
+    LCV(fileTitle.handle().asDebugInfo());
+
+  setFont(stackView.dataArea.font());
+
+  ruleView.setEnterAction(AgAction());
+  ruleView.copyTitle = "File Trace: Rule Stack";
+  reductionChoiceView.copyTitle = "File Trace: Reduction Choices";
+  stackView.copyTitle = "File Trace: Parser Stack";
+
+  dataColorChange.attach(&ColorSpec::inactiveTitle);
+  dataColorChange.attach(&ColorSpec::activeTitle);
+  fontChange.attach(&FontSpec::columnHead);
+
+  reductionMenu = new FtParserReductionDc(fileView.parser);
+  AgDataViewPlug *connector = new AgDataViewPlug(reductionMenu);
+  reductionMenu->windowConnector = connector;
+  reductionChoiceView.init(connector);
+
+  bottomPanel.setSplitWindowPercentage(&reductionChoiceView, 0);
+  bottomPanel.setSplitWindowPercentage(&ruleView, 100);
+
+  fileTitle
+   . setText(fileName.pointer())
+   . setAlignment(IStaticText::centerCenter)
+   . setBackgroundColor(ColorSpec::inactiveTitle.bg())
+   . setForegroundColor(ColorSpec::inactiveTitle.fg())
+   ;
+  LOGS("titles set up");
+  //dc_ref stackWindow = new FtParserDc(fileView.parser);
+  parserDc = new FtParserDc(fileView.parser);
+
+  //fileView.parser.displayControl = stackWindow;
+  //stackConnector = new AgDataViewPlug(stackWindow);
+  stackConnector = new AgDataViewPlug(parserDc);
+  //stackWindow->windowConnector = stackConnector;
+  parserDc->windowConnector = stackConnector;
+  stackView.init(stackConnector);
+
+  itemStack = fileView.parser.x1x_new();
+  //dc_ref ruleWindow = new rule_stack_dc(itemStack,0,stackWindow->head_title);
+  //ruleControl = new rule_stack_dc(itemStack,0, stackWindow->head_title);
+  ruleControl = new rule_stack_dc(itemStack, 0, parserDc->head_title);
+  //fileView.parser.ruleControl = ruleWindow;
+  //ruleConnector = new AgDataViewPlug(ruleWindow);
+  ruleConnector = new AgDataViewPlug(ruleControl);
+  //ruleWindow->windowConnector = ruleConnector;
+  ruleControl->windowConnector = ruleConnector;
+  ruleView.init(ruleConnector);
+
+  int width = stackView.tableWidth;
+  int height = font().externalLeading() + font().maxSize().height();
+  ISize minSize(width, 5*height);
+
+  LOGV(minSize.asString());
+  leftPanel
+   . addToCell(&stackView, 1,1)
+   . setColumnWidth(1,width,true)
+   . setRowHeight(1,0,true)
+   . setMinimumSize(minSize)
+   ;
+  width = fileTitle.minimumSize().width();
+  int maxWidth = IWindow::desktopWindow()->size().width()/3;
+  IFont titleFont = fileTitle.font();
+  int lineHeight = titleFont.maxCharHeight() + titleFont.externalLeading() 
+    + titleFont.maxDescender();
+  if (width > maxWidth) {
+    width = maxWidth;
+  }
+  minSize.setWidth(maxWidth);
+  minSize.setHeight(lineHeight);
+  fileTitle.setMinimumSize(minSize);
+  minSize = ISize(width, 5*height);
+  LOGV(minSize.asString());
+  rightPanel
+   . addToCell(&fileTitle, 1, 1)
+   . addToCell(&fileView,  1, 2)
+   . setColumnWidth(1, width, true)
+   . setRowHeight(2, 0, true)
+   . setMinimumSize(minSize)
+   ;
+  mainSplitter.setSplitWindowPercentage(&tracePanels, 60);
+  mainSplitter.setSplitWindowPercentage(&bottomPanel, 40);
+  tracePanels.setSplitWindowPercentage(&leftPanel, 25);
+  tracePanels.setSplitWindowPercentage(&rightPanel, 75);
+  LOGS("splitters set");
+  AgFocusHandler::handleEventsFor(&stackView.dataArea);
+  AgFocusHandler::handleEventsFor(&fileTitle);
+  AgFocusHandler::handleEventsFor(&fileView.dataArea);
+  AgFocusHandler::handleEventsFor(&reductionChoiceView.dataArea);
+  AgFocusHandler::handleEventsFor(&ruleView.dataArea);
+  LOGS("Focus handler set");
+  IMouseHandler::handleEventsFor(&fileTitle);
+  IPaintHandler::handleEventsFor(this);
+  LOGS("Mouse handler set");
+  focusControl = FileTraceWindow::fileTab;
+  LOGS("all done");
+}
+
+FileTraceView::~FileTraceView() {
+  AgFocusHandler::stopHandlingEventsFor(&stackView.dataArea);
+  AgFocusHandler::stopHandlingEventsFor(&fileTitle);
+  AgFocusHandler::stopHandlingEventsFor(&fileView.dataArea);
+  AgFocusHandler::stopHandlingEventsFor(&reductionChoiceView.dataArea);
+  AgFocusHandler::stopHandlingEventsFor(&ruleView.dataArea);
+  IMouseHandler::stopHandlingEventsFor(&fileTitle);
+  IPaintHandler::stopHandlingEventsFor(this);
+}
+
+Boolean FileTraceView::paintWindow(IPaintEvent &event) {
+  LOGSECTION("FileTraceView::paintWindow");
+  LOGV(event.rect().asString());
+  event.clearBackground(IGUIColor::dialogBgnd);
+  return false;
+}
+
+FileTraceView &FileTraceView::refreshRules(int rule) {
+  LOGSECTION("FileTraceView::refreshRules");
+  LOGV(rule);
+  FtParser &parser = fileView.parser;
+  delete_tsd(itemStack);
+  itemStack = parser.x1x_new();
+  //parser.ruleControl->parser_stack = parser.itemStack;
+  ruleControl->parser_stack = itemStack;
+  int k = itemStack->nt;
+  int ln = parser.stateStack.size();
+  //parser.ruleControl->des->d_size.y = k;
+  ruleControl->des->d_size.y = k;
+  //LOGV(k);
+  while (k--) {
+    int sx, sn, fn, fx;
+    xtxf(itemStack, k, &sx, &sn, &fn, &fx);
+    int length = Rule(fn)->length();
+    //LOGV(length);
+    if (sx == ln && rule == 0) {
+      break;
+    }
+    if (rule && fn == rule && fx == 0 && sx+length >= ln) {
+      break;
+    }
+  }
+  k = itemStack->nt - 1 - k;
+  //LOGV(k);
+
+  ruleView
+   . reset()
+   . setCursorLine(itemStack->nt-1)
+   . setCursorLine(k)
+   . synchCursor(k);
+   //. refresh();
+  return *this;
+}
+
+Boolean FileTraceView::mouseClicked(IMouseClickEvent &event) {
+  LOGSECTION("FileTraceView::mouseClicked");
+  LOGV(event.mouseButton()) LCV(event.mouseAction());
+  if (event.mouseAction() != IMouseClickEvent::down) {
+    return false;
+  }
+  IWindow *controlWindow = event.controlWindow();
+  if (controlWindow == &fileTitle) {
+    fileView.dataArea.setFocus();
+    focusControl = FileTraceWindow::fileTab;
+    return false;
+  }
+  return false;
+}
+
+Boolean FileTraceView::gotFocus(IEvent &event) {
+  LOGSECTION("FileTraceView::gotFocus");
+  LOGV(focusControl);
+  IWindowHandle handle = (void *) event.parameter1();
+  //IWindow *lastWindow = IWindow::windowWithHandle(handle);
+  //LOGV(handle.asUnsigned()) LCV((int) lastWindow);
+  LOGV((int) event.controlWindow()) LCV((int) event.dispatchingWindow());
+  if (event.controlWindow() == &fileView.dataArea) {
+    ColorSpec *color = &ColorSpec::activeTitle;
+    fileTitle.setBackgroundColor(color->bg());
+    fileTitle.setForegroundColor(color->fg());
+    focusControl = activePanel = FileTraceWindow::fileTab;
+
+    fileTitle.refresh();
+  }
+  else if (event.controlWindow() == &stackView.dataArea) {
+    focusControl = activePanel = FileTraceWindow::stackTab;
+  }
+  else if (event.controlWindow() == &reductionChoiceView.dataArea) {
+    focusControl = activePanel = FileTraceWindow::choiceTab;
+  }
+  else if (event.controlWindow() == &ruleView.dataArea) {
+    focusControl = activePanel = FileTraceWindow::ruleTab;
+  }
+  frame->parseButton.disableDefault();
+  frame->resetButton.disableDefault();
+  frame->reloadButton.disableDefault();
+  frame->helpButton.disableDefault();
+  frame->stepButton.enableDefault();
+
+  LOGV(focusControl);
+  return false;
+}
+
+Boolean FileTraceView::lostFocus(IEvent &event) {
+  LOGSECTION("FileTraceView::lostFocus");
+  LOGV(focusControl);
+  IWindowHandle handle = (void *) event.parameter1();
+  //IWindow *nextWindow = IWindow::windowWithHandle(handle);
+  //LOGV(handle.asUnsigned()) LCV((int) nextWindow);
+  if (event.controlWindow() == &fileView.dataArea) {
+    ColorSpec *color = &ColorSpec::inactiveTitle;
+    fileTitle.setBackgroundColor(color->bg());
+    fileTitle.setForegroundColor(color->fg());
+    fileTitle.refresh();
+  }
+  return false;
+}
+
+Boolean FileTraceWindow::characterKeyPress(IKeyboardEvent &event) {
+  LOGSECTION("FileTraceWindow::characterKeyPress");
+  ok_ptr(this);
+  char character = event.character();
+  LOGV(character) LCV(event.isCtrlDown());
+  if (event.isCtrlDown()) {
+    return true;
+  }
+  if (canvas.focusControl < stepTab) {
+    canvas.activePanel = canvas.focusControl;
+  }
+  switch (character) {
+    case 'p':
+    case 'P':
+      parseFile();
+      return true;
+    case 's':
+    case 'S':
+      doStep();
+      return true;
+    case 'r':
+    case 'R':
+      resetParser();
+      return true;
+    case 'l':
+    case 'L':
+      reload();
+      return true;
+    case 'h':
+    case 'H':
+      AgHelpWindow::showHelp("File Trace");
+      helpButton.disableDefault();
+      helpButton.unhighlight();
+      stepButton.enableDefault();
+      canvas.focusControl = fileTab;
+      return true;
+  }
+  return false;
+}
+
+Boolean FileTraceWindow::virtualKeyPress(IKeyboardEvent &event) {
+  LOGSECTION("FileTraceWindow::virtualKeyPress");
+  ok_ptr(this);
+  int increment = 0;
+  int &focusControl = canvas.focusControl;
+  int &activePanel = canvas.activePanel;
+  LOGV(focusControl);
+  LOGV((int) event.controlWindow()) LCV((int) event.dispatchingWindow());
+  LOGV(event.virtualKey());
+  switch (event.virtualKey()) {
+    case IKeyboardEvent::enter:
+    case IKeyboardEvent::newLine: {
+      //activePanel = focusControl;
+      if (focusControl >= stepTab) {
+	tabControl[focusControl].action.performDeferred();
+	IPushButton *button = (IPushButton *)tabControl[focusControl].window;
+	button->disableDefault();
+	button->unhighlight();
+      }
+      else {
+	activePanel = focusControl;
+	doStep();
+      }
+      return true;
+    }
+    case IKeyboardEvent::right:
+    case IKeyboardEvent::down:
+      if (focusControl < stepTab) {
+	return AgFrame::virtualKeyPress(event);
+      }
+      if (focusControl + 1 == nTabs) {
+	increment = stepTab - focusControl;
+      }
+      else {
+	increment = 1;
+      }
+      break;
+    case IKeyboardEvent::tab:
+      increment = 1;
+      break;
+    case IKeyboardEvent::left:
+    case IKeyboardEvent::up:
+      if (focusControl < stepTab) {
+	return AgFrame::virtualKeyPress(event);
+      }
+      if (focusControl == stepTab) {
+	increment = nTabs - 1 - stepTab;
+      }
+      else {
+	increment = nTabs - 1;
+      }
+      break;
+    case IKeyboardEvent::backTab:
+      increment = nTabs - 1;
+      break;
+    default:
+      return AgFrame::virtualKeyPress(event);
+  }
+  if (event.controlWindow() != event.dispatchingWindow()) {
+    return true;
+  }
+  IPushButton *button;
+  if (focusControl >= stepTab) {
+    button = (IPushButton *) tabControl[focusControl].window;
+    button->unhighlight();
+    button->disableDefault();
+  }
+  do {
+    focusControl = (focusControl + increment) % nTabs;
+  } while (!tabControl[focusControl].enabled);
+  LOGV(focusControl) LCV(increment);
+  if (focusControl >= stepTab) {
+    button = (IPushButton *) tabControl[focusControl].window;
+  }
+  else {
+    button = &stepButton;
+  }
+  button->enableDefault();
+  setFocus();
+  return true;
+}
+
+Boolean FileTraceWindow::mouseClicked(IMouseClickEvent &event) {
+  LOGSECTION("FileTraceWindow::mouseClicked");
+  ok_ptr(this);
+  LOGV(event.mouseButton()) LCV(event.mouseAction());
+  if (event.mouseButton() != 0) {
+    return false;
+  }
+  int &focusControl = canvas.focusControl;
+  int &activePanel = canvas.activePanel;
+  IWindow *controlWindow = event.controlWindow();
+  LOGV((int)controlWindow) LCV((int)event.dispatchingWindow());
+
+  if (event.mouseAction() == IMouseClickEvent::click) {
+    return false;
+  }
+  if (event.mouseAction() == IMouseClickEvent::doubleClick) {
+    return false;
+  }
+
+  int tab;
+  for (tab = 0; tab < nTabs; tab++) {
+    LOGV(tab) LCV((int) tabControl[tab].window);
+    if (controlWindow == tabControl[tab].window) {
+      break;
+    }
+  }
+  if (tab == nTabs) {
+    return False;
+  }
+
+  if (ControlPanel::helpCursorSet) {
+    if (event.mouseAction() == IMouseClickEvent::up) {
+      ControlPanel::helpCursorSet = 0;
+      LOGV(tabControl[tab].helpTopic);
+      AgHelpWindow::showHelp(tabControl[tab].helpTopic);
+      ControlPanel::resetCursor();
+    }
+    return true;
+  }
+  LOGV(focusControl) LCV(activePanel);
+  if (tab < stepTab) {
+    return false;
+  }
+  if (focusControl >= stepTab) {
+    IPushButton *button = (IPushButton *) tabControl[focusControl].window;
+    button->unhighlight();
+    button->disableDefault();
+  }
+  IPushButton *button = (IPushButton *) tabControl[tab].window;
+  if (event.mouseAction() == IMouseClickEvent::down) {
+    if (focusControl < stepTab) {
+      activePanel = focusControl;
+    }
+    button->highlight();
+    button->setFocus();
+    focusControl = tab;
+    button->capturePointer();
+    return true;
+  }
+  if (event.mouseAction() == IMouseClickEvent::up) {
+    button->unhighlight();
+    button->releasePointer();
+    AgAction &action = tabControl[tab].action;
+    IWindowHandle h = tabControl[tab].window->handle();
+    if (h == event.windowUnderPointer()) {
+      action.performDeferred();
+    }
+    else if (activePanel < stepTab) {
+      button->disableDefault();
+      parseButton.enableDefault();
+      focusControl = activePanel;
+      setFocus();
+    }
+    else {
+      button->disableDefault();
+      stepButton.enableDefault();
+      focusControl = stepTab;
+      setFocus();
+    }
+    return true;
+  }
+  return false;
+}
+
+
+FileTraceWindow &FileTraceWindow::setFocus() {
+  LOGSECTION("FileTraceWindow::setFocus");
+  ok_ptr(this);
+  int &focusControl = canvas.focusControl;
+  if (focusControl < stepTab) {
+    canvas.activePanel = focusControl;
+  }
+  LOGV(focusControl) LCV((int) tabControl[focusControl].window);
+  tabControl[focusControl].window->setFocus();
+  IPushButton *button;
+  for (int i = stepTab; i < nTabs; i++) {
+    button = (IPushButton *)tabControl[i].window;
+    button->disableDefault();
+    button->unhighlight();
+  }
+  button = &stepButton;
+  if (focusControl > stepTab) {
+    button = (IPushButton *)tabControl[focusControl].window;
+  }
+  button->enableDefault();
+  return *this;
+}
+
+
+FileTraceWindow::FileTraceWindow(AgString fileName_,
+				 int flags)
+  : AgFrame(  IFrameWindow::dialogBackground
+	    | IFrameWindow::systemMenu
+	    | IFrameWindow::maximizeButton
+	    | IFrameWindow::sizingBorder)
+  , canvas(this, text_file(fileName_, flags), fileName_)
+  , fileName(fileName_)
+  , toolBar(this, ISetCanvas::packTight | ISetCanvas::centerVerticalAlign)
+  , locationField(nextChildId(), &toolBar, &toolBar, IRectangle(),
+		    IStaticText::defaultStyle()
+		  | IStaticText::center
+		  | IStaticText::vertCenter
+		  | IStaticText::border3D)
+  , locationFieldHelp(&locationField, "Parse Location")
+  , statusField(nextChildId(), &toolBar, &toolBar, IRectangle(),
+		  IStaticText::defaultStyle()
+		| IStaticText::center
+		| IStaticText::vertCenter
+		| IStaticText::border3D)
+  , statusFieldHelp(&statusField, "Parse Status")
+  , buttonGroup(&toolBar, ISetCanvas::packExpanded)
+  , stepButton(IDTB_STEP, &buttonGroup, SINGLE_STEP)
+  , parseButton(IDTB_PARSE_FILE, &buttonGroup, PARSE_FILE)
+  , resetButton(IDTB_RESET, &buttonGroup, RESET)
+  , reloadButton(IDTB_RELOAD, &buttonGroup, RELOAD)
+  , helpButton(IDTB_HELP, &buttonGroup, HELP)
+{
+  LOGSECTION("FileTraceWindow::FileTraceWindow");
+  ok_ptr(this);
+
+  tabControl[stackTab] = TabControl(&canvas.stackView.dataArea,
+				    "Parser Stack Pane");
+  tabControl[fileTab] = TabControl(&canvas.fileView.dataArea,
+				   "Test File Pane");
+  tabControl[choiceTab] = TabControl(&canvas.reductionChoiceView.dataArea,
+				     "Reduction Choices Pane");
+  tabControl[choiceTab].enabled = 0;
+  tabControl[ruleTab] = TabControl(&canvas.ruleView.dataArea, 
+				   "Rule Stack Pane");
+  tabControl[stepTab]
+    = TabControl(&stepButton, "Single Step", actionObject(this, doStep));
+  tabControl[parseTab]
+    = TabControl(&parseButton, "Parse File", actionObject(this, parseFile));
+  tabControl[resetTab]
+    = TabControl(&resetButton, "Reset", actionObject(this, resetParser));
+  tabControl[reloadTab]
+    = TabControl(&reloadButton, "Reload", actionObject(this, reload));
+  tabControl[helpTab]
+    = TabControl(&helpButton, "File Trace", actionObject(this, showHelp));
+
+#ifdef INCLUDE_LOGGING
+  {
+    for (int tab = 0; tab < nTabs; tab++) {
+      LOGV(tab) LCV((int) tabControl[tab].window);
+    }
+  }
+#endif
+  setFont(canvas.stackView.dataArea.font());
+
+  ISize buttonSize= stepButton.minimumSize();
+  IFont buttonFont = stepButton.font();
+  int buttonWidth = buttonFont.textWidth(" Synch Parse ");
+  LOGV(buttonWidth);
+  buttonSize.setWidth(buttonWidth);
+  stepButton.setMinimumSize(buttonSize);
+  parseButton.setMinimumSize(buttonSize);
+  int buttonHeight = buttonSize.height();
+
+  syntaxDependent = 1;
+  IColor buttonTextColor = stepButton.foregroundColor();
+
+  ISize minimum(buttonWidth, buttonHeight);
+  LOGV(minimum.asString());
+
+  locationField.setFont(buttonFont);
+
+  locationField.setMinimumSize(
+    ISize(locationField.font().textWidth("9999:999"), 
+	  minimum.height())
+  );
+  locationField.setBackgroundColor(IGUIColor::dialogBgnd);
+  locationField.setForegroundColor(buttonTextColor);
+  LOGV(locationField.minimumSize().asString());
+
+  statusField.setFont(buttonFont);
+  LOGV(statusField.minimumSize().asString());
+  statusField.setMinimumSize(
+    ISize(statusField.font().textWidth("MSelect reduction tokenM"), 
+	  minimum.height())
+  );
+  LOGV(statusField.minimumSize().asString());
+  statusField.setBackgroundColor(IGUIColor::dialogBgnd);
+  statusField.setForegroundColor(buttonTextColor);
+
+  ISize margin = toolBar.margin();
+  margin.setHeight(0);
+  toolBar.setMargin(margin);
+  margin = buttonGroup.margin();
+  margin.setWidth(0);
+  margin.setHeight(margin.height()/2);
+  buttonGroup.setMargin(margin);
+  ISize pad = buttonGroup.pad();
+  pad.setWidth(0);
+  buttonGroup.setPad(pad);
+
+  stepButton.enableDefault();
+
+  LOGV(stepButton.minimumSize().asString());
+  LOGV(parseButton.minimumSize().asString());
+  LOGV(resetButton.minimumSize().asString());
+  LOGV(reloadButton.minimumSize().asString());
+  LOGV(helpButton.minimumSize().asString());
+
+  LOGV((int) this);
+  setClient(&canvas);
+  AgString objectTitle = AgString::format("AnaGram : %s",
+					  simple_file_name.pointer());
+  windowTitle.setObjectText(objectTitle.pointer());
+
+  addExtension(&toolBar, IFrameWindow::belowClient, IFrameWindow::thickLine);
+  canvas.fileView.desynchAction = actionObject(this, onDesynch);
+  canvas.fileView.resynchAction = actionObject(this, onResynch);
+
+  windowTitle.setViewText("File Trace");
+  registerTitle("File Trace");
+
+  canvas.stackView.setColumnTitles("\tState\tToken\tToken Name");
+  ISize sizeLeft = canvas.stackView.suggestSize();
+  ISize sizeRight = canvas.fileView.suggestSize();
+  LOGV(sizeLeft.asString());
+  LOGV(sizeRight.asString());
+  int thickness =
+    2*canvas.tracePanels.splitBarThickness(ISplitCanvas::splitBarEdge);
+  thickness +=
+    canvas.tracePanels.splitBarThickness(ISplitCanvas::splitBarMiddle);
+  int width = sizeLeft.width() + sizeRight.width() + thickness;
+  int height = max(2*sizeLeft.height(), sizeRight.height());
+  height += height/2;
+
+  LOGV(width) LCV(height);
+  int maxWidth = 2*IWindow::desktopWindow()->size().width()/3;
+  LOGV(maxWidth);
+  int toolWidth = toolBar.minimumSize().width();
+  if (maxWidth < toolWidth) {
+    maxWidth = toolWidth;
+  }
+  if (width > maxWidth) {
+    width = maxWidth;
+  }
+  if (width < toolWidth) {
+    width = toolWidth;
+  }
+
+  int left = canvas.stackView.columnHeadWidth;
+  left += 2*font().avgCharWidth();
+  int maxRight = maxWidth - left;
+  int right = sizeRight.width();
+  LOGV(right);
+  LOGV(maxRight);
+  if (right > maxRight) right = maxRight;
+  int sum = left+right;
+  LOGV(left) LCV(right) LCV(sum);
+  canvas.tracePanels.setSplitWindowPercentage(
+    &canvas.leftPanel, (100*left)/sum);
+  canvas.tracePanels.setSplitWindowPercentage(
+    &canvas.rightPanel, (100*right)/sum);
+  LOGS("percentages set") LCV((100*left)/sum) LCV((100*right)/sum);
+  ISize clientSize(width, height);
+  LOGV(clientSize.asString());
+  IRectangle frameRect(frameRectFor(clientSize));
+  LOGV(frameRect.asString());
+  sizeTo(frameRect.size());
+  LOGV(frameRect.size().asString());
+
+  positionFrame();
+  canvas.stackView
+   . setFrame(this)
+   . setEnterAction(AgAction())
+   . setSelectAction(actionObject(this, stackSelect))
+   ;
+
+  canvas.fileView
+   . setFrame(this)
+   . setEnterAction(actionObject(this, fileEnter))
+   ;
+
+  canvas.ruleView
+   . setEnterAction(AgAction())
+   . setSelectAction(actionObject(this, ruleSelect))
+   . setFrame(this)
+   ;
+
+  canvas.reductionChoiceView
+   . setEnterAction(actionObject(this, reductionChoiceEnter))
+   . setSelectAction(actionObject(this, tokenSelect))
+   ;
+
+  FtParser &parser = canvas.fileView.parser;
+  setLocationField(canvas.fileView.parser.displayLocation());
+  statusField.setText(FtParser::processStateText[parser.processState]);
+
+  for (int i = 0; i < nTabs; i++) {
+    IKeyboardHandler::handleEventsFor(tabControl[i].window);
+    IMouseHandler::handleEventsFor(tabControl[i].window);
+  }
+  frameHandler->setActivateAction(actionObject(this, onActivate));
+  AgFocusHandler::handleEventsFor(this);
+  LOGS("Handlers set");
+  canvas.focusControl = canvas.activePanel = fileTab;
+  canvas.fileView.dataArea.setFocus();
+  //setFocus();
+  show();
+  LOGS("all done");
+}
+
+void FileTraceWindow::onDesynch() {
+  LOGSECTION("FileTrace");
+  ok_ptr(this);
+  stepButton.setText(SYNCH_PARSE);
+}
+
+void FileTraceWindow::onResynch() {
+  LOGSECTION("FileTrace");
+  ok_ptr(this);
+  stepButton.setText(SINGLE_STEP);
+}
+
+void FileTraceWindow::onActivate() {
+  LOGSECTION("FileTraceWindow::onActivate");
+  ok_ptr(this);
+  //canvas.setFocus();
+}
+
+FileTraceWindow::~FileTraceWindow() {
+  AgFocusHandler::stopHandlingEventsFor(this);
+  for (int i = 0; i < nTabs; i++) {
+    IKeyboardHandler::stopHandlingEventsFor(tabControl[i].window);
+    IMouseHandler::stopHandlingEventsFor(tabControl[i].window);
+  }
+}
+
+Boolean FileTraceWindow::gotFocus(IEvent &event) {
+  LOGSECTION("FileTraceWindow::gotFocus");
+  ok_ptr(this);
+  //int &focusControl = canvas.focusControl;
+  //LOGV(focusControl);
+  IWindowHandle handle = (void *) event.parameter1();
+  //IWindow *lastWindow = IWindow::windowWithHandle(handle);
+  //LOGV((int) lastWindow);
+  LOGV((int) &canvas.stackView.dataArea);
+  LOGV((int) &canvas.ruleView.dataArea);
+  return false;
+}
+
+AgString FileTraceWindow::copyTitle() {
+  ok_ptr(this);
+
+  switch (canvas.focusControl) {
+    case 0: return canvas.stackView.copyTitle;;
+    case 2: return canvas.reductionChoiceView.copyTitle;;
+    case 3: return canvas.ruleView.copyTitle;;
+  }
+  return AgString();
+}
+
+FileTraceWindow  &FileTraceWindow::copyTo(IClipboard &c) {
+  ok_ptr(this);
+
+  switch (canvas.focusControl) {
+    case 0: canvas.stackView.copyTo(c); break;
+    case 2: canvas.reductionChoiceView.copyTo(c); break;
+    case 3: canvas.ruleView.copyTo(c); break;
+  }
+  return *this;
+}
+
+
+Boolean FileTraceWindow::windowResize(IResizeEvent &event){
+  LOGSECTION("FileTraceWindow::windowResize");
+  ok_ptr(this);
+
+  if (event.controlWindow() != this) {
+    return false;
+  }
+  canvas.mainSplitter.sizeTo(
+    clientRectFor(IRectangle(IPoint(), event.newSize())).size()
+  );
+  LOGV(id());
+  return false;
+}
+
+FileTraceWindow &FileTraceWindow::setLocationField(cint loc) {
+  ok_ptr(this);
+  char buffer[100];
+  sprintf(buffer, "%d:%d", loc.y+1, loc.x+1);
+  locationField.setText(buffer);
+  return *this;
+}
+
+FileTraceWindow &FileTraceWindow::setStatusField(const char *msg) {
+  ok_ptr(this);
+  statusField.setText(msg);
+  statusField.refresh(IWindow::immediate);
+  return *this;
+}
+
+FileTraceWindow &FileTraceWindow::showReductionSelection() {
+  LOGSECTION("FileTraceWindow::showReductionSelection");
+  ok_ptr(this);
+  FtParser &parser = canvas.fileView.parser;
+  canvas.reductionMenu = new FtParserReductionDc(parser);
+  AgDataViewPlug *connector = new AgDataViewPlug(canvas.reductionMenu);
+  canvas.reductionMenu->windowConnector = connector;
+
+  canvas.reductionChoiceView.init(connector);
+
+  LOGV(canvas.reductionMenu->columnHeadTitle.pointer());
+  LOGV(connector->columnHeadTitle().pointer());
+
+  ISize tableSize = canvas.reductionChoiceView.suggestSize();
+
+  int width = 40*font().avgCharWidth();
+  int testWidth = tableSize.width();
+  if (testWidth < width/2) {
+    width = width/2;
+  }
+  else if (testWidth > 2*width) {
+    width = 2*width;
+  }
+  else {
+    width = testWidth;
+  }
+
+  int rightWidth = canvas.bottomPanel.size().width();
+
+  int thickness =
+    2*canvas.tracePanels.splitBarThickness(ISplitCanvas::splitBarEdge);
+  thickness +=
+    canvas.tracePanels.splitBarThickness(ISplitCanvas::splitBarMiddle);
+  canvas.bottomPanel.setSplitWindowPercentage(&canvas.reductionChoiceView,
+					      width);
+  canvas.bottomPanel.setSplitWindowPercentage(&canvas.ruleView,
+					      rightWidth - width - thickness);
+
+  canvas.bottomPanel.refresh();
+  LOGV(canvas.size().asString());
+  int ln = parser.reductionSelection;
+  canvas.reductionChoiceView
+   . setCursorLine(ln)
+   . show()
+   ;
+  parser.reductionState.token = ibnfs[ibnfb[parser.ruleToReduce]+ln];
+  canvas.stackView.repaintLine(parser.stateStack.size());
+  canvas.reductionChoiceView.dataArea.setFocus();
+  return *this;
+}
+
+FileTraceView &FileTraceView::completeReduction() {
+  LOGSECTION("FileTraceView::completeReduction");
+  reductionMenu->des->d_size.y = 0;
+  bottomPanel.setSplitWindowPercentage(&reductionChoiceView, 0);
+  bottomPanel.setSplitWindowPercentage(&ruleView, 100);
+  bottomPanel.refresh();
+  FtParser &parser = fileView.parser;
+  int lineNumber = reductionChoiceView.getCursorLine();
+  LOGV(lineNumber);
+  int token = ibnfs[ibnfb[parser.ruleToReduce]+lineNumber];
+  LOGV(token);
+  parser.completeReduction(token);
+  int fileIndex = (char *) parser.state.pointer - parser.text.pointer();
+  fileView.reductionTable[fileIndex] = token;
+  LOGV(fileIndex) LCV(token) LCV(fileView.reductionTable[fileIndex]);
+  return *this;
+}
+
+void FileTraceWindow::reductionChoiceEnter() {
+  LOGSECTION("FileTraceWindow::reductionChoiceEnter");
+  ok_ptr(this);
+  canvas.completeReduction();
+  fileEnter();
+}
+
+void FileTraceWindow::synchRules(unsigned stackIndex, unsigned token) {
+  LOGSECTION("FileTraceWindow::synchRules");
+  ok_ptr(this);
+  FtParser &parser = canvas.fileView.parser;
+  unsigned stackLocation = canvas.itemStack->nt;
+  int sx, sn, snx;
+  if (stackIndex >= parser.stateStack.size()) {
+    sn = parser.state.number;
+  }
+  else {
+    sn = parser.stateStack[stackIndex].number;
+  }
+  state_number_map *sp = &map_state_number[sn];
+  LOGV(stackLocation);
+  while (stackLocation--) {
+    int fn, fx;
+    xtxf(canvas.itemStack,stackLocation, &sx, &snx, &fn, &fx);
+    if (sx == stackIndex) {
+      break;
+    }
+  }
+  int k = stackLocation;
+  LOGV(sn);
+  LOGV(token);
+  if (stackIndex >= parser.stateStack.size()) {
+    int ruleViewLine = canvas.itemStack->nt - stackLocation - 1;
+    do {
+      int fn, fx;
+      xtxf(canvas.itemStack, k, &sx, &snx, &fn, &fx);
+      if (fx < Rule(fn)->length()
+          && token == Rule(fn).token(fx))
+          //&& token == lstptr(map_form_number[fn],tokens)[fx])
+      {
+        k = canvas.itemStack->nt - k - 1;
+        canvas.ruleView.setCursorLine(k).synchCursor(k);
+        ruleViewLine = k;
+        return;
+      }
+      unsigned *p = lstptr(*sp,reductions);
+      unsigned n = sp->n_reductions;
+      while (n--) {
+        unsigned tn = *p++;
+        unsigned rule = *p++;
+        if (rule == fn && tn == token) {
+          k = canvas.itemStack->nt - k - 1;
+          canvas.ruleView.setCursorLine(k).synchCursor(k);
+          ruleViewLine = k;
+          return;
+        }
+      }
+      k--;
+    } while (k >= 0 && sx == stackIndex);
+    canvas.ruleView.setCursorLine(ruleViewLine).synchCursor(ruleViewLine);
+    return;
+  }
+  int nextState;
+  if (stackIndex + 1 >= parser.stateStack.size()) {
+    nextState = parser.state.number;
+  }
+  else {
+    nextState = parser.stateStack[stackIndex+1].number;
+  }
+  int charToken = map_state_number[nextState].char_token;
+  LOGV(nextState) LCV(charToken);
+  do {
+    int fn,fx;
+    xtxf(canvas.itemStack, k, &sx, &snx, &fn, &fx);
+    int length = Rule(fn)->length();
+    LOGV(k) LCV(snx);
+    LOGV(fn) LCV(fx) LCV(length);
+    if (fx < length
+        && charToken == Rule(fn).token(fx)) {
+        //&& charToken == lstptr(map_form_number[fn],tokens)[fx]) {
+      k = canvas.itemStack->nt - k - 1;
+      canvas.ruleView.setCursorLine(k).synchCursor(k);
+      return;
+    }
+    k--;
+    LOGV(k);
+    LOGV(sn) LCV(snx);
+  } while (k >= 0 && sx == stackIndex);
+}
+
+void FileTraceWindow::ruleSelect() {
+  LOGSECTION("FileTraceWindow::ruleSelect");
+  ok_ptr(this);
+  FtParser &parser = canvas.fileView.parser;
+  int ruleLine = canvas.ruleView.getCursorLine();
+
+  int k = canvas.itemStack->nt - ruleLine - 1;
+  LOGV(k);
+  int sx, sn, fn, fx;
+  xtxf(canvas.itemStack, k, &sx, &sn, &fn, &fx);
+  int length = Rule(fn)->length();
+  LOGV(fn);
+  LOGV(fx);
+  LOGV(length);
+  int stackDepth = parser.stateStack.size();
+  int stackLevel = sx;
+  LOGV(stackLevel) LCV(stackDepth);
+  if (stackLevel == stackDepth && 
+      parser.processState == FtParser::selectionRequired) {
+    if (fx >= length) {
+      return;
+    }
+    //int tn = lstptr(map_form_number[fn],tokens)[fx];
+    int tn = Rule(fn).token(fx);
+    LOGV(tn);
+    int n = ibnfn[parser.ruleToReduce];
+    while (n--) {
+      LOGV(n);
+      LOGV(ibnfs[ibnfb[parser.ruleToReduce]+n]);
+      if (ibnfs[ibnfb[parser.ruleToReduce]+n] == tn) {
+	break;
+      }
+    }
+    LOGV(fn) LCV(n) LCV(tn);
+    canvas.reductionChoiceView.setCursorLine(n);
+    parser.reductionState.token = tn;
+    canvas.stackView.repaintLine(stackDepth);
+    return;
+  }
+  canvas.stackView.setCursorLine(stackLevel);
+  //canvas.fileView.turnHighlightOn(stackLevel);
+  if (parser.processState != FtParser::finished) {
+    canvas.fileView.turnHighlightOn(stackLevel);
+  }
+}
+
+void FileTraceWindow::stackSelect() {
+  LOGSECTION("FileTraceWindow::stackSelect");
+  ok_ptr(this);
+  int ln = canvas.stackView.getCursorLine();
+  LOGV(ln);
+  FtParser &parser = canvas.fileView.parser;
+  if (parser.processState != FtParser::finished) {
+    canvas.fileView.turnHighlightOn(ln);
+  }
+  //int sn = parser.state.number;
+  int tn = parser.state.token;
+  if (ln < parser.stateStack.size()) {
+    tn = parser.stateStack[ln].token;
+  }
+  synchRules(ln, tn);
+}
+
+void FileTraceWindow::tokenSelect() {
+  LOGSECTION("FileTraceWindow::tokenSelect");
+  ok_ptr(this);
+  int ln = canvas.reductionChoiceView.getCursorLine();
+  LOGV(ln);
+  FtParser &parser = canvas.fileView.parser;
+  parser.reductionSelection = ln;
+  int flag = parser.validSelection(ln, parser.reductionState.number);
+  parser.processState = 
+    flag ? FtParser::selectionRequired : FtParser::selectionError;
+  statusField.setText(FtParser::processStateText[parser.processState]);
+  parser.reductionState.token = ibnfs[ibnfb[parser.ruleToReduce]+ln];
+  canvas.stackView.repaintLine(parser.stateStack.size());
+}
+
+void FileTraceWindow::fileEnter() {
+  LOGSECTION("FileTraceWindow::fileEnter");
+  ok_ptr(this);
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  LOGV(canvas.fileView.cursorHideCount);
+  if (stepButton.text() != SINGLE_STEP) {
+    stepButton.setText(SINGLE_STEP);
+  }
+  FtParser &parser = canvas.fileView.parser;
+  LOGV(parser.location());
+  unsigned stackDepth = parser.stateStack.size();
+  //parser.displayControl->des->d_size.y = stackDepth+1;
+  canvas.parserDc->des->d_size.y = stackDepth+1;
+  LOGV(stackDepth);
+  LOGV(parser.processState);
+
+  if (parser.processState > FtParser::running) {
+    messageBeep();
+  }
+
+  int stackCursor = stackDepth;
+  canvas.focusControl = canvas.activePanel = fileTab;
+  if (parser.processState == FtParser::selectionRequired) {
+    canvas.fileView.turnHighlightOn(stackCursor);
+
+    int k = parser.stateStack.size() - parser.reductionIndex;
+    LOGV(k);
+    assert((unsigned) k <= (unsigned) parser.stateStack.size());
+    parser.stateStack.discardData(k);
+    unsigned stackDepth = parser.stateStack.size();
+    //parser.displayControl->des->d_size.y = stackDepth+1;
+    canvas.parserDc->des->d_size.y = stackDepth+1;
+
+    showReductionSelection();
+    stackCursor = parser.reductionIndex;
+    canvas.reductionChoiceView.dataArea.setFocus();
+    canvas.focusControl = canvas.activePanel = choiceTab;
+    tabControl[choiceTab].enabled = 1;
+  }
+  else if (parser.ruleToReduce) {
+    parser.ruleToReduce = 0;
+    canvas.reductionMenu->des->d_size.y = 0;
+    canvas.bottomPanel.setSplitWindowPercentage(&canvas.reductionChoiceView,0);
+    canvas.bottomPanel.setSplitWindowPercentage(&canvas.ruleView, 100);
+    canvas.bottomPanel.refresh();
+    statusField.setText(FtParser::processStateText[parser.processState]);
+    canvas.fileView.turnHighlightOff();
+    canvas.fileView.dataArea.setFocus();
+    tabControl[choiceTab].enabled = 0;
+  }
+
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  canvas.stackView.reset();
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  LOGV(canvas.fileView.cursorHideCount);
+  canvas.stackView.setCursorLine(stackCursor);
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  LOGV(canvas.fileView.cursorHideCount);
+  canvas.stackView. refresh();
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  LOGV(canvas.fileView.cursorHideCount);
+
+  LOGV(parser.location());
+  canvas.refreshRules(parser.ruleToReduce);
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  LOGV(canvas.fileView.cursorHideCount);
+  LOGV(parser.location());
+
+  setLocationField(canvas.fileView.parser.displayLocation());
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  LOGV(canvas.fileView.cursorHideCount);
+  setStatusField(FtParser::processStateText[parser.processState]);
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  LOGV(canvas.fileView.cursorHideCount);
+  //canvas.fileView.dataArea.setFocus();
+  //canvas.focusControl = 1;
+  setFocus();
+  LOGV(canvas.focusControl) LCV(canvas.fileView.dataArea.hasFocus());
+  LOGV(canvas.fileView.cursorHideCount);
+
+  AgFrame::windowRegistry.refresh("Trace Coverage");
+  stepButton.enableDefault();
+  setMousePointer(IPointerHandle());
+}
+
+void FileTraceWindow::reload() {
+  ok_ptr(this);
+  canvas.fileView.reductionTable.reset();
+  canvas.fileView.reload();
+  canvas.fileView.refresh();
+  resetParser();
+}
+
+void FileTraceWindow::showHelp() {
+  ok_ptr(this);
+  AgHelpWindow::showHelp("File Trace");
+  helpButton.disableDefault();
+  helpButton.unhighlight();
+  stepButton.enableDefault();
+  canvas.focusControl = FileTraceWindow::fileTab;
+}
+
+
+
+void FileTraceWindow::resetParser() {
+  ok_ptr(this);
+  FtParser &parser = canvas.fileView.parser;
+  if (parser.ruleToReduce) {
+    parser.ruleToReduce = 0;
+    canvas.reductionMenu->des->d_size.y = 0;
+    canvas.bottomPanel.setSplitWindowPercentage(&canvas.reductionChoiceView,0);
+    canvas.bottomPanel.setSplitWindowPercentage(&canvas.ruleView, 100);
+    canvas.bottomPanel.refresh();
+  }
+  parser.reset();
+  onResynch();
+  setLocationField(canvas.fileView.parser.displayLocation());
+  LOGV(parser.state.number) LCV(parser.state.token);
+  //parser.displayControl->des->d_size.y = parser.stateStack.size() + 1;
+  canvas.parserDc->des->d_size.y = parser.stateStack.size() + 1;
+  canvas.refreshRules(0);
+  synchRules(parser.stateStack.size(), parser.state.token);
+  statusField.setText(FtParser::processStateText[parser.processState]);
+  canvas.stackView.reset().setCursorLine(0).refresh();
+  canvas.fileView.turnHighlightOff();
+  canvas.fileView.setCursorLocation(cint(0,0));
+  canvas.fileView.refresh();
+  canvas.fileView.dataArea.setFocus();
+  canvas.focusControl = canvas.activePanel = fileTab;
+  tabControl[choiceTab].enabled = 0;
+  stepButton.unhighlight();
+  stepButton.enableDefault();
+}
+
+Boolean FileTraceWindow::findNext(AgString s) {
+  LOGSECTION("FileTraceWindow::findNext");
+  ok_ptr(this);
+  LOGV(canvas.focusControl);
+  int flag = 0;
+
+  switch (canvas.focusControl) {
+    case 0: {
+      flag = canvas.stackView.findNext(s);
+      if (flag) {
+	stackSelect();
+      }
+      return flag;
+    }
+    case 1: {
+      flag = canvas.fileView.findNext(s);
+      return flag;
+    }
+    case 2: {
+      flag = canvas.reductionChoiceView.findNext(s);
+      if (flag) {
+	tokenSelect();
+      }
+      return flag;
+    }
+    case 3: {
+      flag = canvas.ruleView.findNext(s);
+      if (flag) {
+	ruleSelect();
+      }
+      return flag;
+    }
+  }
+
+  return flag;
+}
+
+Boolean FileTraceWindow::findPrev(AgString s) {
+  LOGSECTION("FileTraceWindow::findPrev");
+  ok_ptr(this);
+  LOGV(canvas.focusControl);
+  int flag = 0;
+
+  switch (canvas.focusControl) {
+    case 0: {
+      flag = canvas.stackView.findPrev(s);
+      if (flag) {
+	stackSelect();
+      }
+      return flag;
+    }
+    case 1:
+      return canvas.fileView.findPrev(s);
+    case 2: {
+      flag = canvas.reductionChoiceView.findPrev(s);
+      if (flag) {
+	tokenSelect();
+      }
+      return flag;
+    }
+    case 3: {
+      flag = canvas.ruleView.findPrev(s);
+      if (flag) {
+	ruleSelect();
+      }
+      return flag;
+    }
+  }
+  return flag;
+}
+
+
+void FileTraceWindow::doStep() {
+  LOGSECTION("FileTraceWindow::doStep");
+  ok_ptr(this);
+  FtParser &parser = canvas.fileView.parser;
+  LOGV(parser.processState);
+  canvas.focusControl = canvas.activePanel = fileTab;
+  if (parser.processState == FtParser::selectionRequired &&
+      parser.location() == canvas.fileView.cursorLocation) {
+    reductionChoiceEnter();
+  }
+  else {
+    canvas.fileView.step();
+  }
+  setLocationField(parser.displayLocation());
+  statusField.setText(FtParser::processStateText[parser.processState]);
+  stepButton.unhighlight();
+  stepButton.enableDefault();
+  setFocus();
+  LOGV(parser.processState);
+}
+
+void FileTraceWindow::parseFile() {
+  LOGSECTION("FileTraceWindow::parseFile");
+  ok_ptr(this);
+  FtParser &parser = canvas.fileView.parser;
+  LOGV(parser.processState);
+  if (parser.processState == FtParser::selectionRequired) {
+    reductionChoiceEnter();
+  }
+  if (parser.processState > FtParser::running) {
+    messageBeep();
+    canvas.focusControl = canvas.activePanel = fileTab;
+    parseButton.disableDefault();
+    parseButton.unhighlight();
+    setFocus();
+    return;
+  }
+  while (parser.processState <= FtParser::running) {
+    canvas.fileView.parse();
+    if (parser.processState != FtParser::selectionRequired) {
+      continue;
+    }
+    int fileIndex = (char *) parser.state.pointer - parser.text.pointer();
+    int tn = canvas.fileView.reductionTable[fileIndex];
+    LOGV(fileIndex) LCV(tn);
+    if (tn == 0) {
+      continue;
+    }
+    parser.completeReduction(tn);
+  }
+  setLocationField(parser.displayLocation());
+  statusField.setText(FtParser::processStateText[parser.processState]);
+  LOGV(parser.processState);
+  parseButton.unhighlight();
+  parseButton.disableDefault();
+}