view anagram/vaclgui/frame.cpp @ 21:1c9dac05d040

Add lint-style FALLTHROUGH annotations to fallthrough cases. (in the parse engine and thus the output code) Document this, because the old output causes warnings with gcc10.
author David A. Holland
date Mon, 13 Jun 2022 00:04:38 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * AnaGram, A System for Syntax Directed Programming
 * Copyright 1997-2002 Parsifal Software. All Rights Reserved.
 * See the file COPYING for license and usage terms.
 *
 * frame.cpp
 */

#include <imnitem.hpp>
#include <ipopmenu.hpp>
#include <windows.h>

#include "action.h"
#include "agstring.h"
#include "ctrlpanel.hpp"
#include "frame.hpp"
#include "helpview.hpp"
#include "myalloc.h"
#include "vaclgui-res.h"
#include "vaclgui.hpp"

//#define INCLUDE_LOGGING
#include "log.h"


int AgFrame::activeWindowCount = 0;
AgFrame *AgFrame::activeWindow = 0;
IPopUpMenu *AgFrame::activePopUpMenu = 0;

IWindow *AgFrame::frameParent  = 0;
IWindow *AgFrame::frameOwner   = 0;
AgArray<AgMenuItem> AgFrame::activeAuxMenu;
int AgFrame::menuShowingFlag   = 0;


Boolean AgHelpHandler::showHelp(IEvent &event) {
  LOGSECTION("AgHelpHandler::showHelp");
  return false;
}

Boolean HelpDemon::showHelp(IEvent &event) {
  AgHelpWindow::showHelp(topic);
  return true;
}

Boolean HelpDemon::mouseClicked(IMouseClickEvent &event) {
  LOGSECTION("HelpDemon::mouseClicked");
  LOGV(event.mouseButton()) LCV(event.mouseAction());
  LOGV(ControlPanel::helpCursorSet);
  if (ControlPanel::helpCursorSet) {
    if (event.mouseButton() == IMouseClickEvent::button2) {
      return false;
    }
    if (event.mouseAction() == IMouseClickEvent::down) {
      AgHelpWindow::showHelp(topic);
      ControlPanel::helpCursorSet = 0;
      ControlPanel::resetCursor();
    }
    return true;
  }
  return false;
}

HelpDemon::HelpDemon(IWindow *w, AgString t)
  : window(w)
  , topic(t)
{
  AgHelpHandler::handleEventsFor(window);
  IMouseHandler::handleEventsFor(window);
}

HelpDemon::~HelpDemon() {
  //if (!topic.exists()) return;
  LOGSECTION("HelpDemon::~HelpDemon");
  LOGV((int) &window);
  AgHelpHandler::stopHandlingEventsFor(window);
  LOGS("Help handler released") LCV((int) &window);
  IMouseHandler::stopHandlingEventsFor(window);
  LOGS("Mouse handler released");
}

void HelpDemon::setTopic(AgString t) {
  //AgString oldTopic = topic;
  topic = t;
  //if (oldTopic.exists()) return;
  //AgHelpHandler::handleEventsFor(window);
  //IMouseHandler::handleEventsFor(window);
}


class ActivateKluge {
private:
  AgFrame *window;

  void pingWindow() {
    LOGSECTION("ActivateKluge::pingWindow");
    LOGV((int) window) LCV(window->id());
    window->setFocus();
    delete this;
  }
  void pingActionWindow() {
    LOGSECTION("ActivateKluge::pingActionWindow");
    LOGV((int) window) LCV(window->id());
    pActionWindow->setFocus();
    defer(this, pingWindow);
  }
  void pingControlPanel() {
    LOGSECTION("ActivateKluge::pingControlPanel");
    LOGV((int) window) LCV(window->id());
    controlPanel->setFocus();
    defer(this, pingActionWindow);
  }

public:
  ActivateKluge(AgFrame *w) : window(w) {
    LOGSECTION("ActivateKluge::ActivateKluge");
    LOGV((int) window) LCV(window->id());
    defer(this, pingControlPanel);
  }
  ~ActivateKluge() {}
};

class FocusKluge {
  AgFrame *window;

