added a chat window to keep track of multiple conversations
authorH.G. Muller <h.g.muller@hccnet.nl>
Sun, 27 Sep 2009 17:24:47 +0000 (10:24 -0700)
committerArun Persaud <arun@nubati.net>
Wed, 30 Sep 2009 05:17:49 +0000 (22:17 -0700)
The chat-window patch affects:
winboard.c, backend.c, winboard.rc, resource.h, backend.h, and adds
the file winboard/wchat.c, which also affects makefile.gcc and makefile.ms.

In addition I added a new option -keepAlive, which affects
common.h (in addition to winboard.c and backend.c).

As I had to modify backend.h, I also defined the -reset option type there,
which we are going to add later. This required some changes
to suppress warnings in wsettings.c.

backend.c
backend.h
common.h
winboard/makefile.gcc
winboard/makefile.ms
winboard/resource.h
winboard/wchat.c [new file with mode: 0644]
winboard/winboard.c
winboard/winboard.rc
winboard/wsettings.c

index 2f839b9..94d0e81 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -242,6 +242,9 @@ VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */
 int lastIndex = 0;      /* [HGM] autoinc: last game/position used in match mode */
 int opponentKibitzes;
 int lastSavedGame; /* [HGM] save: ID of game */
+char chatPartner[MAX_CHAT][MSG_SIZ]; /* [HGM] chat: list of chatting partners */
+extern int chatCount;
+int chattingPartner;
 
 /* States for ics_getting_history */
 #define H_FALSE 0
@@ -1452,6 +1455,13 @@ read_from_player(isr, closure, message, count, error)
 }
 
 void
+KeepAlive()
+{   // [HGM] alive: periodically send dummy (date) command to ICS to prevent time-out
+    SendToICS("date\n");
+    if(appData.keepAlive) ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000);
+}
+
+void
 SendToICS(s)
      char *s;
 {
@@ -2082,6 +2092,7 @@ read_from_ics(isr, closure, data, count, error)
     int tkind;
     int backup;    /* [DM] For zippy color lines */
     char *p;
+    char talker[MSG_SIZ]; // [HGM] chat
 
     if (appData.debugMode) {
       if (!error) {
@@ -2262,6 +2273,12 @@ read_from_ics(isr, closure, data, count, error)
                parse[parse_pos++] = buf[i];
                if (buf[i] == '\n') {
                    parse[parse_pos] = NULLCHAR;
+                   if(chattingPartner>=0) {
+                       char mess[MSG_SIZ];
+                       sprintf(mess, "%s%s", talker, parse);
+                       OutputChatMessage(chattingPartner, mess);
+                       chattingPartner = -1;
+                   } else
                    if(!suppressKibitz) // [HGM] kibitz
                        AppendComment(forwardMostMove, StripHighlight(parse));
                    else { // [HGM kibitz: divert memorized engine kibitz to engine-output window
@@ -2398,6 +2415,32 @@ read_from_ics(isr, closure, data, count, error)
                }
            } // [HGM] kibitz: end of patch
 
+//if(appData.debugMode) fprintf(debugFP, "hunt for tell, buf = %s\n", buf+i);
+
+           // [HGM] chat: intercept tells by users for which we have an open chat window
+           if(started == STARTED_NONE && (looking_at(buf, &i, "* tells you:") || looking_at(buf, &i, "* says:") || 
+                                          looking_at(buf, &i, "* whispers:"))) {
+               int p;
+               sscanf(star_match[0], "%[^(]", talker+1); // strip (C) or (U) off ICS handle
+               chattingPartner = -1;
+               if(buf[i-3] == 'r') // whisper; look if there is a WHISPER chatbox
+               for(p=0; p<MAX_CHAT; p++) if(!strcmp("WHISPER", chatPartner[p])) {
+                   talker[0] = '['; strcat(talker, "]");
+                   chattingPartner = p; break;
+               }
+               if(chattingPartner<0) // if not, look if there is a chatbox for this indivdual
+               for(p=0; p<MAX_CHAT; p++) if(!strcasecmp(talker+1, chatPartner[p])) {
+                   talker[0] = 0;
+                   chattingPartner = p; break;
+               }
+               if(chattingPartner<0) i = oldi; else {
+                   started = STARTED_COMMENT;
+                   parse_pos = 0; parse[0] = NULLCHAR;
+                   savingComment = TRUE;
+                   suppressKibitz = TRUE;
+               }
+           } // [HGM] chat: end of patch
+
            if (appData.zippyTalk || appData.zippyPlay) {
                 /* [DM] Backup address for color zippy lines */
                 backup = i;
@@ -4087,6 +4130,8 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY)
        break;
     }
     SendToICS(user_move);
+    if(appData.keepAlive) // [HGM] alive: schedule sending of dummy 'date' command
+       ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000);
 }
 
 void
