home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 035 / pmics.zip / wpmics.cc < prev    next >
C/C++ Source or Header  |  1994-12-13  |  21KB  |  617 lines

  1. /*
  2.     PMICS -- PM interface for playing chess on internet chess server
  3.     Copyright (C) 1994  Kevin Nomura
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     Author can be reached at email: chow@netcom.com
  20. */
  21. #include <stdio.h>
  22. #include <icolor.hpp>
  23. #include <icmdhdr.hpp>
  24. #include <istring.hpp>
  25. #include <irect.hpp>
  26. #include <ifont.hpp>
  27. #include <ihelp.hpp>
  28. #include <imsgbox.hpp>
  29. //#include <igroupbx.hpp>
  30. #include "pmics.hh"
  31. #include "wpmics.hh"
  32. #include "wboard.hh"
  33. #include "wcomm.hh"
  34. #include "session.hh"
  35. #define INCL_WIN
  36. #define INCL_WINTIMER
  37. #include <os2.h>
  38.  
  39. IHelpWindow *helpWindow;
  40. IWindowHandle hMain;
  41. ASession *aSession;
  42. extern int intOption(IString s);
  43. extern int getIntOption(IString s, int def);
  44. extern IString stringOption(IString s);
  45.  
  46. /***************************************************************************
  47.  *   Pushbutton labels and actions are table driven.  (Currently the
  48.  *   table is statically defined, but we could make it user-customizable
  49.  *   by doing the work to externalize it -- load from file, or put in rc).
  50.  *   The actions can include substitution strings for data tracked by
  51.  *   the stat window, as follows:
  52.  *      %g    game number of the present game
  53.  ***************************************************************************/
  54. typedef struct {
  55.   char label[16];
  56.   char action[100];
  57.   unsigned char flags;
  58. } ButtonInfo;
  59. #define BUTTONINFO_FL_RED 1
  60. ButtonInfo buttonInfo[NUM_PUSHBUTTONS] = {
  61.   {"refresh", "refresh",      0},
  62.   {"flag",    "flag",         0},
  63.   {"resign",  "resign",       BUTTONINFO_FL_RED},
  64.   {"draw",    "draw",         0},
  65.   {"who abr", "who abr",      0},
  66.   {"games",   "games",        0},
  67.   {"al",      "allobservers", 0},
  68.   {"moves",   "moves %g",     0},
  69.   {"messages","messages",     0},
  70.   {"open",    "open",         0},
  71.   {"history", "history",      0}};
  72.  
  73. /**************************************************************************
  74.  * FUNCTION:    constructor (class PmicsWindow)
  75.  *
  76.  * DESCRIPTION: Build main window.  Divides main window into areas
  77.  *   for board, stat and comm subwindows.  Initializes stat window
  78.  *   (integral to PmicsWindow class) and invokes BoardWindow ctr.
  79.  *               
  80.  **************************************************************************/
  81. PmicsWindow :: PmicsWindow(unsigned long windowId)
  82.   : IFrameWindow (                      //Call the IFrameWindow constructor
  83.     IFrameWindow::defaultStyle()        //  using the default style, plus
  84.     | IFrameWindow::accelerator         //  accelerator key table plus
  85.     | IFrameWindow::minimizedIcon,      //  get minimized icon from RC file
  86.     windowId)                           //  and set the main window ID
  87. {
  88.   int odx, ody, idx, idy;    // outside/inside dim of frame window
  89.   int xsplit, ysplit; 
  90.   static IHelpWindow::Settings helpSettings;
  91.   static HelpCommandHandler   * helpHdr;
  92.  
  93.   IFUNCTRACE_DEVELOP();
  94.   hMain = handle();        // export for messaging
  95.  
  96.   /**************************************************************
  97.    * set pixel size of main window.  command line flags: -x -y     
  98.    **************************************************************/
  99.   odx = IWindow::desktopWindow()->size().coord1();
  100.   odx = getIntOption("x", odx>800 ? 800 : odx);
  101.   ody = getIntOption("y", IWindow::desktopWindow()->size().coord2());
  102.   moveSizeTo(IRectangle(0, 0, odx, ody));
  103.  
  104.   /**************************************************************
  105.    * divide window into 3 regions:
  106.    *     ---------------         
  107.    *     |        |    |
  108.    *     |        |    |
  109.    *     | board  |stat|
  110.    *     |        |    |
  111.    *     |-------------|
  112.    *     |             |
  113.    *     |    comm     |
  114.    *     ---------------
  115.    **************************************************************/
  116.   horzCanvas = new ISplitCanvas(WND_CANVAS, this, this); // main client
  117.   horzCanvas->setOrientation (ISplitCanvas::horizontalSplit);
  118.   setClient(horzCanvas);
  119.   ITRACE_DEVELOP("horzCanvas size after creation: " +
  120.          horzCanvas->size().asString());
  121.  
  122.   vertCanvas = new ISetCanvas(WND_CANVAS2, horzCanvas, horzCanvas);
  123.   vertCanvas->setDeckOrientation( ISetCanvas::horizontal )
  124.              .setMargin( ISize(0,0) )
  125.          .setColor( ISetCanvas::background, IColor(IColor::paleGray));
  126.  
  127.   boardWindow = new BoardWindow (WND_BOARD, vertCanvas);
  128.   setupStat(vertCanvas);
  129.  
  130.   commWindow = new CommWindow (WND_COMM, horzCanvas);
  131.  
  132.   /**************************************************************
  133.    * adjust the window proportions to fully display the board
  134.    **************************************************************/
  135.   ITRACE_DEVELOP("horzCanvas size after children created: " +
  136.          horzCanvas->size().asString());
  137.   idx = horzCanvas->size().width();
  138.   idy = horzCanvas->size().height();
  139. //  xsplit = vertCanvas->splitBarThickness(ISplitCanvas::splitBarEdge)*2 +
  140. //    vertCanvas->splitBarThickness(ISplitCanvas::splitBarMiddle);
  141.   ysplit = horzCanvas->splitBarThickness(ISplitCanvas::splitBarEdge)*2 +
  142.     horzCanvas->splitBarThickness(ISplitCanvas::splitBarMiddle);
  143. //  ITRACE_DEVELOP("splitbarthickness(edge) = " +
  144. //     IString(vertCanvas->splitBarThickness(ISplitCanvas::splitBarEdge)) +
  145. //         " splitbarthickness(middle) = " +
  146. //     IString(vertCanvas->splitBarThickness(ISplitCanvas::splitBarMiddle)));
  147. //  vertCanvas->setSplitWindowPercentage(boardWindow, boardWindow->pixelSize());
  148. //  vertCanvas->setSplitWindowPercentage(buttCanvas, 120);
  149. //  vertCanvas->setSplitWindowPercentage(statCanvas, (odx-8) - boardWindow->pixelSize() - 120 - xsplit*2);
  150.  
  151.   horzCanvas->setSplitWindowPercentage(vertCanvas, boardWindow->pixelSize());
  152.   horzCanvas->setSplitWindowPercentage(commWindow, (ody-56) - boardWindow->pixelSize() - ysplit*1);
  153. //  vertCanvas->refresh();
  154.   horzCanvas->refresh();
  155.  
  156.   /**************************************************************
  157.    * setup menubar
  158.    **************************************************************/
  159.   menuBar=new IMenuBar(WND_PMICS, this);    //Create the information area
  160.   menuBar->checkItem(MI_BOARD_LOCK);
  161.   menuBar->checkItem(MI_PROMOTION_Q);
  162.   ITrace::isTraceEnabled() ? menuBar->checkItem(MI_TRACE) :
  163.                              menuBar->uncheckItem(MI_TRACE);
  164.   if (getIntOption("autoflag", 0))
  165.     menuBar->checkItem(MI_AUTOFLAG);
  166.   if (stringOption("bs") == "del") {
  167.     menuBar->checkItem(MI_BS2DEL);
  168.     commWindow->bs2del = true;
  169.   }
  170.   else
  171.     commWindow->bs2del = false;
  172.   if (stringOption("cr") == "lf") {
  173.     menuBar->checkItem(MI_CR2LF);
  174.     commWindow->cr2lf = true;
  175.   }
  176.   else
  177.     commWindow->cr2lf = false;
  178.   if (intOption("localecho")) {
  179.     menuBar->checkItem(MI_LOCAL_ECHO);
  180.     commWindow->localecho = true;
  181.   }
  182.   else
  183.     commWindow->localecho = false;
  184.  
  185.   /**************************************************************
  186.    * setup help on the menubar
  187.    **************************************************************/
  188.   helpSettings
  189.     .setTitle("PMICS help")
  190.     .setLibraries("PMICS.HLP");
  191.   helpWindow = new IHelpWindow(helpSettings);
  192.   helpWindow->associateWindow(this);
  193.   helpHdr = new HelpCommandHandler;
  194.   helpHdr->handleEventsFor(this);
  195.  
  196.   /*********************************************************************
  197.    * handlers and timers
  198.    *********************************************************************/
  199.   handleEventsFor(this);
  200.   msgHandler = new PmicsMsgHandler(this);
  201.   msgHandler->handleEventsFor(this);
  202.   WinStartTimer((HAB)IThread::current().anchorBlock(),  // 1 second timer
  203.         (HWND)handle(),
  204.         1,
  205.         1000);    // tick every second
  206.  
  207.   commWindow->setFocus();   // Set focus to the main window
  208.   show();            // Show the main window
  209.  
  210.   ITRACE_DEVELOP("wpmics: window sizes");
  211.   ITRACE_DEVELOP("  pmicsWindow: " + size().asString());
  212.   ITRACE_DEVELOP("  boardWindow: " + boardWindow->size().asString());
  213.   ITRACE_DEVELOP("  horzCanvas: " + horzCanvas->size().asString());
  214.   ITRACE_DEVELOP("  vertCanvas: " + vertCanvas->size().asString());
  215.   ITRACE_DEVELOP("  statCanvas: " + statCanvas->size().asString());
  216.   ITRACE_DEVELOP("  buttCanvas: " + buttCanvas->size().asString());
  217.   ITRACE_DEVELOP("  commWindow: " + commWindow->size().asString());
  218. } /* end PmicsWindow :: PmicsWindow(...) */
  219.  
  220.  
  221. /**************************************************************************
  222.  * FUNCTION:    setupStat (class PmicsWindow)
  223.  *
  224.  * DESCRIPTION: Create stat window.  Has text controls for player names,
  225.  *   countdown clocks, game number and last move.  Has pushbuttons for
  226.  *   common ICS commands that don't require parameters (e.g. resign, flag).
  227.  *   MultiCellCanvas is used to arrange these items.
  228.  **************************************************************************/
  229. void PmicsWindow :: setupStat (IWindow *parent)
  230. {
  231.   IFUNCTRACE_DEVELOP();
  232.  
  233.   statCanvas = new IMultiCellCanvas(WND_STAT, parent, parent);
  234.  
  235.   buttCanvas = new ISetCanvas(WND_BUTT, parent, parent);
  236.   buttCanvas->setDeckOrientation( ISetCanvas::vertical )
  237.              .setPackType( ISetCanvas::expanded )
  238.              .setAlignment( ISetCanvas::topLeft )
  239.              .setPad(ISize(5,5));   // width,height
  240.  
  241.   for (int bnum = 0; bnum<NUM_PUSHBUTTONS; bnum++) {
  242.     pushButton[bnum] = new IPushButton(WND_BUTTON_BASE+bnum,
  243.                        buttCanvas, buttCanvas);
  244.     pushButton[bnum]->setText(buttonInfo[bnum].label);
  245.     pushButton[bnum]->disableMouseClickFocus();
  246.  
  247.     if (buttonInfo[bnum].flags & BUTTONINFO_FL_RED) {
  248.       pushButton[bnum]->setColor(IButton::border, IColor(IColor::red));
  249.       pushButton[bnum]->setColor(IButton::foreground, IColor(IColor::red));
  250.       pushButton[bnum]->setColor(IButton::disabledForeground, IColor(IColor::red));
  251.     }
  252.   }
  253.  
  254.   textWName  = new ISetCanvas(WND_WNAME, statCanvas, statCanvas);
  255.   textWName->setText("white");
  256.  
  257.   textWClock = new IStaticText(WND_WCLOCK, textWName, textWName);
  258.   textWClock->setFont(IFont("Helvetica",18));
  259.   textWClock->setLimit(5);    // allocate room for 5 chars
  260.   statWClock = 3600;
  261.  
  262.   textBName  = new ISetCanvas(WND_BNAME, statCanvas, statCanvas);
  263.   textBName->setText("black");
  264.  
  265.   textBClock = new IStaticText(WND_BCLOCK, textBName, textBName);
  266.   textBClock->setFont(IFont("Helvetica",18));
  267.   textBClock->setLimit(5);    // allocate room for 5 chars
  268.   statBClock = 3600;
  269.   tickClock = NULL;
  270.   updateClocks();
  271.  
  272.   textGameName  = new IStaticText(WND_GAME_NAME, statCanvas, statCanvas);
  273.   textGameName->setText("Game 0");
  274.  
  275.   textMove  = new IStaticText(WND_MOVE, statCanvas, statCanvas);
  276.   textMove->setText("o-o-o");
  277.  
  278.  
  279. /*  for (bnum=0; bnum<NUM_PUSHBUTTONS; bnum++) {
  280.     buttCanvas->addToCell(pushButton[bnum], 1,bnum+1);
  281.   }*/
  282.   statCanvas->addToCell(textWName,   2,2);
  283.   statCanvas->addToCell(textBName,   2,4);
  284.   statCanvas->addToCell(textGameName,2,6);
  285.   statCanvas->addToCell(textMove,    2,7);
  286.   statCanvas->setColumnWidth(1,10); // left margin
  287.   statCanvas->setRowHeight(1,10);   // top margin
  288. }
  289.  
  290.  
  291. void PmicsWindow::statWhiteTop()
  292. {
  293.   IFUNCTRACE_DEVELOP();
  294.   statCanvas->removeFromCell(textWName);
  295.   statCanvas->removeFromCell(textBName);
  296.  
  297.   statCanvas->addToCell(textWName,   2,2);
  298.   statCanvas->addToCell(textBName,   2,4);
  299.   statCanvas->refresh();
  300. }
  301.  
  302. void PmicsWindow::statWhiteBottom()
  303. {
  304.   IFUNCTRACE_DEVELOP();
  305.   statCanvas->removeFromCell(textWName);
  306.   statCanvas->removeFromCell(textBName);
  307.  
  308.   statCanvas->addToCell(textWName,   2,4);
  309.   statCanvas->addToCell(textBName,   2,2);
  310.   statCanvas->refresh();
  311. }
  312.  
  313. void PmicsWindow::updateStat(char *p_)
  314. {
  315.   struct statData {
  316.     char  onMove;
  317.     int   wClock, bClock, gameNum;
  318.     char  wName[32], bName[32], move[32];
  319.   } *p = (struct statData *)(p_);
  320.  
  321.   // in addition to displaying the chess clocks, save off the times in
  322.   // private data.  the timer tick continuously updates the clocks
  323.   // every second.
  324.   statWClock = p->wClock;
  325.   statBClock = p->bClock;
  326.   tickClock = NULL;
  327.   updateClocks();
  328.   tickClock = (p->onMove == 'W' ? &statWClock : &statBClock);
  329.  
  330.   if (textWName->text() != p->wName) 
  331.     textWName->setText(p->wName);
  332.   if (textBName->text() != p->bName) 
  333.     textBName->setText(p->bName);
  334.   if (textGameName->text() != "Game " + IString(p->gameNum))
  335.     textGameName->setText("Game " + IString(p->gameNum));
  336.   gameNum = p->gameNum;        // save off for Moves button
  337.   textMove->setText(p->move);
  338. }
  339.  
  340. void PmicsWindow::updateClocks()
  341. {
  342.   char  wTextClock[20], bTextClock[20];
  343.   if (tickClock != NULL) {
  344.     (*tickClock) --;
  345.  
  346.     if (onMove == -1 &&        // opponent's move
  347.     (*tickClock == 0 || *tickClock == -1) &&
  348.     menuBar->isItemChecked(MI_AUTOFLAG)) {
  349.       aSession->write("flag\n");
  350.     }
  351.   }
  352.  
  353.   sprintf(wTextClock, "%d:%02d ", statWClock/60, statWClock % 60);
  354.   sprintf(bTextClock, "%d:%02d ", statBClock/60, statBClock % 60);
  355.   textWClock->setText(wTextClock);
  356.   textBClock->setText(bTextClock);
  357. }
  358.  
  359. void PmicsWindow::statWhiteOnMove(unsigned int whoseMove)
  360. {
  361.   IColor  color = (whoseMove==1)? IColor::red : IColor::green;
  362.   onMove = whoseMove;
  363.   textWClock->setColor(IStaticText::background, color);
  364. /*  textBName->setColor(IStaticText::background, 
  365.               statCanvas->color(ISetCanvas::background));*/
  366.   textBClock->setColor(IStaticText::background, statCanvas->color());
  367. }
  368.  
  369. void PmicsWindow::statBlackOnMove(unsigned int whoseMove)
  370. {
  371.   IColor  color = (whoseMove==1) ? IColor::red : IColor::green;
  372.   onMove = whoseMove;
  373.   textBClock->setColor(IStaticText::background, color);
  374.   /*textWName->setColor(IStaticText::background, 
  375.               statCanvas->color(ISetCanvas::background));*/
  376.   textWClock->setColor(IStaticText::background, statCanvas->color());
  377. }
  378.  
  379.  
  380. /**************************************************************************
  381.  * FUNCTION:    dispatchHandlerEvent (class PmicsMsgHandler)
  382.  *
  383.  * DESCRIPTION: IEvent (window message) handler for PmicsWindow.
  384.  **************************************************************************/
  385. Boolean PmicsMsgHandler::dispatchHandlerEvent(IEvent &evt)
  386. {
  387.   static Boolean whiteAtTop = false;
  388.   PmicsWindow    *pmicsWindow = (PmicsWindow *)evt.window();
  389.  
  390.   switch (evt.eventId()) {
  391.   case MSG_STAT_UPDATE:
  392.     {
  393.       char *p;
  394.       ITRACE_DEVELOP("MSG_STAT_UPDATE received");
  395.       p = (char *)IEventData(evt.parameter1());
  396.       pmicsWindow->updateStat(p);
  397.       free((void *)p);
  398.       break;
  399.     }
  400.   case MSG_STAT_WHITE_AT_TOP:
  401.     ITRACE_DEVELOP("MSG_STAT_WHITE_AT_TOP received");
  402.     pmicsWindow->statWhiteTop();
  403.     whiteAtTop = true;
  404.     break;
  405.   case MSG_STAT_WHITE_AT_BOTTOM:
  406.     ITRACE_DEVELOP("MSG_STAT_WHITE_AT_BOTTOM received");
  407.     pmicsWindow->statWhiteBottom();
  408.     whiteAtTop = false;
  409.     break;
  410.   case MSG_STAT_WHITE_AT_OTHER:
  411.     ITRACE_DEVELOP("MSG_STAT_WHITE_AT_OTHER received");
  412.     if (whiteAtTop = 1 - whiteAtTop)
  413.       pmicsWindow->statWhiteTop();
  414.     else
  415.       pmicsWindow->statWhiteBottom();
  416.     break;
  417.   case MSG_STAT_WHITE_ONMOVE:
  418.     pmicsWindow->statWhiteOnMove(IEventData(evt.parameter1()));
  419.     break;
  420.   case MSG_STAT_BLACK_ONMOVE:
  421.     pmicsWindow->statBlackOnMove(IEventData(evt.parameter1()));
  422.     break;
  423.   case WM_TIMER:
  424.     pmicsWindow->updateClocks();
  425.     pmicsWindow->commWindow->timerTick();
  426.     break;
  427.   default:
  428.     return false;
  429.   }
  430.   return true;
  431. }
  432.  
  433.  
  434. IString PmicsWindow :: expandButtonAction(IString in)
  435. {
  436.   IString out;
  437.   int     inLen = in.size();
  438.   for (int i=1; i<=inLen; i++) {
  439.     if (in[i] != '%' || i == inLen)
  440.       out += in[i];
  441.     else {
  442.       i++;
  443.       switch (in[i]) {
  444.       case 'g':
  445.     out += gameNum;
  446.     break;
  447.       default:
  448.     out += "%";
  449.     break;
  450.       }
  451.     }
  452.   }
  453.   return out;
  454. }
  455.  
  456. /**************************************************************************
  457.  * FUNCTION:    command (class PmicsWindow)
  458.  *
  459.  * DESCRIPTION: ICommandEvent (menu bar) handler for PmicsWindow.
  460.  **************************************************************************/
  461.  
  462. Boolean PmicsWindow :: command(ICommandEvent &cmdEvent)
  463. {
  464.   IResourceLibrary   reslib;
  465.  
  466.   IFUNCTRACE_DEVELOP();
  467.   switch (cmdEvent.commandId()) {
  468.   case MI_QUIT:
  469.     postEvent(WM_CLOSE);
  470.     break;
  471.   case MI_FLIP:
  472.     hBoard.postEvent(MSG_BOARD_FLIP);
  473.     break;
  474.   case MI_BOARD_LOCK:
  475.     if (menuBar->isItemChecked(MI_BOARD_LOCK))
  476.       menuBar->uncheckItem(MI_BOARD_LOCK);
  477.     else
  478.       menuBar->checkItem(MI_BOARD_LOCK);
  479.     break;
  480.   case MI_BOARD_REPLOT:
  481.     hBoard.postEvent(MSG_BOARD_REPLOT);
  482.     break;
  483.   case MI_NEWBOARD:
  484.     AGame::current()->initialize();
  485.     hBoard.postEvent(MSG_BOARD_WHITE_AT_BOTTOM);
  486.     break;
  487.   case MI_FONT:
  488.     hComm.postEvent(MSG_COM_FONT);
  489.     break;
  490.   case MI_TRACE:
  491.     ITrace::isTraceEnabled() ? ITrace::disableTrace() : ITrace::enableTrace();
  492.     ITrace::isTraceEnabled() ? menuBar->checkItem(MI_TRACE) :
  493.                                menuBar->uncheckItem(MI_TRACE);
  494.     break;
  495.   case MI_AUTOFLAG:
  496.     if (menuBar->isItemChecked(MI_AUTOFLAG)) {
  497.       menuBar->uncheckItem(MI_AUTOFLAG);
  498.     }
  499.     else {
  500.       menuBar->checkItem(MI_AUTOFLAG);
  501.     }
  502.     break;
  503.   case MI_LOCAL_ECHO:
  504.     if (menuBar->isItemChecked(MI_LOCAL_ECHO)) {
  505.       menuBar->uncheckItem(MI_LOCAL_ECHO);
  506.       commWindow->localecho = false;
  507.     }
  508.     else {
  509.       menuBar->checkItem(MI_LOCAL_ECHO);
  510.       commWindow->localecho = true;
  511.     }
  512.     break;
  513.   case MI_BS2DEL:
  514.     if (menuBar->isItemChecked(MI_BS2DEL)) {
  515.       menuBar->uncheckItem(MI_BS2DEL);
  516.       commWindow->bs2del = false;
  517.     }
  518.     else {
  519.       menuBar->checkItem(MI_BS2DEL);
  520.       commWindow->bs2del = true;
  521.     }
  522.     break;
  523.   case MI_CR2LF:
  524.     if (menuBar->isItemChecked(MI_CR2LF)) {
  525.       menuBar->uncheckItem(MI_CR2LF);
  526.       commWindow->cr2lf = false;
  527.     }
  528.     else {
  529.       menuBar->checkItem(MI_CR2LF);
  530.       commWindow->cr2lf = true;
  531.     }
  532.     break;
  533.   case MI_PROMOTION_Q:
  534.     hBoard.postEvent(MI_PROMOTION_Q);
  535.     menuBar->checkItem(MI_PROMOTION_Q);
  536.     menuBar->uncheckItem(MI_PROMOTION_R);
  537.     menuBar->uncheckItem(MI_PROMOTION_B);
  538.     menuBar->uncheckItem(MI_PROMOTION_N);
  539.     break;
  540.   case MI_PROMOTION_R:
  541.     hBoard.postEvent(MI_PROMOTION_R);
  542.     menuBar->checkItem(MI_PROMOTION_R);
  543.     menuBar->uncheckItem(MI_PROMOTION_Q);
  544.     menuBar->uncheckItem(MI_PROMOTION_B);
  545.     menuBar->uncheckItem(MI_PROMOTION_N);
  546.     break;
  547.   case MI_PROMOTION_B:
  548.     hBoard.postEvent(MI_PROMOTION_B);
  549.     menuBar->checkItem(MI_PROMOTION_B);
  550.     menuBar->uncheckItem(MI_PROMOTION_Q);
  551.     menuBar->uncheckItem(MI_PROMOTION_R);
  552.     menuBar->uncheckItem(MI_PROMOTION_N);
  553.     break;
  554.   case MI_PROMOTION_N:
  555.     hBoard.postEvent(MI_PROMOTION_N);
  556.     menuBar->checkItem(MI_PROMOTION_N);
  557.     menuBar->uncheckItem(MI_PROMOTION_Q);
  558.     menuBar->uncheckItem(MI_PROMOTION_R);
  559.     menuBar->uncheckItem(MI_PROMOTION_B);
  560.     break;
  561.  
  562.   default:
  563.     if (cmdEvent.commandId() < WND_BUTTON_BASE ||
  564.     cmdEvent.commandId() >= WND_BUTTON_BASE+11)
  565.       return false;
  566.     aSession->write(expandButtonAction(buttonInfo[cmdEvent.commandId() - WND_BUTTON_BASE].action) + "\n");
  567.   }
  568.   return true;
  569. }
  570.  
  571.  
  572. /**************************************************************************
  573.  * FUNCTION:    command (class HelpCommandHandler)
  574.  *
  575.  * DESCRIPTION: Process help menu-bar selections
  576.  **************************************************************************/
  577.  
  578. Boolean HelpCommandHandler :: command(ICommandEvent &evt)
  579. {
  580.   IFUNCTRACE_DEVELOP();
  581.   switch (evt.commandId()) {
  582.   case MI_PRODUCTINFO:
  583.     {
  584.       IMessageBox mb(evt.window());
  585.       mb.setTitle("Product Information")
  586.     .show(
  587.     "PMICS, a graphical ICS client for OS/2 PM\n"
  588.     "Copyright (C) 1994  Kevin Nomura\n"
  589.     "\n"
  590.     "This program is free software; you can redistribute it and/or modify "
  591.     "it under the terms of the GNU General Public License as published by "
  592.     "the Free Software Foundation; either version 2 of the License, or "
  593.     "(at your option) any later version."
  594.     "This program is distributed in the hope that it will be useful,\n"
  595.     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  596.     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  597.     "GNU General Public License for more details.\n"
  598.     "Author can be reached at email: chow@netcom.com\n",
  599.           IMessageBox::informationIcon |
  600.           IMessageBox::okButton);
  601.       return true;
  602.     }
  603.   case MI_HELPINDEX:
  604.     {
  605.       helpWindow->show(IHelpWindow::index);
  606.       return true;
  607.     }
  608.   case MI_HELPINDEX2:
  609.     {
  610.       IHelpWindow *help = IHelpWindow::helpWindow(evt.window());
  611.       help->show(IHelpWindow::index);
  612.       return true;
  613.     }
  614.   }
  615.   return false;
  616. }
  617.