  void pingWindow() {
    LOGSECTION("FocusKluge::pingWindow");
    LOGV((int) window) LCV(window->id());
    window->setFocus();
    delete this;
  }

public:
  FocusKluge(AgFrame *w) : window(w) {
    LOGSECTION("FocusKluge::FocusKluge");
    LOGV((int) window) LCV(window->id());
    defer(this, pingWindow);
  }
  ~FocusKluge() {}
};

Boolean AgFrameHandler::activated(IFrameEvent &event) {
  LOGSECTION_OFF("AgFrameHandler::activated");
  //int protectHelp = ControlPanel::helpCursorSet;
  //ControlPanel::helpCursorSet = 0;
  AgFrame *window = (AgFrame *) event.controlWindow();
  window->activeFlag = 1;
  LOGV(AgFrame::menuShowingFlag) LCV(ControlPanel::helpCursorSet);
  int windowId = window->id();
  LOGV(windowId) LCV((int) window);
  LOGV((int) controlPanel) LCV((int) pActionWindow);
  AgFrame::activeWindowCount++;
  AgFrame::windowRegistry.markActive(windowId);
  AgFrame::activeWindow = (AgFrame *) window;
  IWindowHandle previous = (void *) event.parameter2();
  IWindow *previousWindow = IWindow::windowWithHandle(previous);
  if (previousWindow == 0 && controlPanel != 0) {
    new ActivateKluge(window);
  }
  else if (previousWindow != pActionWindow) {
    window->setFocus();
  }
  LOGV((int) window);
  LOGV((int) event.parameter2().asLong()) LCV((int) previousWindow);
  //ControlPanel::helpCursorSet = protectHelp;

  return true;
}

Boolean AgFrameHandler::deactivated(IFrameEvent &event) {
  LOGSECTION_OFF("AgFrameHandler::deactivated");
  AgFrame *window = (AgFrame *) event.controlWindow();
  window->activeFlag = 0;
#ifdef INCLUDE_LOGGING
  int windowId = window->id();
  LOGV(windowId) LCV((int) window);
#endif
  AgFrame::activeWindowCount--;
  LOGV(AgFrame::activeWindowCount);
  if (AgFrame::activeWindow == window) {
    AgFrame::activeWindow = 0;
  }
  //onDeactivate();
  return false;
}


Boolean AgFrameHandler::dispatchHandlerEvent(IEvent &event) {
  //LOGSECTION("AgFrameHandler::dispatchHandlerEvent", Log::off);
  LOGSECTION_OFF("AgFrameHandler::dispatchHandlerEvent");
  LOGV(event.eventId());
  LOGV((int) event.controlWindow()) LCV(event.controlWindow()->id());
  ok_ptr(this);
  if (event.eventId()==WM_WINDOWPOSCHANGED || event.eventId()==WM_KILLFOCUS) {
    if (controlPanel) {
      controlPanel->makeTopmost();
    }
  }
  return IFrameHandler::dispatchHandlerEvent(event);
}

Boolean AgUserHandler::dispatchHandlerEvent(IEvent &event) {
  //LOGSECTION("AgUserHandler::dispatchHandlerEvent", Log::off);
  LOGSECTION_OFF("AgUserHandler::dispatchHandlerEvent");
  LOGV(event.eventId());
  LOGV((int) event.controlWindow()) LCV(event.controlWindow()->id());
  if (event.eventId() == WM_USER) {
    AgAction::Kernel *kernel = 
      (AgAction::Kernel *) (void *) event.parameter1().asLong();
    kernel->perform();
    if (kernel->unlock()) {
      delete kernel;
      kernel = 0;
    }
    event.setResult(true);
    return true;
  }
  return false;
}

Boolean AgHelpHandler::dispatchHandlerEvent(IEvent &event) {
  //LOGSECTION("AgHelpHandler", Log::off);
  LOGSECTION_OFF("AgHelpHandler");
  LOGV(event.eventId());
  if (event.eventId() == WM_HELP || event.eventId() == IC_ID_HELP) {
    LOGSECTION("WM_HELP message");
    if (!showHelp(event)) {
      return false;
    }
    event.setResult(true);
    return true;
  }
  return false;
}

