Make WB Chat Boxes wrap and handle URLs
[xboard.git] / winboard / wchat.c
index d6dc502..e1f43cf 100644 (file)
@@ -45,7 +45,7 @@ extern char chatPartner[MAX_CHAT][MSG_SIZ];
 HANDLE chatHandle[MAX_CHAT];\r
 \r
 void SendToICS P((char *s));\r
-void ChatPopUp();\r
+void ChatPopUp P((char *s));\r
 void ChatPopDown();\r
 \r
 /* Imports from backend.c */\r
@@ -139,6 +139,8 @@ LRESULT CALLBACK ChatProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam
     char buf[MSG_SIZ], mess[MSG_SIZ];\r
     int partner = -1, i;\r
     static BOOL filterHasFocus[MAX_CHAT];\r
+    WORD wMask;\r
+    HWND hMemo;\r
 \r
     for(i=0; i<MAX_CHAT; i++) if(hDlg == chatHandle[i]) { partner = i; break; }\r
 \r
@@ -150,11 +152,37 @@ LRESULT CALLBACK ChatProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam
                sprintf(buf, "Chat Window %s", first.tidy);\r
                SetWindowText(hDlg, buf);\r
         }\r
-       chatPartner[partner][0] = 0;\r
-       filterHasFocus[partner] = FALSE;\r
-\r
+//     chatPartner[partner][0] = 0;\r
+       SendMessage( GetDlgItem(hDlg, IDC_ChatPartner), // [HGM] clickbox: initialize with requested handle\r
+                       WM_SETTEXT, 0, (LPARAM) chatPartner[partner] );\r
+       filterHasFocus[partner] = TRUE;\r
+       if(chatPartner[partner][0]) {\r
+           filterHasFocus[partner] = FALSE;\r
+           SetFocus( GetDlgItem(hDlg, OPT_ChatInput) );\r
+       }\r
+       hMemo = GetDlgItem(hDlg, IDC_ChatMemo);\r
+       wMask = (WORD) SendMessage(hMemo, EM_GETEVENTMASK, 0, 0L);\r
+       SendMessage(hMemo, EM_SETEVENTMASK, 0, wMask | ENM_LINK);\r
+       SendMessage(hMemo, EM_AUTOURLDETECT, TRUE, 0L);\r
         return FALSE;\r
 \r
+    case WM_NOTIFY:\r
+      if (((NMHDR*)lParam)->code == EN_LINK)\r
+      {\r
+       ENLINK *pLink = (ENLINK*)lParam;\r
+       if (pLink->msg == WM_LBUTTONUP)\r
+       {\r
+         TEXTRANGE tr;\r
+\r
+         tr.chrg = pLink->chrg;\r
+         tr.lpstrText = malloc(1+tr.chrg.cpMax-tr.chrg.cpMin);\r
+         SendMessage( GetDlgItem(hDlg, IDC_ChatMemo), EM_GETTEXTRANGE, 0, (LPARAM)&tr);\r
+         ShellExecute(NULL, "open", tr.lpstrText, NULL, NULL, SW_SHOW);\r
+         free(tr.lpstrText);\r
+       }\r
+      }\r
+    break;\r
+\r
     case WM_COMMAND:\r
       /* \r
         [AS]\r
@@ -203,7 +231,7 @@ LRESULT CALLBACK ChatProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam
                sprintf(buf, "whisper %s\n", mess); // WHISPER box uses "whisper" to send\r
            else {\r
                if(!atoi(chatPartner[partner])) {\r
-                   sprintf(buf, "> %s\n", mess); // echo only tells to handle, not channel\r
+                   sprintf(buf, "> %s\r\n", mess); // echo only tells to handle, not channel\r
                InsertIntoMemo(hDlg, buf);\r
                sprintf(buf, "xtell %s %s\n", chatPartner[partner], mess);\r
                } else\r
@@ -246,13 +274,17 @@ LRESULT CALLBACK ChatProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam
 }\r
 \r
 // front end\r
-void ChatPopUp()\r
+void ChatPopUp(char *icsHandle)\r
 {\r
   FARPROC lpProc;\r
+  int i, partner = -1;\r
   \r
-  if(chatCount >= MAX_CHAT) return;\r
-\r
   CheckMenuItem(GetMenu(hwndMain), IDM_NewChat, MF_CHECKED);\r
+  for(i=0; i<MAX_CHAT; i++) if(chatHandle[i] == NULL) { partner = i; break; }\r
+  if(partner == -1) { DisplayError("You first have to close a Chat Box\nbefore you can open a new one", 0); return; }\r
+  if(icsHandle) // [HGM] clickbox set handle in advance\r
+       strcpy(chatPartner[partner], icsHandle);\r
+  else chatPartner[partner][0] = NULLCHAR;\r
   chatCount++;\r
 \r
     lpProc = MakeProcInstance( (FARPROC) ChatProc, hInst );\r
@@ -278,5 +310,7 @@ void OutputChatMessage(int partner, char *text)
 {\r
        if(!chatHandle[partner]) return;\r
 \r
+       int n = strlen(text);\r
+       text[n+1] = 0; text[n] = '\n'; text[n-1] = '\r'; // Needs CR to not lose line breaks on copy-paste\r
        InsertIntoMemo(chatHandle[partner], text);\r
 }\r