home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spiele Shareware / os2games.iso / os2games / addons / pmics / src / wpmics.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-17  |  21.5 KB  |  631 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.   int boardSize;
  128.   // first set default, then apply explicit size if specified
  129.   boardSize = (ody >= 768 ? 2 : 1);
  130.   boardSize = intOption("big") ? 3 : intOption("medium") ? 2 : 
  131.               intOption("small") ? 1 : boardSize;
  132.   boardWindow = new BoardWindow (WND_BOARD, vertCanvas, boardSize);
  133.   setupStat(vertCanvas);
  134.  
  135.   commWindow = new CommWindow (WND_COMM, horzCanvas);
  136.  
  137.   /**************************************************************
  138.    * adjust the window proportions to fully display the board
  139.    **************************************************************/
  140.   ITRACE_DEVELOP("horzCanvas size after children created: " +
  141.          horzCanvas->size().asString());
  142.   idx = horzCanvas->size().width();
  143.   idy = horzCanvas->size().height();
  144. //  xsplit = vertCanvas->splitBarThickness(ISplitCanvas::splitBarEdge)*2 +
  145. //    vertCanvas->splitBarThickness(ISplitCanvas::splitBarMiddle);
  146.   ysplit = horzCanvas->splitBarThickness(ISplitCanvas::splitBarEdge)*2 +
  147.     horzCanvas->splitBarThickness(ISplitCanvas::splitBarMiddle);
  148. //  ITRACE_DEVELOP("splitbarthickness(edge) = " +
  149. //     IString(vertCanvas->splitBarThickness(ISplitCanvas::splitBarEdge)) +
  150. //         " splitbarthickness(middle) = " +
  151. //     IString(vertCanvas->splitBarThickness(ISplitCanvas::splitBarMiddle)));
  152. //  vertCanvas->setSplitWindowPercentage(boardWindow, boardWindow->pixelSize());
  153. //  vertCanvas->setSplitWindowPercentage(buttCanvas, 120);
  154. //  vertCanvas->setSplitWindowPercentage(statCanvas, (odx-8) - boardWindow->pixelSize() - 120 - xsplit*2);
  155.  
  156.   horzCanvas->setSplitWindowPercentage(vertCanvas, boardWindow->pixelSize());
  157.   horzCanvas->setSplitWindowPercentage(commWindow, (ody-56) - boardWindow->pixelSize() - ysplit*1);
  158. //  vertCanvas->refresh();
  159.   horzCanvas->refresh();
  160.  
  161.   /**************************************************************
  162.    * setup menubar
  163.    **************************************************************/
  164.   menuBar=new IMenuBar(WND_PMICS, this);    //Create the information area
  165.   menuBar->checkItem(MI_BOARD_LOCK);
  166.   menuBar->checkItem(MI_PROMOTION_Q);
  167.   ITrace::isTraceEnabled() ? menuBar->checkItem(MI_TRACE) :
  168.                              menuBar->uncheckItem(MI_TRACE);
  169.   if (getIntOption("autoflag", 0))
  170.     menuBar->checkItem(MI_AUTOFLAG);
  171.   if (stringOption("bs") == "del") {
  172.     menuBar->checkItem(MI_BS2DEL);
  173.     commWindow->bs2del = true;
  174.   }
  175.   else
  176.     commWindow->bs2del = false;
  177.   if (stringOption("cr") == "lf") {
  178.     menuBar->checkItem(MI_CR2LF);
  179.     commWindow->cr2lf = true;
  180.   }
  181.   else
  182.     commWindow->cr2lf = false;
  183.   if (intOption("localecho")) {
  184.     menuBar->checkItem(MI_LOCAL_ECHO);
  185.     commWindow->localecho = true;
  186.   }
  187.   else
  188.     commWindow->localecho = false;
  189.  
  190.   /**************************************************************
  191.    * setup help on the menubar
  192.    **************************************************************/
  193.   helpSettings
  194.     .setTitle("PMICS help")
  195.     .setLibraries("PMICS.HLP");
  196.   helpWindow = new IHelpWindow(helpSettings);
  197.   helpWindow->associateWindow(this);
  198.   helpHdr = new HelpCommandHandler;
  199.   helpHdr->handleEventsFor(this);
  200.  
  201.   /*********************************************************************
  202.    * handlers and timers
  203.    *********************************************************************/
  204.   handleEventsFor(this);
  205.   msgHandler = new PmicsMsgHandler(this);
  206.   msgHandler->handleEventsFor(this);
  207.   WinStartTimer((HAB)IThread::current().anchorBlock(),  // 1 second timer
  208.         (HWND)handle(),
  209.         1,
  210.         1000);    // tick every second
  211.  
  212.   commWindow->setFocus();   // Set focus to the main window
  213.   show();            // Show the main window
  214.  
  215.   ITRACE_DEVELOP("wpmics: window sizes");
  216.   ITRACE_DEVELOP("  pmicsWindow: " + size().asString());
  217.   ITRACE_DEVELOP("  boardWindow: " + boardWindow->size().asString());
  218.   ITRACE_DEVELOP("  horzCanvas: " + horzCanvas->size().asString());
  219.   ITRACE_DEVELOP("  vertCanvas: " + vertCanvas->size().asString());
  220.   ITRACE_DEVELOP("  statCanvas: " + statCanvas->size().asString());
  221.   ITRACE_DEVELOP("  buttCanvas: " + buttCanvas->size().asString());
  222.   ITRACE_DEVELOP("  commWindow: " + commWindow->size().asString());
  223. } /* end PmicsWindow :: PmicsWindow(...) */
  224.  
  225.  
  226. /**************************************************************************
  227.  * FUNCTION:    setupStat (class PmicsWindow)
  228.  *
  229.  * DESCRIPTION: Create stat window.  Has text controls for player names,
  230.  *   countdown clocks, game number and last move.  Has pushbuttons for
  231.  *   common ICS commands that don't require parameters (e.g. resign, flag).
  232.  *   MultiCellCanvas is used to arrange these items.
  233.  **************************************************************************/
  234. void PmicsWindow :: setupStat (IWindow *parent)
  235. {
  236.   int numPushbuttons;
  237.  
  238.   IFUNCTRACE_DEVELOP();
  239.  
  240.   /* kludge: reduce the number of pushbuttons for -small geometry */
  241.   /* so the button column is smaller than the board window.  */
  242.   /* otherwise the comm window is forced to shrink. */
  243.   numPushbuttons = (boardWindow->pixelSize() > 320 ? 
  244.             NUM_PUSHBUTTONS : 8);
  245.  
  246.   statCanvas = new IMultiCellCanvas(WND_STAT, parent, parent);
  247.  
  248.   buttCanvas = new ISetCanvas(WND_BUTT, parent, parent);
  249.   buttCanvas->setDeckOrientation( ISetCanvas::vertical )
  250.              .setPackType( ISetCanvas::expanded )
  251.              .setAlignment( ISetCanvas::topLeft )
  252.              .setPad(ISize(5,5));   // width,height
  253.  
  254.   for (int bnum = 0; bnum<numPushbuttons; bnum++) {
  255.     pushButton[bnum] = new IPushButton(WND_BUTTON_BASE+bnum,
  256.                        buttCanvas, buttCanvas);
  257.     pushButton[bnum]->setText(buttonInfo[bnum].label);
  258.     pushButton[bnum]->disableMouseClickFocus();
  259.  
  260.     if (buttonInfo[bnum].flags & BUTTONINFO_FL_RED) {
  261.       pushButton[bnum]->setColor(IButton::border, IColor(IColor::red));
  262.       pushButton[bnum]->setColor(IButton::foreground, IColor(IColor::red));
  263.       pushButton[bnum]->setColor(IButton::disabledForeground, IColor(IColor::red));
  264.     }
  265.   }
  266.  
  267.   textWName  = new ISetCanvas(WND_WNAME, statCanvas, statCanvas);
  268.   textWName->setText("white");
  269.  
  270.   textWClock = new IStaticText(WND_WCLOCK, textWName, textWName);
  271.   textWClock->setFont(IFont("Helvetica",18));
  272.   textWClock->setLimit(5);    // allocate room for 5 chars
  273.   statWClock = 3600;
  274.  
  275.   textBName  = new ISetCanvas(WND_BNAME, statCanvas, statCanvas);
  276.   textBName->setText("black");
  277.  
  278.   textBClock = new IStaticText(WND_BCLOCK, textBName, textBName);
  279.   textBClock->setFont(IFont("Helvetica",18));
  280.   textBClock->setLimit(5);    // allocate room for 5 chars
  281.   statBClock = 3600;
  282.   tickClock = NULL;
  283.   updateClocks();
  284.  
  285.   textGameName  = new IStaticText(WND_GAME_NAME, statCanvas, statCanvas);
  286.   textGameName->setText("Game 0");
  287.  
  288.   textMove  = new IStaticText(WND_MOVE, statCanvas, statCanvas);
  289.   textMove->setText("o-o-o");
  290.  
  291.  
  292. /*  for (bnum=0; bnum<numPushbuttons; bnum++) {
  293.     buttCanvas->addToCell(pushButton[bnum], 1,bnum+1);
  294.   }*/
  295.   statCanvas->addToCell(textWName,   2,2);
  296.   statCanvas->addToCell(textBName,   2,4);
  297.   statCanvas->addToCell(textGameName,2,6);
  298.   statCanvas->addToCell(textMove,    2,7);
  299.   statCanvas->setColumnWidth(1,10); // left margin
  300.   statCanvas->setRowHeight(1,10);   // top margin
  301. }
  302.  
  303.  
  304. void PmicsWindow::statWhiteTop()
  305. {
  306.   IFUNCTRACE_DEVELOP();
  307.   statCanvas->removeFromCell(textWName);
  308.   statCanvas->removeFromCell(textBName);
  309.  
  310.   statCanvas->addToCell(textWName,   2,2);
  311.   statCanvas->addToCell(textBName,   2,4);
  312.   statCanvas->refresh();
  313. }
  314.  
  315. void PmicsWindow::statWhiteBottom()
  316. {
  317.   IFUNCTRACE_DEVELOP();
  318.   statCanvas->removeFromCell(textWName);
  319.   statCanvas->removeFromCell(textBName);
  320.  
  321.   statCanvas->addToCell(textWName,   2,4);
  322.   statCanvas->addToCell(textBName,   2,2);
  323.   statCanvas->refresh();
  324. }
  325.  
  326. void PmicsWindow::updateStat(char *p_)
  327. {
  328.   struct statData {
  329.     char  onMove;
  330.     int   wClock, bClock, gameNum;
  331.     char  wName[32], bName[32], move[32];
  332.   } *p = (struct statData *)(p_);
  333.  
  334.   // in addition to displaying the chess clocks, save off the times in
  335.   // private data.  the timer tick continuously updates the clocks
  336.   // every second.
  337.   statWClock = p->wClock;
  338.   statBClock = p->bClock;
  339.   tickClock = NULL;
  340.   updateClocks();
  341.   tickClock = (p->onMove == 'W' ? &statWClock : &statBClock);
  342.  
  343.   if (textWName->text() != p->wName) 
  344.     textWName->setText(p->wName);
  345.   if (textBName->text() != p->bName) 
  346.     textBName->setText(p->bName);
  347.   if (textGameName->text() != "Game " + IString(p->gameNum))
  348.     textGameName->setText("Game " + IString(p->gameNum));
  349.   gameNum = p->gameNum;        // save off for Moves button
  350.   textMove->setText(p->move);
  351. }
  352.  
  353. void PmicsWindow::updateClocks()
  354. {
  355.   char  wTextClock[20], bTextClock[20];
  356.   if (tickClock != NULL) {
  357.     (*tickClock) --;
  358.  
  359.     if (onMove == -1 &&        // opponent's move
  360.     (*tickClock == 0 || *tickClock == -1) &&
  361.     menuBar->isItemChecked(MI_AUTOFLAG)) {
  362.       aSession->write("flag");
  363.       aSession->write(IString(commWindow->crChar()));
  364.     }
  365.   }
  366.  
  367.   sprintf(wTextClock, "%d:%02d ", statWClock/60, statWClock % 60);
  368.   sprintf(bTextClock, "%d:%02d ", statBClock/60, statBClock % 60);
  369.   textWClock->setText(wTextClock);
  370.   textBClock->setText(bTextClock);
  371. }
  372.  
  373. void PmicsWindow::statWhiteOnMove(unsigned int whoseMove)
  374. {
  375.   IColor  color = (whoseMove==1)? IColor::red : IColor::green;
  376.   onMove = whoseMove;
  377.   textWClock->setColor(IStaticText::background, color);
  378. /*  textBName->setColor(IStaticText::background, 
  379.               statCanvas->color(ISetCanvas::background));*/
  380.   textBClock->setColor(IStaticText::background, statCanvas->color());
  381. }
  382.  
  383. void PmicsWindow::statBlackOnMove(unsigned int whoseMove)
  384. {
  385.   IColor  color = (whoseMove==1) ? IColor::red : IColor::green;
  386.   onMove = whoseMove;
  387.   textBClock->setColor(IStaticText::background, color);
  388.   /*textWName->setColor(IStaticText::background, 
  389.               statCanvas->color(ISetCanvas::background));*/
  390.   textWClock->setColor(IStaticText::background, statCanvas->color());
  391. }
  392.  
  393.  
  394. /**************************************************************************
  395.  * FUNCTION:    dispatchHandlerEvent (class PmicsMsgHandler)
  396.  *
  397.  * DESCRIPTION: IEvent (window message) handler for PmicsWindow.
  398.  **************************************************************************/
  399. Boolean PmicsMsgHandler::dispatchHandlerEvent(IEvent &evt)
  400. {
  401.   static Boolean whiteAtTop = false;
  402.   PmicsWindow    *pmicsWindow = (PmicsWindow *)evt.window();
  403.  
  404.   switch (evt.eventId()) {
  405.   case MSG_STAT_UPDATE:
  406.     {
  407.       char *p;
  408.       ITRACE_DEVELOP("MSG_STAT_UPDATE received");
  409.       p = (char *)IEventData(evt.parameter1());
  410.       pmicsWindow->updateStat(p);
  411.       free((void *)p);
  412.       break;
  413.     }
  414.   case MSG_STAT_WHITE_AT_TOP:
  415.     ITRACE_DEVELOP("MSG_STAT_WHITE_AT_TOP received");
  416.     pmicsWindow->statWhiteTop();
  417.     whiteAtTop = true;
  418.     break;
  419.   case MSG_STAT_WHITE_AT_BOTTOM:
  420.     ITRACE_DEVELOP("MSG_STAT_WHITE_AT_BOTTOM received");
  421.     pmicsWindow->statWhiteBottom();
  422.     whiteAtTop = false;
  423.     break;
  424.   case MSG_STAT_WHITE_AT_OTHER:
  425.     ITRACE_DEVELOP("MSG_STAT_WHITE_AT_OTHER received");
  426.     if (whiteAtTop = 1 - whiteAtTop)
  427.       pmicsWindow->statWhiteTop();
  428.     else
  429.       pmicsWindow->statWhiteBottom();
  430.     break;
  431.   case MSG_STAT_WHITE_ONMOVE:
  432.     pmicsWindow->statWhiteOnMove(IEventData(evt.parameter1()));
  433.     break;
  434.   case MSG_STAT_BLACK_ONMOVE:
  435.     pmicsWindow->statBlackOnMove(IEventData(evt.parameter1()));
  436.     break;
  437.   case WM_TIMER:
  438.     pmicsWindow->updateClocks();
  439.     pmicsWindow->commWindow->timerTick();
  440.     break;
  441.   default:
  442.     return false;
  443.   }
  444.   return true;
  445. }
  446.  
  447.  
  448. IString PmicsWindow :: expandButtonAction(IString in)
  449. {
  450.   IString out;
  451.   int     inLen = in.size();
  452.   for (int i=1; i<=inLen; i++) {
  453.     if (in[i] != '%' || i == inLen)
  454.       out += in[i];
  455.     else {
  456.       i++;
  457.       switch (in[i]) {
  458.       case 'g':
  459.     out += gameNum;
  460.     break;
  461.       default:
  462.     out += "%";
  463.     break;
  464.       }
  465.     }
  466.   }
  467.   return out;
  468. }
  469.  
  470. /**************************************************************************
  471.  * FUNCTION:    command (class PmicsWindow)
  472.  *
  473.  * DESCRIPTION: ICommandEvent (menu bar) handler for PmicsWindow.
  474.  **************************************************************************/
  475.  
  476. Boolean PmicsWindow :: command(ICommandEvent &cmdEvent)
  477. {
  478.   IResourceLibrary   reslib;
  479.  
  480.   IFUNCTRACE_DEVELOP();
  481.   switch (cmdEvent.commandId()) {
  482.   case MI_QUIT:
  483.     postEvent(WM_CLOSE);
  484.     break;
  485.   case MI_FLIP:
  486.     hBoard.postEvent(MSG_BOARD_FLIP);
  487.     break;
  488.   case MI_BOARD_LOCK:
  489.     if (menuBar->isItemChecked(MI_BOARD_LOCK))
  490.       menuBar->uncheckItem(MI_BOARD_LOCK);
  491.     else
  492.       menuBar->checkItem(MI_BOARD_LOCK);
  493.     break;
  494.   case MI_BOARD_REPLOT:
  495.     hBoard.postEvent(MSG_BOARD_REPLOT);
  496.     break;
  497.   case MI_NEWBOARD:
  498.     AGame::current()->initialize();
  499.     hBoard.postEvent(MSG_BOARD_WHITE_AT_BOTTOM);
  500.     break;
  501.   case MI_FONT:
  502.     hComm.postEvent(MSG_COM_FONT);
  503.     break;
  504.   case MI_TRACE:
  505.     ITrace::isTraceEnabled() ? ITrace::disableTrace() : ITrace::enableTrace();
  506.     ITrace::isTraceEnabled() ? menuBar->checkItem(MI_TRACE) :
  507.                                menuBar->uncheckItem(MI_TRACE);
  508.     break;
  509.   case MI_AUTOFLAG:
  510.     if (menuBar->isItemChecked(MI_AUTOFLAG)) {
  511.       menuBar->uncheckItem(MI_AUTOFLAG);
  512.     }
  513.     else {
  514.       menuBar->checkItem(MI_AUTOFLAG);
  515.     }
  516.     break;
  517.   case MI_LOCAL_ECHO:
  518.     if (menuBar->isItemChecked(MI_LOCAL_ECHO)) {
  519.       menuBar->uncheckItem(MI_LOCAL_ECHO);
  520.       commWindow->localecho = false;
  521.     }
  522.     else {
  523.       menuBar->checkItem(MI_LOCAL_ECHO);
  524.       commWindow->localecho = true;
  525.     }
  526.     break;
  527.   case MI_BS2DEL:
  528.     if (menuBar->isItemChecked(MI_BS2DEL)) {
  529.       menuBar->uncheckItem(MI_BS2DEL);
  530.       commWindow->bs2del = false;
  531.     }
  532.     else {
  533.       menuBar->checkItem(MI_BS2DEL);
  534.       commWindow->bs2del = true;
  535.     }
  536.     break;
  537.   case MI_CR2LF:
  538.     if (menuBar->isItemChecked(MI_CR2LF)) {
  539.       menuBar->uncheckItem(MI_CR2LF);
  540.       commWindow->cr2lf = false;
  541.     }
  542.     else {
  543.       menuBar->checkItem(MI_CR2LF);
  544.       commWindow->cr2lf = true;
  545.     }
  546.     break;
  547.   case MI_PROMOTION_Q:
  548.     hBoard.postEvent(MI_PROMOTION_Q);
  549.     menuBar->checkItem(MI_PROMOTION_Q);
  550.     menuBar->uncheckItem(MI_PROMOTION_R);
  551.     menuBar->uncheckItem(MI_PROMOTION_B);
  552.     menuBar->uncheckItem(MI_PROMOTION_N);
  553.     break;
  554.   case MI_PROMOTION_R:
  555.     hBoard.postEvent(MI_PROMOTION_R);
  556.     menuBar->checkItem(MI_PROMOTION_R);
  557.     menuBar->uncheckItem(MI_PROMOTION_Q);
  558.     menuBar->uncheckItem(MI_PROMOTION_B);
  559.     menuBar->uncheckItem(MI_PROMOTION_N);
  560.     break;
  561.   case MI_PROMOTION_B:
  562.     hBoard.postEvent(MI_PROMOTION_B);
  563.     menuBar->checkItem(MI_PROMOTION_B);
  564.     menuBar->uncheckItem(MI_PROMOTION_Q);
  565.     menuBar->uncheckItem(MI_PROMOTION_R);
  566.     menuBar->uncheckItem(MI_PROMOTION_N);
  567.     break;
  568.   case MI_PROMOTION_N:
  569.     hBoard.postEvent(MI_PROMOTION_N);
  570.     menuBar->checkItem(MI_PROMOTION_N);
  571.     menuBar->uncheckItem(MI_PROMOTION_Q);
  572.     menuBar->uncheckItem(MI_PROMOTION_R);
  573.     menuBar->uncheckItem(MI_PROMOTION_B);
  574.     break;
  575.  
  576.   default:
  577.     if (cmdEvent.commandId() < WND_BUTTON_BASE ||
  578.     cmdEvent.commandId() >= WND_BUTTON_BASE+11)
  579.       return false;
  580.     aSession->write(expandButtonAction(buttonInfo[cmdEvent.commandId() - WND_BUTTON_BASE].action) + IString(commWindow->crChar()));
  581.   }
  582.   return true;
  583. }
  584.  
  585.  
  586. /**************************************************************************
  587.  * FUNCTION:    command (class HelpCommandHandler)
  588.  *
  589.  * DESCRIPTION: Process help menu-bar selections
  590.  **************************************************************************/
  591.  
  592. Boolean HelpCommandHandler :: command(ICommandEvent &evt)
  593. {
  594.   IFUNCTRACE_DEVELOP();
  595.   switch (evt.commandId()) {
  596.   case MI_PRODUCTINFO:
  597.     {
  598.       IMessageBox mb(evt.window());
  599.       mb.setTitle("Product Information")
  600.     .show(
  601.     "PMICS, a graphical ICS client for OS/2 PM\n"
  602.     "Copyright (C) 1994  Kevin Nomura\n"
  603.     "\n"
  604.     "This program is free software; you can redistribute it and/or modify "
  605.     "it under the terms of the GNU General Public License as published by "
  606.     "the Free Software Foundation; either version 2 of the License, or "
  607.     "(at your option) any later version."
  608.     "This program is distributed in the hope that it will be useful,\n"
  609.     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  610.     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  611.     "GNU General Public License for more details.\n"
  612.     "Author can be reached at email: chow@netcom.com\n",
  613.           IMessageBox::informationIcon |
  614.           IMessageBox::okButton);
  615.       return true;
  616.     }
  617.   case MI_HELPINDEX:
  618.     {
  619.       helpWindow->show(IHelpWindow::index);
  620.       return true;
  621.     }
  622.   case MI_HELPINDEX2:
  623.     {
  624.       IHelpWindow *help = IHelpWindow::helpWindow(evt.window());
  625.       help->show(IHelpWindow::index);
  626.       return true;
  627.     }
  628.   }
  629.   return false;
  630. }
  631.