/*
Boolean AgFrame::mousePointerChange(IMousePointerEvent &event) {
  LOGSECTION("AgFrame::mousePointerChange");
  if (ControlPanel::helpCursorSet && helpCursorSupported) {
    event.setMousePointer(ControlPanel::helpCursor);
  }
  else {
    event.setMousePointer(ControlPanel::activeCursor);
  }
  LOGS("Pointer changed");
  return true;
}
*/

void AgFrame::showHelpTopic() {
  LOGSECTION("AgFrame::showHelpTopic");
  if (AgFrame::menuShowingFlag) {
    defer(this, showHelpTopic);
    return;
  }
  AgHelpWindow::showHelp(helpTopic);
}

Boolean AgFrame::showHelp(IEvent &event) {
  AgString topic;

  LOGSECTION("AgFrame::showHelp");
  // look for active pop up menu
  LOGV((int) AgFrame::activePopUpMenu);
  LOGV(AgFrame::activeAuxMenu.exists());
  if (AgFrame::activePopUpMenu && AgFrame::activeAuxMenu.exists()) {
    int n = AgFrame::activePopUpMenu->numberOfItems();
    for (int i = 0; i++ < n;) {
      IMenuItem item = AgFrame::activePopUpMenu->menuItem(i);
      if (item.isHighlighted()) {
        topic = AgFrame::activeAuxMenu[i-1].text;
        break;
      }
    }
  }
  if (!topic.exists() && AgFrame::activeWindow) {
    topic = AgFrame::windowRegistry.getTitle(AgFrame::activeWindow->id());
  }
  if (!topic.exists()) {
    topic = "Using Help";
  }
  LOGV(topic) LCV(topic.size());
  //LOGV(simple_file_name) LCV(simple_file_name.size());
  helpTopic = topic;
  defer(this, showHelpTopic);
  event.setResult(true);
  return true;
}

WindowRegistry AgFrame::windowRegistry;

AgFrame::AgFrame()
  : IFrameWindow(nextChildId(), frameParent, frameOwner, IRectangle(),
		   titleBar
		 | systemMenu
		 | minimizeButton
		 | sizingBorder
		 | noMoveWithOwner)
  , windowTitle(this, "AnaGram")
  , syntaxDependent(0)
  , activeFlag(1)
  , helpCursorSupported(0)
  , accelerator(IDW_FRAME_WINDOW, this)
  , modalDialog(0)
  , closeAction(actionObject(this, closeFrame))
{
  LOGSECTION("AgFrame::AgFrame()");
  windowId = id();
  //useExtensionMinimumSize(&windowTitle);
  LOGV(windowId) LCV((int) this);
  setIcon(IDI_ICON);
  frameHandler = new AgFrameHandler;
  IFrameWindow::removeDefaultHandler();
  frameHandler->handleEventsFor(this);
  ICommandHandler::handleEventsFor(this);
  IResizeHandler::handleEventsFor(this);
  LOGS("command handler attached");
  AgHelpHandler::handleEventsFor(this);
  userHandler = new AgUserHandler;
  userHandler->handleEventsFor(this);
  IKeyboardHandler::handleEventsFor(this);
  //IMousePointerHandler::handleEventsFor(this);
  activeWindow = this;
}

AgFrame::AgFrame(Style s)
  : IFrameWindow(nextChildId(), frameParent, frameOwner, IRectangle(),
		 s | titleBar | minimizeButton | noMoveWithOwner)
  , windowTitle(this, "AnaGram")
  , syntaxDependent(0)
  , activeFlag(1)
  , helpCursorSupported(0)
  , accelerator(IDW_FRAME_WINDOW, this)
  , modalDialog(0)
  , closeAction(actionObject(this, closeFrame))
{
  LOGSECTION("AgFrame::AgFrame(Style)");
  windowId = id();
  //useExtensionMinimumSize(&windowTitle);
  LOGV(windowId) LCV((int) this);
  setIcon(IDI_ICON);
  LOGV("Icon set");
  frameHandler = new AgFrameHandler;
  LOGS("frameHandler built");
  IFrameWindow::removeDefaultHandler();
  LOGS("Old frame handler removed");
  frameHandler->handleEventsFor(this);
  LOGS("New frame handler atteched");
  ICommandHandler::handleEventsFor(this);
  LOGS("Command handler attached");
  IResizeHandler::handleEventsFor(this);
  LOGS("resize handler attached");
  AgHelpHandler::handleEventsFor(this);
  LOGS("help handler attached");
  userHandler = new AgUserHandler;
  LOGS("user handler created");
  userHandler->handleEventsFor(this);
  LOGS("user handler attached");
  IKeyboardHandler::handleEventsFor(this);
  LOGS("keyboard handler attached");
  //IMousePointerHandler::handleEventsFor(this);
  activeWindow = this;
}