@@ -5647,7 +5692,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
          if(appData.autoKibitz && !appData.icsEngineAnalyze ) { /* [HGM] kibitz: send most-recent PV info to ICS */
                char buf[3*MSG_SIZ];
 
-               sprintf(buf, "kibitz !!! %+.2f/%d (%.2f sec, %u nodes, %1.0f knps) PV=%s\n",
+               sprintf(buf, "kibitz !!! %+.2f/%d (%.2f sec, %u nodes, %.0f knps) PV=%s\n",
                        programStats.score / 100.,
                        programStats.depth,
                        programStats.time / 100.,
@@ -5655,6 +5700,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                        (unsigned int)programStats.nodes / (10*abs(programStats.time) + 1.),
                        programStats.movelist);
                SendToICS(buf);
+if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.nodes, programStats.nodes);
          }
        }
 #endif
index 8a0b184..c687701 100644 (file)
--- a/backend.h
+++ b/backend.h
@@ -202,6 +202,8 @@ Boolean ParseOneMove P((char *move, int moveNum,
 char *VariantName P((VariantClass v));
 VariantClass StringToVariant P((char *e));
 double u64ToDouble P((u64 value));
+void OutputChatMessage P((int partner, char *mess));
+
 
 char *StrStr P((char *string, char *match));
 char *StrCaseStr P((char *string, char *match));
@@ -257,7 +259,7 @@ char * GameListLineFull P(( int, GameInfo *));
 extern char* StripHighlight P((char *));  /* returns static data */
 extern char* StripHighlightAndTitle P((char *));  /* returns static data */
 
-typedef enum { CheckBox, ComboBox, TextBox, Button, Spin, 
+typedef enum { CheckBox, ComboBox, TextBox, Button, Spin, ResetButton,
                   SaveButton, FileName, PathName, Slider, Message } Control;
 
 typedef struct _OPT {   // [HGM] options: descriptor of UCI-style option
index 266e77e..af659b4 100644 (file)
--- a/common.h
+++ b/common.h
@@ -600,6 +600,7 @@ typedef struct {
     char *secondOptions;
     char *fenOverride1;
     char *fenOverride2;
+    Boolean keepAlive;  /* [HGM] alive     */
 } AppData, *AppDataPtr;
 
 /* [AS] PGN tags (for showing in the game list) */
@@ -648,6 +649,11 @@ typedef struct {
     int holdingsWidth; /* number of files left and right of board, 0 or 2   */
 } GameInfo;
 
+// [HGM] chat  
+#define MAX_CHAT 3
+extern int chatCount;
+extern char chatPartner[MAX_CHAT][MSG_SIZ];
+
 
 #endif
 
index 83dde19..e8a7e99 100644 (file)
@@ -7,7 +7,7 @@ PROJ=winboard
 OBJS=backend.o book.o gamelist.o lists.o moves.o pgntags.o uci.o zippy.o\\r
  parser.o wbres.o wclipbrd.o wedittags.o wengineo.o wevalgraph.o\\r
  wgamelist.o whistory.o winboard.o wlayout.o woptions.o wsnap.o\\r
- wsockerr.o help.o wsettings.o\r
+ wsockerr.o help.o wsettings.o wchat.o\r
 \r
 \r
 # make compiling less spammy\r
@@ -160,10 +160,13 @@ zippy.o: ../zippy.c config.h ../common.h ../zippy.h ../frontend.h \
 book.o: ../book.c ../common.h ../backend.h ../lists.h\r
        $(call compile, $<)\r
 \r
-uci.o: ../uci.c ..//common.h ../backend.h ../frontend.h ../lists.h\r
+uci.o: ../uci.c ../common.h ../backend.h ../frontend.h ../lists.h\r
        $(call compile, $<)\r
 \r
-wsettings.o: wsettings.c ..//common.h ../backend.h ../frontend.h ../lists.h\r
+wsettings.o: wsettings.c ../common.h ../backend.h ../frontend.h ../lists.h\r
+       $(call compile, $<)\r
+\r
+wchat.o: wchat.c winboard.h wsnap.h ../common.h ../backend.h ../frontend.h ../lists.h\r
        $(call compile, $<)\r
 \r
 %.o: %.c\r
index c78bbb4..10c95fd 100644 (file)
@@ -15,7 +15,7 @@ PROJ = winboard
 OBJS=backend.obj book.obj gamelist.obj lists.obj moves.obj pgntags.obj uci.obj\\r
  zippy.obj parser.obj wclipbrd.obj wedittags.obj wengineo.obj wevalgraph.obj\\r
  wgamelist.obj whistory.obj winboard.obj wlayout.obj woptions.obj wsnap.obj\\r
- wsockerr.obj help.obj wsettings.obj\r
+ wsockerr.obj help.obj wsettings.obj wchat.obj\r
 \r
 \r
 # Debugging?\r
@@ -165,13 +165,16 @@ zippy.obj: ../zippy.c config.h ../common.h ../zippy.h ../frontend.h \
        ../backend.h ../backendz.h ../lists.h\r
         $(CC) $(CFLAGS) ../zippy.c\r
 \r
-uci.obj: ../uci.c ..//common.h ../backend.h ../frontend.h ../lists.h\r
+uci.obj: ../uci.c ../common.h ../backend.h ../frontend.h ../lists.h\r
         $(CC) $(CFLAGS) ../uci.c\r
 \r
 \r
-wsettings.obj: wsettings.c ..//common.h ../backend.h ../frontend.h ../lists.h\r
+wsettings.obj: wsettings.c ../common.h ../backend.h ../frontend.h ../lists.h\r
         $(CC) $(CFLAGS) wsettings.c\r
 \r
+wchat.obj: wchat.c winboard.h wsnap.h ../common.h ../backend.h ../frontend.h ../lists.h\r
+        $(CC) $(CFLAGS) wchat.c\r
+\r
 \r
 $(PROJ).exe: $(OBJS) $(PROJ).res $(PROJ).hlp\r
     $(LINK) $(LFLAGS) $(OBJS) wsock32.lib comctl32.lib winmm.lib shell32.lib\\r
index 565fab6..56918ae 100644 (file)
 #define IDM_FlipClock                   1700\r
 #define OPT_AllWhite                    1701\r
 #define OPT_UpsideDown                  1702\r
+#define DLG_Chat                       1720\r
+#define IDC_Change                     1721\r
+#define IDC_ChatPartner                        1722\r
+#define IDC_ChatMemo                   1723\r
+#define OPT_ChatInput                  1724\r
+#define IDC_Clear                      1725\r
+#define IDC_Send                       1726\r
+#define IDM_NewChat                    1727\r
 #define IDC_SPECIFY_ENG_STATIC          1814\r
 #define IDC_SPECIFY_SERVER_STATIC       1815\r
 #define OPT_MESS                        1818\r
diff --git a/winboard/wchat.c b/winboard/wchat.c
new file mode 100644 (file)
index 0000000..0fd5e08
--- /dev/null
@@ -0,0 +1,255 @@
+/*\r
+ * Chat window (PV)\r
+ *\r
+ * Author: H.G.Muller (August 2009)\r
+ *\r
+ * ------------------------------------------------------------------------\r
+ *\r
+ * GNU XBoard is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or (at\r
+ * your option) any later version.\r
+ *\r
+ * GNU XBoard is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
+ *\r
+ *------------------------------------------------------------------------\r
+ ** See the file ChangeLog for a revision history.  */\r
+\r
+#include "config.h"\r
+\r
+#include <windows.h> /* required for all Windows applications */\r
+#include <richedit.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <commdlg.h>\r
+#include <dlgs.h>\r
+\r
+#include "common.h"\r
+#include "winboard.h"\r
+#include "frontend.h"\r
+#include "backend.h"\r
+\r
+#include "wsnap.h"\r
+\r
+int chatCount;\r
+extern char chatPartner[MAX_CHAT][MSG_SIZ];\r
+HANDLE chatHandle[MAX_CHAT];\r
+\r
+void SendToICS P((char *s));\r
+void ChatPopUp();\r
+void ChatPopDown();\r
+\r
+/* Imports from backend.c */\r
+char * SavePart(char *str);\r
+extern int opponentKibitzes;\r
+\r
+/* Imports from winboard.c */\r
+extern HWND ChatDialog;\r
+\r
+extern HINSTANCE hInst;\r
+extern HWND hwndMain;\r
+\r
+extern WindowPlacement wpChat[MAX_CHAT];\r
+\r
+extern BoardSize boardSize;\r
+\r
+/* Module variables */\r
+#define H_MARGIN            5\r
+#define V_MARGIN            5\r
+\r
+// front end, although we might make GetWindowRect front end instead\r
+static int GetControlWidth( HWND hDlg, int id )\r
+{\r
+    RECT rc;\r
+\r
+    GetWindowRect( GetDlgItem( hDlg, id ), &rc );\r
+\r
+    return rc.right - rc.left;\r
+}\r
+\r
+// front end?\r
+static int GetControlHeight( HWND hDlg, int id )\r
+{\r
+    RECT rc;\r
+\r
+    GetWindowRect( GetDlgItem( hDlg, id ), &rc );\r
+\r
+    return rc.bottom - rc.top;\r
+}\r
+\r
+static void SetControlPos( HWND hDlg, int id, int x, int y, int width, int height )\r
+{\r
+    HWND hControl = GetDlgItem( hDlg, id );\r
+\r
+    SetWindowPos( hControl, HWND_TOP, x, y, width, height, SWP_NOZORDER );\r
+}\r
+\r
+// Also here some of the size calculations should go to the back end, and their actual application to a front-end routine\r
+static void ResizeWindowControls( HWND hDlg )\r
+{\r
+    RECT rc;\r
+    int clientWidth;\r
+    int clientHeight;\r
+    int maxControlWidth;\r
+    int buttonWidth, buttonHeight;\r
+#if 0\r
+}\r
+#else\r
+    /* Initialize variables */\r
+    GetClientRect( hDlg, &rc );\r
+\r
+    clientWidth = rc.right - rc.left;\r
+    clientHeight = rc.bottom - rc.top;\r
+\r
+    maxControlWidth = clientWidth - 2*H_MARGIN;\r
+    buttonWidth  = GetControlWidth(hDlg, IDC_Send);\r
+    buttonHeight = GetControlHeight(hDlg, IDC_Send);\r
+\r
+    /* Resize controls */\r
+    SetControlPos( hDlg, IDC_Clear, maxControlWidth+H_MARGIN-2*buttonWidth-5, V_MARGIN, buttonWidth, buttonHeight );\r
+    SetControlPos( hDlg, IDC_Send, maxControlWidth+H_MARGIN-buttonWidth, V_MARGIN, buttonWidth, buttonHeight );\r
+    SetControlPos( hDlg, IDC_ChatMemo, H_MARGIN, 2*V_MARGIN+buttonHeight, maxControlWidth, clientHeight-3*V_MARGIN-2*buttonHeight );\r
+    SetControlPos( hDlg, OPT_ChatInput, H_MARGIN, clientHeight-V_MARGIN-buttonHeight, maxControlWidth, buttonHeight );\r
+\r
+//    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo1), NULL, FALSE );\r
+//    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo2), NULL, FALSE );\r
+}\r
+#endif\r
+\r
+// front end. Actual printing of PV lines into the output field\r
+static void InsertIntoMemo( HANDLE hDlg, char * text )\r
+{\r
+    HANDLE hMemo = GetDlgItem(hDlg, IDC_ChatMemo);\r
+\r
+    SendMessage( hMemo, EM_SETSEL, 1000000, 1000000 );\r
+\r
+    SendMessage( hMemo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );\r
+    SendMessage( hMemo, EM_SCROLLCARET, 0, 0);\r
+}\r
+\r
+// This seems pure front end\r
+LRESULT CALLBACK ChatProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )\r
+{\r
+    static SnapData sd;\r
+    char buf[MSG_SIZ], mess[MSG_SIZ];\r
+    int partner = -1, i;\r
+\r
+    for(i=0; i<MAX_CHAT; i++) if(hDlg == chatHandle[i]) { partner = i; break; }\r
+\r
+    switch (message) {\r
+    case WM_INITDIALOG:\r
+       if(partner<0) {\r
+               for(i=0; i<MAX_CHAT; i++) if(chatHandle[i] == NULL) { partner = i; break; }\r
+               chatHandle[partner] = hDlg;\r
+               sprintf(buf, "Chat Window %s", first.tidy);\r
+               SetWindowText(hDlg, buf);\r
+        }\r
+       chatPartner[partner][0] = 0;\r
+\r
+        return FALSE;\r
+\r
+    case WM_COMMAND:\r
+        switch (LOWORD(wParam)) {\r
+\r
+       case IDCANCEL:\r
+           chatHandle[partner] = 0;\r
+           chatPartner[partner][0] = 0;\r
+            ChatPopDown();\r
+           EndDialog(hDlg, TRUE);\r
+            break;\r
+\r
+       case IDC_Clear:\r
+           SendMessage( GetDlgItem(hDlg, IDC_ChatMemo), WM_SETTEXT, 0, (LPARAM) "" );\r
+           break;\r
+\r
+       case IDC_Change:\r
+           GetDlgItemText(hDlg, IDC_ChatPartner, chatPartner[partner], MSG_SIZ);\r
+           break;\r
+\r
+       case IDC_Send:\r
+           GetDlgItemText(hDlg, OPT_ChatInput, mess, MSG_SIZ);\r
+           SetDlgItemText(hDlg, OPT_ChatInput, "");\r
+           // from here on it could be back-end\r
+           if(strcmp("WHISPER", chatPartner[partner])) {\r
+               sprintf(buf, "> %s\n", mess); // echo only tells, not whispers\r
+               InsertIntoMemo(hDlg, buf);\r
+               sprintf(buf, "tell %s %s\n", chatPartner[partner], mess);\r
+           } else sprintf(buf, "whisper %s\n", mess); // SAY box uses "say" to send\r
+           SendToICS(buf);\r
+           break;\r
+\r
+        default:\r
+          break;\r
+        }\r
+\r
+        break;\r
+\r
+    case WM_CLOSE:\r
+       chatHandle[partner] = 0;\r
+       chatPartner[partner][0] = 0;\r
+        ChatPopDown();\r
+       EndDialog(hDlg, TRUE);\r
+        break;\r
+\r
+    case WM_SIZE:\r
+        ResizeWindowControls( hDlg );\r
+        break;\r
+\r
+    case WM_ENTERSIZEMOVE:\r
+        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_SIZING:\r
+        return OnSizing( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_MOVING:\r
+        return OnMoving( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_EXITSIZEMOVE:\r
+        return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+// front end\r
+void ChatPopUp()\r
+{\r
+  FARPROC lpProc;\r
+  \r
+  if(chatCount >= MAX_CHAT) return;\r
+\r
+  CheckMenuItem(GetMenu(hwndMain), IDM_NewChat, MF_CHECKED);\r
+  chatCount++;\r
+\r
+    lpProc = MakeProcInstance( (FARPROC) ChatProc, hInst );\r
+\r
+    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */\r
+    CreateDialog( hInst, MAKEINTRESOURCE(DLG_Chat), hwndMain, (DLGPROC)lpProc );\r
+\r
+    FreeProcInstance(lpProc);\r
+\r
+}\r
+\r
+// front end\r
+void ChatPopDown()\r
+{\r
+  if(--chatCount <= 0)\r
+       CheckMenuItem(GetMenu(hwndMain), IDM_NewChat, MF_UNCHECKED);\r
+}\r
+\r
+\r
+//------------------------ pure back-end routines -------------------------------\r
+\r
+void OutputChatMessage(int partner, char *text)\r
+{\r
+       if(!chatHandle[partner]) return;\r
+\r
+       InsertIntoMemo(chatHandle[partner], text);\r
+}\r
index d6f4a45..4cb6ef4 100644 (file)
 \r
 extern int whiteFlag, blackFlag;\r
 Boolean flipClock = FALSE;\r
+extern HANDLE chatHandle[];\r
+extern int ics_type;\r
 \r
 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);\r
 VOID NewVariantPopup(HWND hwnd);\r
@@ -108,6 +110,7 @@ int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);\r
 void DisplayMove P((int moveNumber));\r
 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));\r
+void ChatPopUp P(());\r
 typedef struct {\r
   ChessSquare piece;  \r
   POINT pos;      /* window coordinates of current pos */\r
@@ -572,7 +575,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        if(msg.hwnd == e2)                 currentElement = 3; else\r
        if(msg.hwnd == moveHistoryDialog) currentElement = 4; else\r
        if(msg.hwnd == mh)                currentElement = 4; else\r
-       if(msg.hwnd == evalGraphDialog)    currentElement = 7; else\r
+       if(msg.hwnd == evalGraphDialog)    currentElement = 6; else\r
        if(msg.hwnd == hText)  currentElement = 5; else\r
        if(msg.hwnd == hInput) currentElement = 6; else\r
        for (i = 0; i < N_BUTTONS; i++) {\r
@@ -597,7 +600,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                case 4:\r
                  if(!MoveHistoryIsUp()) continue;\r
                  h = mh; break;\r
-//             case 5: // input to eval graph does not seem to get here!\r
+//             case 6: // input to eval graph does not seem to get here!\r
 //               if(!EvalGraphIsUp()) continue;\r
 //               h = evalGraphDialog; break;\r
                case 5:\r
@@ -629,6 +632,12 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL\r
           !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&\r
          !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {\r
+       int done = 0, i; // [HGM] chat: dispatch cat-box messages\r
+       for(i=0; i<MAX_CHAT; i++) \r
+           if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {\r
+               done = 1; break;\r
+       }\r
+       if(done) continue; // [HGM] chat: end patch\r
        TranslateMessage(&msg); /* Translates virtual key codes */\r
        DispatchMessage(&msg);  /* Dispatches message to window */\r
       }\r
@@ -1321,6 +1330,8 @@ ArgDescriptor argDescriptors[] = {
   { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },\r
   { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },\r
   { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },\r
+  { "keepAlive", ArgInt, (LPVOID) &appData.keepAlive, FALSE },\r
+  { "icstype", ArgInt, (LPVOID) &ics_type, FALSE },\r
 \r
 #ifdef ZIPPY\r
   { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
@@ -5129,7 +5140,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                      If promotion to Q is legal, all are legal! */\r
                  if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)\r
                  { ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];\r
-                   // kludge to temporarily execute move on display, without promotng yet\r
+                   // kludge to temporarily execute move on display, without promoting yet\r
                    promotionChoice = TRUE;\r
                    boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank\r
                    boards[currentMove][toY][toX] = p;\r
@@ -5865,6 +5876,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       GameListOptions();\r
       break;\r
 \r
+    case IDM_NewChat:\r
+      ChatPopUp();\r
+      break;\r
+\r
     case IDM_CopyPosition:\r
       CopyFENToClipboard();\r
       break;\r
@@ -9849,7 +9864,7 @@ void
 ScheduleDelayedEvent(DelayedEventCallback cb, long millisec)\r
 {\r
   if (delayedTimerEvent != 0) {\r
-    if (appData.debugMode) {\r
+    if (appData.debugMode && cb != delayedTimerCallback) { // [HGM] alive: not too much debug\r
       fprintf(debugFP, "ScheduleDelayedEvent: event already scheduled\n");\r
     }\r
     KillTimer(hwndMain, delayedTimerEvent);\r
index 0e9cb38..bb0927d 100644 (file)
@@ -815,6 +815,24 @@ BEGIN
     ICON            IDI_TRANS_14,IDC_StateIcon2,164,84,20,20\r
 END\r
 \r
+DLG_Chat DIALOGEX 0, 0, 256, 106\r
+STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME\r
+EXSTYLE WS_EX_TOOLWINDOW\r
+CAPTION "Chat Window"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    LTEXT           "Chat partner:",IDC_STATIC,5,5,45,10\r
+    EDITTEXT        IDC_ChatPartner,50,3,100,13,ES_AUTOHSCROLL\r
+    PUSHBUTTON      "Change",IDC_Change,155,3,35,13\r
+    PUSHBUTTON      "Clear",IDC_Clear,198,3,25,13\r
+    DEFPUSHBUTTON   "Send",IDC_Send,228,3,25,13\r
+    CONTROL         "",IDC_ChatMemo,"RICHEDIT",ES_MULTILINE | ES_READONLY |\r
+                    ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | \r
+                    WS_HSCROLL | WS_TABSTOP,3,17,250,70\r
+    CONTROL         "",OPT_ChatInput,"RICHEDIT",ES_AUTOHSCROLL | ES_NOHIDESEL | \r
+                    WS_BORDER | WS_TABSTOP,3,90,250,13\r
+END\r
+\r
 DLG_EnginePlayOptions DIALOG DISCARDABLE  0, 0, 208, 202\r
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
 CAPTION "Adjudications"\r
@@ -1095,6 +1113,7 @@ BEGIN
         MENUITEM "Show Evaluation Graph\tAlt+Shift+E",IDM_ShowEvalGraph\r
         MENUITEM "Show Game &List\tAlt+Shift+G",      IDM_ShowGameList\r
         MENUITEM "Show Move History\tAlt+Shift+H",    IDM_ShowMoveHistory\r
+        MENUITEM "Open Chat Window",            IDM_NewChat\r
         MENUITEM SEPARATOR\r
         MENUITEM "Edit &Tags...",               IDM_EditTags\r
         MENUITEM "Edit &Comment...",            IDM_EditComment\r
index 8907a3b..257fcd2 100644 (file)
@@ -52,6 +52,7 @@ PrintOpt(int i, int right, ChessProgramState *cps)
                break;\r
            case Button:\r
            case SaveButton:\r
+           case ResetButton:\r
                fprintf(debugFP, "[ %26.26s ]", opt.name);\r
            case Message:\r
                break;\r
@@ -86,6 +87,7 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis
            switch(nextType = optionList[nextOption].type) {\r
                case CheckBox: checkList[checks++] = nextOption; lastType = CheckBox; break;\r
                case ComboBox: comboList[combos++] = nextOption; lastType = ComboBox; break;\r
+               case ResetButton:\r
                case SaveButton:\r
                case Button:  buttonList[buttons++] = nextOption; lastType = Button; break;\r
                case TextBox:\r
@@ -596,6 +598,7 @@ void AddOption(int x, int y, Control type, int i)
            AddControl(x+95, y-1, 50, 500, 0x0085, CBS_AUTOHSCROLL | CBS_DROPDOWN | WS_VISIBLE | WS_CHILD | WS_TABSTOP, i+1);\r
            break;\r
        case Button:\r
+       case ResetButton:\r
        case SaveButton:\r
            AddControl(x-2, y, 65, 13, 0x0080, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD, i);\r
        case Message:\r