view anagram/vaclgui/frame.cpp @ 15:f5acaf0c8a29

Don't cast through "volatile int". Causes a gcc warning nowadays. XXX: should put something else back here to frighten the optimizer
author David A. Holland
date Tue, 31 May 2022 01:00:55 -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;
}