AgFrame::AgFrame(int id_)
  : IFrameWindow(id_, frameParent, frameOwner, IRectangle(),
		   titleBar
		 | systemMenu
		 | minimizeButton
		 | maximizeButton
		 | sizingBorder
		 | noMoveWithOwner)
  , windowTitle(this, "AnaGram")
  , syntaxDependent(0)
  , activeFlag(1)
  , helpCursorSupported(0)
  , accelerator(IDW_FRAME_WINDOW, this)
  , modalDialog(0)
  , closeAction(actionObject(this, closeFrame))
{
  LOGSECTION("AgFrame::AgFrame(int id)");
  windowId = id();
  //useExtensionMinimumSize(&windowTitle);
  LOGV(windowId) LCV((int) this);
  setIcon(IDI_ICON);
  frameHandler = new AgFrameHandler;
  IFrameWindow::removeDefaultHandler();
  frameHandler->handleEventsFor(this);
  ICommandHandler::handleEventsFor(this);
  IResizeHandler::handleEventsFor(this);
  LOGS("command handler attached");
  AgHelpHandler::handleEventsFor(this);
  userHandler = new AgUserHandler;
  userHandler->handleEventsFor(this);
  IKeyboardHandler::handleEventsFor(this);
  //IMousePointerHandler::handleEventsFor(this);
  activeWindow = this;
}

AgFrame::~AgFrame() {
  LOGSECTION("AgFrame::~AgFrame");
  LOGV(windowId) LCV((int) this);
  IPoint cascadeRestore = cascadeOffset - cascadeIncrement;
  if (cascadeRestore == initialPosition) {
    cascadeOffset = cascadeRestore;
  }
  ICommandHandler::stopHandlingEventsFor(this);
  LOGS("command handler detached");
  AgHelpHandler::stopHandlingEventsFor(this);
  LOGS("help handler detached");
  userHandler->stopHandlingEventsFor(this);
  LOGS("user handler detached");
  frameHandler->stopHandlingEventsFor(this);
  LOGS("frame handler detached");
  delete frameHandler;
  LOGS("frame handler deleted");
  delete userHandler;
  LOGS("user handler deleted");

  IResizeHandler::stopHandlingEventsFor(this);
  LOGS("resize handler detached");
  IKeyboardHandler::stopHandlingEventsFor(this);
  //IMousePointerHandler::stopHandlingEventsFor(this);
  LOGS("~AgFrame completed");
}

void AgFrame::closeFrame() {
  LOGSECTION("AgFrame::closeFrame");
  LOGV(windowId) LCV((int) this);
  if (modalDialog) {
    closeAction.performDeferred();
    return;
  }
  close();
}

AgFrame &AgFrame::close() {
  LOGSECTION("AgFrame::close");
  LOGV(id()) LCV(syntaxFileId);
  IFrameWindow::close();
  return *this;
}

Boolean AgFrame::characterKeyPress(IKeyboardEvent &event) {
  LOGSECTION("AgFrame::characterKeyPress");
  if (event.isCtrlDown())  {
    return false;
  }
  if (event.isShiftDown()) {
    return false;
  }
  if (!event.isAltDown())  {
    return false;
  }
  //IMenuBar &menu = controlPanel->menuBar;
  switch (event.character()) {
/*
    case 'a':
      controlPanel->selectMenuItem(IDM_FILE);
      return true;
    case 'b':
      controlPanel->selectMenuItem(IDM_BROWSE);
      return true;
    case 'o':
      controlPanel->selectMenuItem(IDM_OPTIONS);
      return true;
    case 'w':
      controlPanel->selectMenuItem(IDM_WINDOWS);
      return true;
    case 'h':
      controlPanel->selectMenuItem(IDM_HELP);
      return true;
*/
    default:
      return false;
  }
}

Boolean AgFrame::virtualKeyPress(IKeyboardEvent &event) {
  LOGSECTION("AgFrame::virtualKeyPress");
  LOGV((int) event.virtualKey());
  LOGV(event.isShiftDown()) LCV(event.isCtrlDown()) LCV(event.isAltDown());
  switch (event.virtualKey()) {
    case IKeyboardEvent::esc: {
      //IWindow *waiting = controlPanel;
      AgFrame::windowRegistry.remove(id());
      close();
      return true;
    }
    case IKeyboardEvent::f10: {
      if (event.isShiftDown()) {
	return true;
      }
      if (event.isCtrlDown() || event.isAltDown()) {
	return false;
      }
      if (controlPanel) {
	controlPanel->setFocus();
      }
      return false;
    }
    case IKeyboardEvent::f3: {
      if (event.isShiftDown() || event.isCtrlDown() || event.isAltDown()) {
	return false;
      }
      if (controlPanel) {
	controlPanel->findNext();
      }
      return true;
    }
    case IKeyboardEvent::f4: {
      if (event.isShiftDown() || event.isCtrlDown() || event.isAltDown()) {
	return false;
      }
      if (controlPanel) {
	controlPanel->findPrev();
      }
      return true;
    }
    case IKeyboardEvent::f8: {
      if (event.isShiftDown() || event.isCtrlDown() || event.isAltDown()) {
	return false;
      }
      if (controlPanel) {
	controlPanel->setFocus();
      }
      return true;
    }
  }
  return false;
}

void AgFrame::popUp() {
  if (modalDialog) {
    modalDialog->show().setFocus();
    return;
  }
  if (isMinimized()) {
    restore();
  }
  show().setFocus();
}

AgFrame &AgFrame::show(Boolean showWindow) {
  IFrameWindow::show(showWindow);
  return *this;
}

AgFrame &AgFrame::setFocus() {
  IFrameWindow::setFocus();
  return *this;
}

AgFrame &AgFrame::mySetFocus() {
  LOGSECTION("AgFrame::mySetFocus");
  LOGV((int) modalDialog);
  IHandle h = handle();
  if (modalDialog) {
    modalDialog->setFocus();
    h = modalDialog->handle();
  }
  else {
    setFocus();
  }
  //BringWindowToTop(h);
  return *this;
}

AgFrame &AgFrame::positionFrame() {
  LOGSECTION("AgFrame::positionFrame");
  LOGV(size());
  if (!(size() + cascadeOffset <= desktopWindow()->size())) {
    cascadeOffset = cascadeOrigin;
  }

  LOGV(cascadeOffset);
  moveTo(cascadeOffset);
  initialPosition = cascadeOffset;
  cascadeOffset += cascadeIncrement;
  return *this;
}

Boolean AgFrame::windowResize(IResizeEvent &event) {
  LOGSECTION("AgFrame::windowResize");
  LOGV(windowId) LCV((int) this);
  LOGV(event.newSize().asString());
  LOGV(minimumSize().asString());
  return false;
}

void AgFrame::registerTitle(AgString name) {
  LOGSECTION("Register title");
  LOGV(windowId) LCV((int) this) LCV(name);
  windowRegistry.registerId(this, name, actionObject(this, popUp));
  LOGS("registration complete");
}

Boolean AgFrame::command(ICommandEvent &event) {
  LOGSECTION("AgFrame::command");
  if (messageBoxShowing) {
    messageBeep();
    return true;
  }
  switch(event.commandId()) {
    case IDM_EDIT_FIND:
      if (controlPanel) {
	controlPanel->searchKeyBox.setFocus();
      }
      break;
    case IDM_EDIT_FINDNEXT: {
      LOGSECTION("AgFrame::FINDNEXT");
      if (controlPanel) {
	controlPanel->findNext();
      }
      break;
    }
    case IDM_EDIT_FINDPREV:
      LOGSECTION("AgFrame::FINDPREV");
      if (controlPanel) {
	controlPanel->findPrev();
      }
      break;
  }
  return true;
}

Boolean AgFrame::systemCommand(ICommandEvent &event) {
  LOGSECTION("AgFrame::systemCommand");
  int commandId = event.commandId() & 0xfff0;
  LOGV(commandId);
  if (messageBoxShowing) {
    messageBeep();
    return true;
  }
  if (commandId == ISystemMenu::idClose) {
    LOGSECTION("AgFrame::systemCommand::idClose");
    LOGV(windowId) LCV((int) this);

    LOGV((int)event.dispatchingWindow());
    LOGV((int)event.controlWindow());
    LOGV((int)this);
    if (event.dispatchingWindow() != this) {
      return false;
    }

    AgFrame *window = windowRegistry.find(windowId);
    if (window && window->modalDialog) {
      window->modalDialog->close();
    }
    //IWindow *waiting = controlPanel;
    windowRegistry.remove(windowId);
/*
    int n = AgFrame::windowRegistry.size();
    if (n) {
      waiting = AgFrame::windowRegistry[n-1].window;
    }
    waiting->setFocus();
*/
    closeAction.performDeferred();
    LOGS("finished");
    //return false;
    return true;
  }
  else if (commandId == ISystemMenu::idMinimize) {
    LOGSECTION("AgFrame::systemCommand::idMinimize");
    hide();
    return true;
  }
  return false;
}

AgDialog::AgDialog(IWindow *owner)
  : IFrameWindow(nextChildId(), AgFrame::frameParent, owner, IRectangle(),
		   titleBar
		 | systemMenu
		 | dialogBorder
		 | dialogBackground
		 | noMoveWithOwner
		 | synchPaint)
  , windowTitle(this, "AnaGram")
{
  LOGSECTION("AgDialog::AgDialog");
  windowId = id();
  LOGV(windowId);
  setIcon(IDI_ICON);
  ICommandHandler::handleEventsFor(this);
  IResizeHandler::handleEventsFor(this);
  AgHelpHandler::handleEventsFor(this);
}

AgDialog::~AgDialog() {
  LOGSECTION("AgDialog::~AgDialog");
  LOGV(windowId);
  ICommandHandler::stopHandlingEventsFor(this);
  IResizeHandler::stopHandlingEventsFor(this);
  AgHelpHandler::stopHandlingEventsFor(this);
}

Boolean AgDialog::showHelp(IEvent &event) {
  AgString topic;

  LOGSECTION("AgDialog::showHelp");
  topic = AgFrame::windowRegistry.getTitle(AgFrame::activeWindow->id());
  if (!topic.exists()) {
    topic = "Using Help";
  }
  AgString title;
  if (topic.exists()) {
    title = topic.firstCut(' ').leftX();
    LOGV(topic.pointer());
    LOGV(title.pointer());
    if (!title.exists()) {
      title = topic;
    }
    if (title == "Help") {
      topic = "Using Help";
    }
    title = AgString::format("Help - %s", topic.pointer());
  }
  LOGV(topic.pointer());
  IFrameWindow *helpWindow = AgFrame::windowRegistry.find(title);
  LOGV((int) helpWindow);
  if (helpWindow == 0) {
    helpWindow = new AgHelpWindow(topic);
    helpWindow->setAutoDeleteObject();
  }
  helpWindow->setFocus();
  event.setResult(true);
  return true;
}

Boolean AgDialog::systemCommand(ICommandEvent &event) {
  LOGSECTION("AgDialog::systemCommand");
  int commandId = event.commandId() & 0xfff0;
  if (commandId == ISystemMenu::idClose) {
    LOGSECTION("AgDialog::systemCommand::idClose");
    LOGV(windowId);

    LOGV((int)event.dispatchingWindow());
    LOGV((int)event.controlWindow());
    LOGV((int)this);
    if (event.dispatchingWindow() != this) {
      return false;
    }

    //IWindow *waiting = controlPanel;
    AgFrame::windowRegistry.remove(windowId);
/*
    int n = AgFrame::windowRegistry.size();
    if (n) {
      waiting = AgFrame::windowRegistry[n-1].window;
    }
    waiting->setFocus();
*/
    LOGS("finished");
    return false;
  }
  else if (commandId == ISystemMenu::idMinimize) {
    LOGSECTION("AgDialog::systemCommand::idMinimize");
    hide();
    return true;
  }
  return false;
}