diff options
author | George Hazan <ghazan@miranda.im> | 2016-11-01 23:26:59 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2016-11-01 23:26:59 +0300 |
commit | 88e9a3438231b9dc6e1101e739f55bceead19796 (patch) | |
tree | b531ef8dc61160152d357702094f94485e7227b8 | |
parent | be8e375ec9335eb717a17239f68c9b40daed8233 (diff) |
StdChat merged with StdMsg
50 files changed, 4853 insertions, 18 deletions
diff --git a/src/core/stdmsg/res/1.ico b/src/core/stdmsg/res/1.ico Binary files differnew file mode 100644 index 0000000000..61fa00e172 --- /dev/null +++ b/src/core/stdmsg/res/1.ico diff --git a/src/core/stdmsg/res/2.ico b/src/core/stdmsg/res/2.ico Binary files differnew file mode 100644 index 0000000000..5c1dc06fbc --- /dev/null +++ b/src/core/stdmsg/res/2.ico diff --git a/src/core/stdmsg/res/3.ico b/src/core/stdmsg/res/3.ico Binary files differnew file mode 100644 index 0000000000..f103719b68 --- /dev/null +++ b/src/core/stdmsg/res/3.ico diff --git a/src/core/stdmsg/res/4.ico b/src/core/stdmsg/res/4.ico Binary files differnew file mode 100644 index 0000000000..47d8f35fe2 --- /dev/null +++ b/src/core/stdmsg/res/4.ico diff --git a/src/core/stdmsg/res/5.ico b/src/core/stdmsg/res/5.ico Binary files differnew file mode 100644 index 0000000000..7008463787 --- /dev/null +++ b/src/core/stdmsg/res/5.ico diff --git a/src/core/stdmsg/res/6.ico b/src/core/stdmsg/res/6.ico Binary files differnew file mode 100644 index 0000000000..8a681faeb7 --- /dev/null +++ b/src/core/stdmsg/res/6.ico diff --git a/src/core/stdmsg/res/action.ico b/src/core/stdmsg/res/action.ico Binary files differnew file mode 100644 index 0000000000..ec7694b075 --- /dev/null +++ b/src/core/stdmsg/res/action.ico diff --git a/src/core/stdmsg/res/addmode.ico b/src/core/stdmsg/res/addmode.ico Binary files differnew file mode 100644 index 0000000000..fcfa03a6ad --- /dev/null +++ b/src/core/stdmsg/res/addmode.ico diff --git a/src/core/stdmsg/res/bkgcolor.ico b/src/core/stdmsg/res/bkgcolor.ico Binary files differnew file mode 100644 index 0000000000..8ff040dd1b --- /dev/null +++ b/src/core/stdmsg/res/bkgcolor.ico diff --git a/src/core/stdmsg/res/blank.ico b/src/core/stdmsg/res/blank.ico Binary files differnew file mode 100644 index 0000000000..d8a5b3d80d --- /dev/null +++ b/src/core/stdmsg/res/blank.ico diff --git a/src/core/stdmsg/res/bold.ico b/src/core/stdmsg/res/bold.ico Binary files differnew file mode 100644 index 0000000000..63810159f9 --- /dev/null +++ b/src/core/stdmsg/res/bold.ico diff --git a/src/core/stdmsg/res/close.ico b/src/core/stdmsg/res/close.ico Binary files differnew file mode 100644 index 0000000000..6facfcffeb --- /dev/null +++ b/src/core/stdmsg/res/close.ico diff --git a/src/core/stdmsg/res/color.ico b/src/core/stdmsg/res/color.ico Binary files differnew file mode 100644 index 0000000000..b75015154a --- /dev/null +++ b/src/core/stdmsg/res/color.ico diff --git a/src/core/stdmsg/res/excl.ico b/src/core/stdmsg/res/excl.ico Binary files differnew file mode 100644 index 0000000000..7cb1691367 --- /dev/null +++ b/src/core/stdmsg/res/excl.ico diff --git a/src/core/stdmsg/res/filter.ico b/src/core/stdmsg/res/filter.ico Binary files differnew file mode 100644 index 0000000000..a2edc9e60c --- /dev/null +++ b/src/core/stdmsg/res/filter.ico diff --git a/src/core/stdmsg/res/filter2.ico b/src/core/stdmsg/res/filter2.ico Binary files differnew file mode 100644 index 0000000000..3adc966a6c --- /dev/null +++ b/src/core/stdmsg/res/filter2.ico diff --git a/src/core/stdmsg/res/highlight.ico b/src/core/stdmsg/res/highlight.ico Binary files differnew file mode 100644 index 0000000000..850afb2f46 --- /dev/null +++ b/src/core/stdmsg/res/highlight.ico diff --git a/src/core/stdmsg/res/history.ico b/src/core/stdmsg/res/history.ico Binary files differnew file mode 100644 index 0000000000..10bbd7aaf7 --- /dev/null +++ b/src/core/stdmsg/res/history.ico diff --git a/src/core/stdmsg/res/info.ico b/src/core/stdmsg/res/info.ico Binary files differnew file mode 100644 index 0000000000..419bb1adb5 --- /dev/null +++ b/src/core/stdmsg/res/info.ico diff --git a/src/core/stdmsg/res/italics.ico b/src/core/stdmsg/res/italics.ico Binary files differnew file mode 100644 index 0000000000..42d3fea61b --- /dev/null +++ b/src/core/stdmsg/res/italics.ico diff --git a/src/core/stdmsg/res/join.ico b/src/core/stdmsg/res/join.ico Binary files differnew file mode 100644 index 0000000000..1b6176d0ad --- /dev/null +++ b/src/core/stdmsg/res/join.ico diff --git a/src/core/stdmsg/res/kick.ico b/src/core/stdmsg/res/kick.ico Binary files differnew file mode 100644 index 0000000000..f8dee5c356 --- /dev/null +++ b/src/core/stdmsg/res/kick.ico diff --git a/src/core/stdmsg/res/message.ico b/src/core/stdmsg/res/message.ico Binary files differnew file mode 100644 index 0000000000..7d98eb94e3 --- /dev/null +++ b/src/core/stdmsg/res/message.ico diff --git a/src/core/stdmsg/res/messageout.ico b/src/core/stdmsg/res/messageout.ico Binary files differnew file mode 100644 index 0000000000..83c8e296e5 --- /dev/null +++ b/src/core/stdmsg/res/messageout.ico diff --git a/src/core/stdmsg/res/nick.ico b/src/core/stdmsg/res/nick.ico Binary files differnew file mode 100644 index 0000000000..27d9fea978 --- /dev/null +++ b/src/core/stdmsg/res/nick.ico diff --git a/src/core/stdmsg/res/nicklist.ico b/src/core/stdmsg/res/nicklist.ico Binary files differnew file mode 100644 index 0000000000..460e7890a2 --- /dev/null +++ b/src/core/stdmsg/res/nicklist.ico diff --git a/src/core/stdmsg/res/nicklist2.ico b/src/core/stdmsg/res/nicklist2.ico Binary files differnew file mode 100644 index 0000000000..236787629b --- /dev/null +++ b/src/core/stdmsg/res/nicklist2.ico diff --git a/src/core/stdmsg/res/overlay.ico b/src/core/stdmsg/res/overlay.ico Binary files differnew file mode 100644 index 0000000000..dc9738d792 --- /dev/null +++ b/src/core/stdmsg/res/overlay.ico diff --git a/src/core/stdmsg/res/part.ico b/src/core/stdmsg/res/part.ico Binary files differnew file mode 100644 index 0000000000..5d6e5b90df --- /dev/null +++ b/src/core/stdmsg/res/part.ico diff --git a/src/core/stdmsg/res/quit.ico b/src/core/stdmsg/res/quit.ico Binary files differnew file mode 100644 index 0000000000..febcbecb96 --- /dev/null +++ b/src/core/stdmsg/res/quit.ico diff --git a/src/core/stdmsg/res/removestatus.ico b/src/core/stdmsg/res/removestatus.ico Binary files differnew file mode 100644 index 0000000000..b772f6a9c6 --- /dev/null +++ b/src/core/stdmsg/res/removestatus.ico diff --git a/src/core/stdmsg/res/resource.rc b/src/core/stdmsg/res/resource.rc index 0d7d7d4593..9a0800758c 100644 --- a/src/core/stdmsg/res/resource.rc +++ b/src/core/stdmsg/res/resource.rc @@ -200,7 +200,149 @@ BEGIN LTEXT "Load history events",IDC_TXT_TITLE2,0,52,369,8
END
+IDD_CHANNEL DIALOGEX 0, 0, 252, 140
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX |
+ WS_MAXIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU |
+ WS_THICKFRAME
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_MESSAGE,"RichEdit50W",ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_NOHIDESEL | ES_WANTRETURN |
+ ES_NUMBER | WS_VSCROLL | WS_TABSTOP,0,128,127,12,
+ WS_EX_STATICEDGE
+ PUSHBUTTON "&Send",IDOK,136,126,115,14,WS_DISABLED
+ CONTROL "&Emoticons",IDC_SMILEY,"MButtonClass",WS_DISABLED | WS_TABSTOP,112,108,15,13,0x18000000L
+ CONTROL "&Bold",IDC_BOLD,"MButtonClass",WS_DISABLED | WS_TABSTOP,8,108,15,13,0x18000000L
+ CONTROL "&Italic",IDC_ITALICS,"MButtonClass",WS_DISABLED | WS_TABSTOP,24,108,15,13,0x18000000L
+ CONTROL "&Underline",IDC_UNDERLINE,"MButtonClass",WS_DISABLED | WS_TABSTOP,40,108,15,13,0x18000000L
+ CONTROL "&Color",IDC_COLOR,"MButtonClass",WS_DISABLED | WS_TABSTOP,68,108,15,13,0x18000000L
+ CONTROL "&Background color",IDC_BKGCOLOR,"MButtonClass",WS_DISABLED | WS_TABSTOP,84,108,15,13,0x18000000L
+ CONTROL "&History",IDC_HISTORY,"MButtonClass",WS_TABSTOP,188,108,15,13,0x18000000L
+ CONTROL "&Filter",IDC_FILTER,"MButtonClass",WS_TABSTOP,220,108,15,13,0x18000000L
+ CONTROL "&Room settings",IDC_CHANMGR,"MButtonClass",WS_DISABLED | WS_TABSTOP,204,108,15,13,0x18000000L
+ CONTROL "&Show/Hide nick list",IDC_SHOWNICKLIST,"MButtonClass",WS_TABSTOP,236,108,15,13,0x18000000L
+ CONTROL "",IDC_LOG,"RichEdit50W",ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_READONLY | ES_NUMBER | WS_VSCROLL | WS_TABSTOP,8,23,
+ 164,73,WS_EX_STATICEDGE
+ CONTROL "",IDC_SPLITTERX,"Static",SS_ENHMETAFILE,172,23,10,73
+ CONTROL "",IDC_SPLITTERY,"Static",SS_ENHMETAFILE,0,102,251,6
+ LISTBOX IDC_LIST,182,23,69,73,LBS_OWNERDRAWFIXED |
+ LBS_NOINTEGRALHEIGHT | LBS_NODATA | NOT WS_BORDER |
+ WS_VSCROLL | WS_TABSTOP,WS_EX_STATICEDGE
+ CONTROL "Tab1",IDC_TAB,"SysTabControl32",TCS_MULTILINE,0,0,231,102
+ CONTROL "",IDC_CLOSE,"MButtonClass",WS_TABSTOP,236,2,15,13,0x18000000L
+END
+
+IDD_FILTER DIALOGEX 0, 0, 83, 125
+STYLE DS_FIXEDSYS | DS_SETFONT | WS_POPUP | WS_BORDER
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CTEXT "Show these events only:",IDC_TEXTO,0,0,83,13,
+ SS_CENTERIMAGE
+ LTEXT "",IDC_STATIC,0,13,83,112
+ CONTROL "Actions",IDC_1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,13,73,10
+ CONTROL "Messages",IDC_2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,23,73,10
+ CONTROL "Nick changes",IDC_3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,33,73,10
+ CONTROL "Users joining",IDC_4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,43,73,10
+ CONTROL "Users leaving",IDC_5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,53,73,10
+ CONTROL "Topic changes",IDC_6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,63,73,10
+ CONTROL "Status changes",IDC_7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,73,73,10
+ CONTROL "Information",IDC_8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,83,73,10
+ CONTROL "Disconnects",IDC_9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,93,73,10
+ CONTROL "User kicks",IDC_10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,103,73,10
+ CONTROL "Notices",IDC_11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,113,73,10
+END
+
+IDD_OPTIONS1 DIALOGEX 0, 0, 300, 230
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Tree1",IDC_CHECKBOXES,"SysTreeView32",TVS_HASBUTTONS |
+ TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP |
+ TVS_FULLROWSELECT | WS_BORDER | WS_TABSTOP,10,12,280,205
+ GROUPBOX "Options",IDC_STATIC,0,0,300,227
+END
+
+IDD_OPTIONS2 DIALOGEX 0, 0, 300, 200
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Log options",IDC_STATIC,1,1,294,134
+ EDITTEXT IDC_OUTSTAMP,10,19,35,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_INSTAMP,60,19,35,14,ES_AUTOHSCROLL
+ LTEXT "Log timestamp",IDC_STATIC,205,11,81,8
+ EDITTEXT IDC_LOGTIMESTAMP,205,19,81,14,ES_AUTOHSCROLL
+ LTEXT "Timestamp",IDC_STATIC,119,11,78,8
+ EDITTEXT IDC_TIMESTAMP,118,19,81,14,ES_AUTOHSCROLL
+ LTEXT "Other name",IDC_STATIC,60,11,57,8
+ LTEXT "Your name",IDC_STATIC,10,11,50,8
+ CONTROL "Enable highlighting",IDC_HIGHLIGHT,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,10,46,118,10
+ LTEXT "Limit log text to (events):",IDC_STATIC,133,46,112,8
+ LTEXT "Trim to (KB)",IDC_STATIC,248,104,38,8
+ EDITTEXT IDC_LOGLIMIT,248,44,38,14,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "Spin1",IDC_SPIN2,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,275,43,11,14
+ LTEXT "Words to highlight (wildcards allowed)",IDC_STATIC,10,
+ 58,240,8
+ EDITTEXT IDC_HIGHLIGHTWORDS,10,67,276,14,ES_AUTOHSCROLL
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,10,86,275,1
+ CONTROL "Enable logging to disk",IDC_LOGGING,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,10,94,211,10
+ LTEXT "Log directory",IDC_STATIC,10,106,211,8
+ EDITTEXT IDC_LOGDIRECTORY,10,114,211,14,ES_AUTOHSCROLL |
+ ES_READONLY
+ PUSHBUTTON "...",IDC_FONTCHOOSE,221,114,19,14
+ EDITTEXT IDC_LIMIT,248,114,38,14,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "Spin1",IDC_SPIN3,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,275,112,11,14
+ GROUPBOX "Other",IDC_STATIC,1,145,294,53
+ LTEXT "Add new rooms to group:",IDC_STATIC,11,159,132,8
+ EDITTEXT IDC_GROUP,158,158,49,14,ES_AUTOHSCROLL
+ LTEXT "Nick list row distance (pixels):",IDC_STATIC,11,180,132,
+ 8
+ EDITTEXT IDC_NICKROW2,158,178,29,14,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "",IDC_SPIN4,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,183,178,11,14
+END
+IDD_OPTIONSPOPUP DIALOGEX 0, 0, 277, 177
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Use same style as in the message log",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,33,29,225,10
+ CONTROL "Use default colors",IDC_RADIO2,"Button",
+ BS_AUTORADIOBUTTON,33,62,217,10
+ CONTROL "Use custom colors",IDC_RADIO3,"Button",
+ BS_AUTORADIOBUTTON,33,95,105,10
+ CONTROL "Custom1",IDC_TEXT,"ColourPicker",WS_TABSTOP,141,93,50,
+ 14,0x18000000L
+ CONTROL "Custom2",IDC_BKG,"ColourPicker",WS_TABSTOP,201,93,50,14,
+ 0x18000000L
+ EDITTEXT IDC_TIMEOUT,132,134,38,14,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,169,135,11,14
+ GROUPBOX "Popups for the Chat plugin",IDC_STATIC,0,0,277,174
+ LTEXT "Timeout (s)",IDC_STATIC,33,138,92,8
+ LTEXT "Text",IDC_STATIC,141,83,49,8
+ LTEXT "Background",IDC_STATIC,201,83,67,8
+ LTEXT "(Setting timeout to 0 means default setting and -1 means indefinite time)",
+ IDC_STATIC,33,151,207,17
+END
+
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
@@ -252,6 +394,71 @@ BEGIN TOPMARGIN, 7
BOTTOMMARGIN, 245
END
+ IDD_CHANNEL, DIALOG
+ BEGIN
+ RIGHTMARGIN, 251
+ VERTGUIDE, 8
+ VERTGUIDE, 172
+ VERTGUIDE, 182
+ VERTGUIDE, 237
+ HORZGUIDE, 8
+ HORZGUIDE, 23
+ HORZGUIDE, 70
+ HORZGUIDE, 96
+ HORZGUIDE, 102
+ HORZGUIDE, 108
+ HORZGUIDE, 121
+ END
+
+ IDD_FILTER, DIALOG
+ BEGIN
+ VERTGUIDE, 5
+ VERTGUIDE, 78
+ HORZGUIDE, 13
+ HORZGUIDE, 117
+ END
+ IDD_OPTIONS1, DIALOG
+ BEGIN
+ VERTGUIDE, 10
+ VERTGUIDE, 153
+ VERTGUIDE, 181
+ VERTGUIDE, 202
+ VERTGUIDE, 290
+ HORZGUIDE, 12
+ HORZGUIDE, 174
+ HORZGUIDE, 192
+ HORZGUIDE, 213
+ END
+
+ IDD_OPTIONS2, DIALOG
+ BEGIN
+ LEFTMARGIN, 1
+ RIGHTMARGIN, 295
+ VERTGUIDE, 10
+ VERTGUIDE, 60
+ VERTGUIDE, 144
+ VERTGUIDE, 158
+ VERTGUIDE, 183
+ VERTGUIDE, 221
+ VERTGUIDE, 286
+ TOPMARGIN, 1
+ BOTTOMMARGIN, 198
+ HORZGUIDE, 108
+ HORZGUIDE, 126
+ HORZGUIDE, 146
+ HORZGUIDE, 158
+ HORZGUIDE, 174
+ END
+
+ IDD_OPTIONSPOPUP, DIALOG
+ BEGIN
+ VERTGUIDE, 33
+ VERTGUIDE, 157
+ VERTGUIDE, 201
+ HORZGUIDE, 49
+ HORZGUIDE, 81
+ HORZGUIDE, 174
+ END
END
#endif // APSTUDIO_INVOKED
@@ -294,6 +501,44 @@ END IDI_INCOMING ICON "incoming.ico"
IDI_OUTGOING ICON "outgoing.ico"
IDI_NOTICE ICON "notice.ico"
+IDI_TAG1 ICON "tag1.ico"
+IDI_TAG2 ICON "tag2.ico"
+IDI_BUNDERLINE ICON "underline.ico"
+IDI_BBOLD ICON "bold.ico"
+IDI_BITALICS ICON "italics.ico"
+IDI_BSMILEY ICON "smiley.ico"
+IDI_JOIN ICON "join.ico"
+IDI_TOPIC ICON "topic.ico"
+IDI_ADDSTATUS ICON "addmode.ico"
+IDI_INFO ICON "info.ico"
+IDI_KICK ICON "kick.ico"
+IDI_MESSAGE ICON "message.ico"
+IDI_NICK ICON "nick.ico"
+IDI_EXCL ICON "excl.ico"
+IDI_PART ICON "part.ico"
+IDI_QUIT ICON "quit.ico"
+IDI_REMSTATUS ICON "removestatus.ico"
+IDI_HIGHLIGHT ICON "highlight.ico"
+IDI_MESSAGEOUT ICON "messageout.ico"
+IDI_ACTION ICON "action.ico"
+IDI_TOPICBUT ICON "topicbut.ico"
+IDI_BKGCOLOR ICON "bkgcolor.ico"
+IDI_CHANMGR ICON "window.ico"
+IDI_COLOR ICON "color.ico"
+IDI_FILTER ICON "filter.ico"
+IDI_HISTORY ICON "history.ico"
+IDI_NICKLIST ICON "nicklist.ico"
+IDI_BLANK ICON "blank.ico"
+IDI_STATUS3 ICON "4.ico"
+IDI_STATUS2 ICON "3.ico"
+IDI_STATUS4 ICON "5.ico"
+IDI_STATUS1 ICON "2.ico"
+IDI_STATUS0 ICON "1.ico"
+IDI_STATUS5 ICON "6.ico"
+IDI_CLOSE ICON "close.ico"
+IDI_OVERLAY ICON "overlay.ico"
+IDI_NICKLIST2 ICON "nicklist2.ico"
+IDI_FILTER2 ICON "filter2.ico"
/////////////////////////////////////////////////////////////////////////////
//
@@ -309,6 +554,52 @@ IDC_DROPUSER CURSOR "dropuser.cur" // Menu
//
+IDR_MENU MENU
+BEGIN
+ POPUP "List"
+ BEGIN
+ MENUITEM "&Message", ID_MESS
+ END
+ POPUP "Log"
+ BEGIN
+ MENUITEM "Clear lo&g", ID_CLEARLOG
+ MENUITEM SEPARATOR
+ MENUITEM "Co&py all", ID_COPYALL
+ MENUITEM SEPARATOR
+ POPUP "Word lookup", GRAYED
+ BEGIN
+ MENUITEM "Google", ID_SEARCH_GOOGLE
+ MENUITEM "Wikipedia", ID_SEARCH_WIKIPEDIA
+ END
+ END
+ POPUP "Link"
+ BEGIN
+ MENUITEM "Open a &new browser window", ID_NEW
+ MENUITEM "&Open in current browser window", ID_CURR
+ MENUITEM "&Copy link", ID_COPY
+ END
+ MENUITEM "", 65535
+ POPUP "Message"
+ BEGIN
+ MENUITEM "Undo", ID_MESSAGE_UNDO, GRAYED
+ MENUITEM "Redo", ID_MESSAGE_REDO, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "Copy", ID_MESSAGE_COPY, GRAYED
+ MENUITEM "Cut", ID_MESSAGE_CUT, GRAYED
+ MENUITEM "Paste", ID_MESSAGE_PASTE
+ MENUITEM "Select all", ID_MESSAGE_SELECTALL
+ MENUITEM SEPARATOR
+ MENUITEM "Clear", ID_MESSAGE_CLEAR
+ END
+ POPUP "Tabs"
+ BEGIN
+ MENUITEM "&Close tab", ID_CLOSE
+ MENUITEM "C&lose other tabs", ID_CLOSEOTHER
+ MENUITEM SEPARATOR
+ MENUITEM "&Open at this position", ID_LOCKPOSITION
+ END
+END
+
IDR_CONTEXT MENU
BEGIN
POPUP "Log"
diff --git a/src/core/stdmsg/res/smiley.ico b/src/core/stdmsg/res/smiley.ico Binary files differnew file mode 100644 index 0000000000..1062805741 --- /dev/null +++ b/src/core/stdmsg/res/smiley.ico diff --git a/src/core/stdmsg/res/smileyc.ico b/src/core/stdmsg/res/smileyc.ico Binary files differnew file mode 100644 index 0000000000..2290e97fe4 --- /dev/null +++ b/src/core/stdmsg/res/smileyc.ico diff --git a/src/core/stdmsg/res/tag1.ico b/src/core/stdmsg/res/tag1.ico Binary files differnew file mode 100644 index 0000000000..4db0312d9d --- /dev/null +++ b/src/core/stdmsg/res/tag1.ico diff --git a/src/core/stdmsg/res/tag2.ico b/src/core/stdmsg/res/tag2.ico Binary files differnew file mode 100644 index 0000000000..5b5197a9cd --- /dev/null +++ b/src/core/stdmsg/res/tag2.ico diff --git a/src/core/stdmsg/res/topic.ico b/src/core/stdmsg/res/topic.ico Binary files differnew file mode 100644 index 0000000000..7d7fe6d402 --- /dev/null +++ b/src/core/stdmsg/res/topic.ico diff --git a/src/core/stdmsg/res/topicbut.ico b/src/core/stdmsg/res/topicbut.ico Binary files differnew file mode 100644 index 0000000000..7c6b07c71a --- /dev/null +++ b/src/core/stdmsg/res/topicbut.ico diff --git a/src/core/stdmsg/res/underline.ico b/src/core/stdmsg/res/underline.ico Binary files differnew file mode 100644 index 0000000000..646d58456d --- /dev/null +++ b/src/core/stdmsg/res/underline.ico diff --git a/src/core/stdmsg/res/window.ico b/src/core/stdmsg/res/window.ico Binary files differnew file mode 100644 index 0000000000..d317845d55 --- /dev/null +++ b/src/core/stdmsg/res/window.ico diff --git a/src/core/stdmsg/src/chat_manager.cpp b/src/core/stdmsg/src/chat_manager.cpp new file mode 100644 index 0000000000..eabc191afc --- /dev/null +++ b/src/core/stdmsg/src/chat_manager.cpp @@ -0,0 +1,474 @@ +/* +Chat module plugin for Miranda IM + +Copyright 2000-12 Miranda IM, 2012-16 Miranda NG project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +TABLIST *g_TabList = 0; + +BOOL SM_SetTabbedWindowHwnd(SESSION_INFO *si, HWND hwnd) +{ + for (SESSION_INFO *p = pci->wndList; p != NULL; p = p->next) { + if (si && si == p) + p->hWnd = hwnd; + else + p->hWnd = NULL; + } + return TRUE; +} + +SESSION_INFO* SM_GetPrevWindow(SESSION_INFO *si) +{ + if (!si) + return NULL; + + BOOL bFound = FALSE; + SESSION_INFO *pTemp = pci->wndList; + while (pTemp != NULL) { + if (si == pTemp) { + if (bFound) + return NULL; + else + bFound = TRUE; + } + else if (bFound == TRUE && pTemp->hWnd) + return pTemp; + pTemp = pTemp->next; + if (pTemp == NULL && bFound) + pTemp = pci->wndList; + } + return NULL; +} + +SESSION_INFO* SM_GetNextWindow(SESSION_INFO *si) +{ + if (!si) + return NULL; + + SESSION_INFO *pTemp = pci->wndList, *pLast = NULL; + while (pTemp != NULL) { + if (si == pTemp) { + if (pLast) { + if (pLast != pTemp) + return pLast; + else + return NULL; + } + } + if (pTemp->hWnd) + pLast = pTemp; + pTemp = pTemp->next; + if (pTemp == NULL) + pTemp = pci->wndList; + } + return NULL; +} + +//--------------------------------------------------- +// Tab list manager functions +// +// Necessary to keep track of what tabs should +// be restored +//--------------------------------------------------- + +BOOL TabM_AddTab(const wchar_t *pszID, const char* pszModule) +{ + TABLIST *node = NULL; + if (!pszID || !pszModule) + return FALSE; + + node = (TABLIST*)mir_alloc(sizeof(TABLIST)); + memset(node, 0, sizeof(TABLIST)); + node->pszID = mir_wstrdup(pszID); + node->pszModule = mir_strdup(pszModule); + + if (g_TabList == NULL) { // list is empty + g_TabList = node; + node->next = NULL; + } + else { + node->next = g_TabList; + g_TabList = node; + } + return TRUE; +} + +BOOL TabM_RemoveAll(void) +{ + while (g_TabList != NULL) { + TABLIST *pLast = g_TabList->next; + mir_free(g_TabList->pszModule); + mir_free(g_TabList->pszID); + mir_free(g_TabList); + g_TabList = pLast; + } + g_TabList = NULL; + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +CHAT_MANAGER *pci, saveCI; + +SESSION_INFO g_TabSession; +HMENU g_hMenu = NULL; + +BOOL SmileyAddInstalled = FALSE, PopupInstalled = FALSE; +HIMAGELIST hIconsList; + +GlobalLogSettings g_Settings; + +static int OnShutdown(WPARAM, LPARAM) +{ + for (SESSION_INFO *si = pci->wndList; si; si = si->next) + SendMessage(si->hWnd, WM_CLOSE, 0, 0); + + TabM_RemoveAll(); + ImageList_Destroy(hIconsList); + return 0; +} + +static void OnCreateModule(MODULEINFO *mi) +{ + mi->OnlineIconIndex = ImageList_AddIcon(hIconsList, Skin_LoadProtoIcon(mi->pszModule, ID_STATUS_ONLINE)); + mi->hOnlineIcon = ImageList_GetIcon(hIconsList, mi->OnlineIconIndex, ILD_TRANSPARENT); + mi->hOnlineTalkIcon = ImageList_GetIcon(hIconsList, mi->OnlineIconIndex, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1)); + ImageList_AddIcon(hIconsList, mi->hOnlineTalkIcon); + + mi->OfflineIconIndex = ImageList_AddIcon(hIconsList, Skin_LoadProtoIcon(mi->pszModule, ID_STATUS_OFFLINE)); + mi->hOfflineIcon = ImageList_GetIcon(hIconsList, mi->OfflineIconIndex, ILD_TRANSPARENT); + mi->hOfflineTalkIcon = ImageList_GetIcon(hIconsList, mi->OfflineIconIndex, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1)); + ImageList_AddIcon(hIconsList, mi->hOfflineTalkIcon); +} + +static void OnAddLog(SESSION_INFO *si, int isOk) +{ + if (isOk && si->hWnd) { + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + SendMessage(si->hWnd, GC_ADDLOG, 0, 0); + } + else if (si->hWnd) { + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + SendMessage(si->hWnd, GC_REDRAWLOG2, 0, 0); + } +} + +static void OnClearLog(SESSION_INFO *si) +{ + if (si->hWnd) { + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + } +} + +static void OnDblClickSession(SESSION_INFO *si) +{ + if (g_Settings.bTabsEnable) + SendMessage(si->hWnd, GC_REMOVETAB, 1, (LPARAM)si); + else + PostMessage(si->hWnd, GC_CLOSEWINDOW, 0, 0); +} + +static void OnRemoveSession(SESSION_INFO *si) +{ + if (!g_Settings.bTabsEnable) { + if (si->hWnd) + SendMessage(si->hWnd, GC_CONTROL_MSG, SESSION_TERMINATE, 0); + } + else if (g_TabSession.hWnd) + SendMessage(g_TabSession.hWnd, GC_REMOVETAB, 1, (LPARAM)si); + + if (si->hWnd) + g_TabSession.nUsersInNicklist = 0; +} + +static void OnRenameSession(SESSION_INFO *si) +{ + if (g_TabSession.hWnd && g_Settings.bTabsEnable) { + g_TabSession.ptszName = si->ptszName; + SendMessage(g_TabSession.hWnd, GC_SESSIONNAMECHANGE, 0, (LPARAM)si); + } +} + +static void OnReplaceSession(SESSION_INFO *si) +{ + if (si->hWnd) + g_TabSession.nUsersInNicklist = 0; + + if (!g_Settings.bTabsEnable) { + if (si->hWnd) + RedrawWindow(GetDlgItem(si->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE); + } + else if (g_TabSession.hWnd) + RedrawWindow(GetDlgItem(g_TabSession.hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE); +} + +static void OnOfflineSession(SESSION_INFO *si) +{ + if (si->hWnd) { + g_TabSession.nUsersInNicklist = 0; + if (g_Settings.bTabsEnable) + g_TabSession.pUsers = 0; + } +} + +static void OnEventBroadcast(SESSION_INFO *si, GCEVENT *gce) +{ + if (pci->SM_AddEvent(si->ptszID, si->pszModule, gce, FALSE) && si->hWnd && si->bInitDone) { + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + SendMessage(si->hWnd, GC_ADDLOG, 0, 0); + } + else if (si->hWnd && si->bInitDone) { + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + SendMessage(si->hWnd, GC_REDRAWLOG2, 0, 0); + } +} + +static void OnSetStatusBar(SESSION_INFO *si) +{ + if (si->hWnd) { + g_TabSession.ptszStatusbarText = si->ptszStatusbarText; + SendMessage(si->hWnd, GC_UPDATESTATUSBAR, 0, 0); + } +} + +static void OnAddUser(SESSION_INFO *si, USERINFO*) +{ + if (si->hWnd) + g_TabSession.nUsersInNicklist++; +} + +static void OnNewUser(SESSION_INFO *si, USERINFO*) +{ + if (si->hWnd) { + g_TabSession.pUsers = si->pUsers; + SendMessage(si->hWnd, GC_UPDATENICKLIST, 0, 0); + } +} + +static void OnRemoveUser(SESSION_INFO *si, USERINFO*) +{ + if (si->hWnd) { + g_TabSession.pUsers = si->pUsers; + g_TabSession.nUsersInNicklist--; + } +} + +static void OnAddStatus(SESSION_INFO *si, STATUSINFO*) +{ + if (g_Settings.bTabsEnable && si->hWnd) + g_TabSession.pStatuses = si->pStatuses; +} + +static void OnSetStatus(SESSION_INFO *si, int wStatus) +{ + if (g_Settings.bTabsEnable) { + if (si->hWnd) + g_TabSession.wStatus = wStatus; + if (g_TabSession.hWnd) + PostMessage(g_TabSession.hWnd, GC_FIXTABICONS, 0, (LPARAM)si); + } +} + +static void OnSetTopic(SESSION_INFO *si) +{ + if (si->hWnd) + g_TabSession.ptszTopic = si->ptszTopic; +} + +static void OnFlashHighlight(SESSION_INFO *si, int bInactive) +{ + if (!bInactive) + return; + + if (!g_Settings.bTabsEnable && si->hWnd && g_Settings.bFlashWindowHighlight) + SetTimer(si->hWnd, TIMERID_FLASHWND, 900, NULL); + if (g_Settings.bTabsEnable && g_TabSession.hWnd) + SendMessage(g_TabSession.hWnd, GC_SETMESSAGEHIGHLIGHT, 0, (LPARAM)si); +} + +static void OnFlashWindow(SESSION_INFO *si, int bInactive) +{ + if (!bInactive) + return; + + if (!g_Settings.bTabsEnable && si->hWnd && g_Settings.bFlashWindow) + SetTimer(si->hWnd, TIMERID_FLASHWND, 900, NULL); + if (g_Settings.bTabsEnable && g_TabSession.hWnd) + SendMessage(g_TabSession.hWnd, GC_SETTABHIGHLIGHT, 0, (LPARAM)si); +} + +static BOOL DoTrayIcon(SESSION_INFO *si, GCEVENT *gce) +{ + if (gce->pDest->iType & g_Settings.dwTrayIconFlags) + return saveCI.DoTrayIcon(si, gce); + return TRUE; +} + +static BOOL DoPopup(SESSION_INFO *si, GCEVENT *gce) +{ + if (gce->pDest->iType & g_Settings.dwPopupFlags) + return saveCI.DoPopup(si, gce); + return TRUE; +} + +static void OnLoadSettings() +{ + if (g_Settings.MessageAreaFont) + DeleteObject(g_Settings.MessageAreaFont); + + LOGFONT lf; + LoadMessageFont(&lf, &g_Settings.MessageAreaColor); + g_Settings.MessageAreaFont = CreateFontIndirect(&lf); + + g_Settings.iX = db_get_dw(NULL, CHAT_MODULE, "roomx", -1); + g_Settings.iY = db_get_dw(NULL, CHAT_MODULE, "roomy", -1); + + g_Settings.bTabsEnable = db_get_b(NULL, CHAT_MODULE, "Tabs", 1) != 0; + g_Settings.TabRestore = db_get_b(NULL, CHAT_MODULE, "TabRestore", 0) != 0; + g_Settings.TabsAtBottom = db_get_b(NULL, CHAT_MODULE, "TabBottom", 0) != 0; + g_Settings.TabCloseOnDblClick = db_get_b(NULL, CHAT_MODULE, "TabCloseOnDblClick", 0) != 0; +} + +static void RegisterFonts() +{ + ColourIDW colourid = { sizeof(colourid) }; + strncpy(colourid.dbSettingsGroup, CHAT_MODULE, sizeof(colourid.dbSettingsGroup)); + wcsncpy(colourid.group, LPGENW("Chat module"), _countof(colourid.group)); + + strncpy(colourid.setting, "ColorLogBG", _countof(colourid.setting)); + wcsncpy(colourid.name, LPGENW("Group chat log background"), _countof(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_WINDOW); + Colour_RegisterW(&colourid); + + strncpy(colourid.setting, "ColorMessageBG", _countof(colourid.setting)); + wcsncpy(colourid.name, LPGENW("Message background"), _countof(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_WINDOW); + Colour_RegisterW(&colourid); + + strncpy(colourid.setting, "ColorNicklistBG", _countof(colourid.setting)); + wcsncpy(colourid.name, LPGENW("Nick list background"), _countof(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_WINDOW); + Colour_RegisterW(&colourid); + + strncpy(colourid.setting, "ColorNicklistLines", _countof(colourid.setting)); + wcsncpy(colourid.name, LPGENW("Nick list lines"), _countof(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_INACTIVEBORDER); + Colour_RegisterW(&colourid); + + strncpy(colourid.setting, "ColorNicklistSelectedBG", _countof(colourid.setting)); + wcsncpy(colourid.name, LPGENW("Nick list background (selected)"), _countof(colourid.name)); + colourid.defcolour = GetSysColor(COLOR_HIGHLIGHT); + Colour_RegisterW(&colourid); +} + +static int OnCheckPlugins(WPARAM, LPARAM) +{ + SmileyAddInstalled = ServiceExists(MS_SMILEYADD_REPLACESMILEYS); + PopupInstalled = ServiceExists(MS_POPUP_ADDPOPUPT); + return 0; +} + +static void TabsInit() +{ + memset(&g_TabSession, 0, sizeof(SESSION_INFO)); + g_TabSession.iType = GCW_TABROOM; + g_TabSession.iSplitterX = g_Settings.iSplitterX; + g_TabSession.iSplitterY = g_Settings.iSplitterY; + g_TabSession.iLogFilterFlags = (int)db_get_dw(NULL, CHAT_MODULE, "FilterFlags", 0x03E0); + g_TabSession.bFilterEnabled = db_get_b(NULL, CHAT_MODULE, "FilterEnabled", 0); + g_TabSession.bNicklistEnabled = db_get_b(NULL, CHAT_MODULE, "ShowNicklist", 1); + g_TabSession.iFG = 4; + g_TabSession.bFGSet = TRUE; + g_TabSession.iBG = 2; + g_TabSession.bBGSet = TRUE; +} + +void Load_ChatModule() +{ + AddIcons(); + RegisterFonts(); + + CHAT_MANAGER_INITDATA data = { &g_Settings, sizeof(MODULEINFO), sizeof(SESSION_INFO), LPGENW("Chat module"), FONTMODE_SKIP }; + pci = Chat_GetInterface(&data); + saveCI = *pci; + + pci->OnAddUser = OnAddUser; + pci->OnNewUser = OnNewUser; + pci->OnRemoveUser = OnRemoveUser; + + pci->OnAddStatus = OnAddStatus; + pci->OnSetStatus = OnSetStatus; + pci->OnSetTopic = OnSetTopic; + + pci->OnAddLog = OnAddLog; + pci->OnClearLog = OnClearLog; + + pci->OnCreateModule = OnCreateModule; + pci->OnOfflineSession = OnOfflineSession; + pci->OnRemoveSession = OnRemoveSession; + pci->OnRenameSession = OnRenameSession; + pci->OnReplaceSession = OnReplaceSession; + pci->OnDblClickSession = OnDblClickSession; + + pci->OnEventBroadcast = OnEventBroadcast; + pci->OnLoadSettings = OnLoadSettings; + pci->OnSetStatusBar = OnSetStatusBar; + pci->OnFlashWindow = OnFlashWindow; + pci->OnFlashHighlight = OnFlashHighlight; + pci->ShowRoom = ShowRoom; + + pci->DoPopup = DoPopup; + pci->DoTrayIcon = DoTrayIcon; + pci->ReloadSettings(); + + g_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU)); + + hIconsList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 0, 100); + ImageList_AddIcon(hIconsList, Skin_LoadIcon(SKINICON_EVENT_MESSAGE)); + ImageList_AddIcon(hIconsList, LoadIconEx("overlay", FALSE)); + ImageList_SetOverlayImage(hIconsList, 1, 1); + + TabsInit(); + + HookEvent(ME_OPT_INITIALISE, OptionsInitialize); + HookEvent(ME_SYSTEM_SHUTDOWN, OnShutdown); + HookEvent(ME_SYSTEM_MODULELOAD, OnCheckPlugins); + HookEvent(ME_SYSTEM_MODULESLOADED, OnCheckPlugins); +} + +void Unload_ChatModule() +{ + db_set_w(NULL, CHAT_MODULE, "SplitterX", (WORD)g_Settings.iSplitterX); + db_set_w(NULL, CHAT_MODULE, "SplitterY", (WORD)g_Settings.iSplitterY); + db_set_dw(NULL, CHAT_MODULE, "roomx", g_Settings.iX); + db_set_dw(NULL, CHAT_MODULE, "roomy", g_Settings.iY); + db_set_dw(NULL, CHAT_MODULE, "roomwidth", g_Settings.iWidth); + db_set_dw(NULL, CHAT_MODULE, "roomheight", g_Settings.iHeight); + + if (g_Settings.MessageAreaFont) + DeleteObject(g_Settings.MessageAreaFont); + DestroyMenu(g_hMenu); +} diff --git a/src/core/stdmsg/src/chat_options.cpp b/src/core/stdmsg/src/chat_options.cpp new file mode 100644 index 0000000000..f234bdbeed --- /dev/null +++ b/src/core/stdmsg/src/chat_options.cpp @@ -0,0 +1,761 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 Jörgen Persson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "resource.h" +#include "stdafx.h" + +struct branch_t +{ + const wchar_t* szDescr; + const char* szDBName; + int iMode; + BYTE bDefault; +}; + +static const struct branch_t branch0[] = { + { LPGENW("Use a tabbed interface"), "Tabs", 0, 1 }, + { LPGENW("Close tab on double click"), "TabCloseOnDblClick", 0, 0 }, + { LPGENW("Restore previously open tabs when showing the window"), "TabRestore", 0, 0 }, + { LPGENW("Show tabs at the bottom"), "TabBottom", 0, 0 }, +}; + +static const struct branch_t branch1[] = { + { LPGENW("Send message by pressing the 'Enter' key"), "SendOnEnter", 0, 1 }, + { LPGENW("Send message by pressing the 'Enter' key twice"), "SendOnDblEnter", 0, 0 }, + { LPGENW("Flash window when someone speaks"), "FlashWindow", 0, 0 }, + { LPGENW("Flash window when a word is highlighted"), "FlashWindowHighlight", 0, 1 }, + { LPGENW("Show list of users in the chat room"), "ShowNicklist", 0, 1 }, + { LPGENW("Show button for sending messages"), "ShowSend", 0, 0 }, + { LPGENW("Show buttons for controlling the chat room"), "ShowTopButtons", 0, 1 }, + { LPGENW("Show buttons for formatting the text you are typing"), "ShowFormatButtons", 0, 1 }, + { LPGENW("Show button menus when right clicking the buttons"), "RightClickFilter", 0, 0 }, + { LPGENW("Show new windows cascaded"), "CascadeWindows", 0, 1 }, + { LPGENW("Save the size and position of chat rooms"), "SavePosition", 0, 0 }, + { LPGENW("Show the topic of the room on your contact list (if supported)"), "TopicOnClist", 0, 0 }, + { LPGENW("Do not play sounds when the chat room is focused"), "SoundsFocus", 0, 0 }, + { LPGENW("Do not pop up the window when joining a chat room"), "PopupOnJoin", 0, 0 }, + { LPGENW("Toggle the visible state when double clicking in the contact list"), "ToggleVisibility", 0, 0 }, + { LPGENW("Show contact statuses if protocol supports them"), "ShowContactStatus", 0, 0 }, + { LPGENW("Display contact status icon before user role icon"), "ContactStatusFirst", 0, 0 }, +}; + +static const struct branch_t branch2[] = { + { LPGENW("Prefix all events with a timestamp"), "ShowTimeStamp", 0, 1 }, + { LPGENW("Only prefix with timestamp if it has changed"), "ShowTimeStampIfChanged", 0, 0 }, + { LPGENW("Timestamp has same color as the event"), "TimeStampEventColour", 0, 0 }, + { LPGENW("Indent the second line of a message"), "LogIndentEnabled", 0, 1 }, + { LPGENW("Limit user names in the message log to 20 characters"), "LogLimitNames", 0, 1 }, + { LPGENW("Add ':' to auto-completed user names"), "AddColonToAutoComplete", 0, 1 }, + { LPGENW("Strip colors from messages in the log"), "StripFormatting", 0, 0 }, + { LPGENW("Enable the 'event filter' for new rooms"), "FilterEnabled", 0, 0 } +}; + +static const struct branch_t branch3[] = { + { LPGENW("Show topic changes"), "FilterFlags", GC_EVENT_TOPIC, 0 }, + { LPGENW("Show users joining"), "FilterFlags", GC_EVENT_JOIN, 0 }, + { LPGENW("Show users disconnecting"), "FilterFlags", GC_EVENT_QUIT, 0 }, + { LPGENW("Show messages"), "FilterFlags", GC_EVENT_MESSAGE, 1 }, + { LPGENW("Show actions"), "FilterFlags", GC_EVENT_ACTION, 1 }, + { LPGENW("Show users leaving"), "FilterFlags", GC_EVENT_PART, 0 }, + { LPGENW("Show users being kicked"), "FilterFlags", GC_EVENT_KICK, 1 }, + { LPGENW("Show notices"), "FilterFlags", GC_EVENT_NOTICE, 1 }, + { LPGENW("Show users changing name"), "FilterFlags", GC_EVENT_NICK, 0 }, + { LPGENW("Show information messages"), "FilterFlags", GC_EVENT_INFORMATION, 1 }, + { LPGENW("Show status changes of users"), "FilterFlags", GC_EVENT_ADDSTATUS, 0 }, +}; + +static const struct branch_t branch4[] = { + { LPGENW("Show icon for topic changes"), "IconFlags", GC_EVENT_TOPIC, 0 }, + { LPGENW("Show icon for users joining"), "IconFlags", GC_EVENT_JOIN, 1 }, + { LPGENW("Show icon for users disconnecting"), "IconFlags", GC_EVENT_QUIT, 0 }, + { LPGENW("Show icon for messages"), "IconFlags", GC_EVENT_MESSAGE, 0 }, + { LPGENW("Show icon for actions"), "IconFlags", GC_EVENT_ACTION, 0 }, + { LPGENW("Show icon for highlights"), "IconFlags", GC_EVENT_HIGHLIGHT, 0 }, + { LPGENW("Show icon for users leaving"), "IconFlags", GC_EVENT_PART, 0 }, + { LPGENW("Show icon for users kicking other user"), "IconFlags", GC_EVENT_KICK, 0 }, + { LPGENW("Show icon for notices"), "IconFlags", GC_EVENT_NOTICE, 0 }, + { LPGENW("Show icon for name changes"), "IconFlags", GC_EVENT_NICK, 0 }, + { LPGENW("Show icon for information messages"), "IconFlags", GC_EVENT_INFORMATION, 0 }, + { LPGENW("Show icon for status changes"), "IconFlags", GC_EVENT_ADDSTATUS, 0 }, +}; + +static const struct branch_t branch5[] = { + { LPGENW("Show icons in tray only when the chat room is not active"), "TrayIconInactiveOnly", 0, 1 }, + { LPGENW("Show icon in tray for topic changes"), "TrayIconFlags", GC_EVENT_TOPIC, 0 }, + { LPGENW("Show icon in tray for users joining"), "TrayIconFlags", GC_EVENT_JOIN, 0 }, + { LPGENW("Show icon in tray for users disconnecting"), "TrayIconFlags", GC_EVENT_QUIT, 0 }, + { LPGENW("Show icon in tray for messages"), "TrayIconFlags", GC_EVENT_MESSAGE, 0 }, + { LPGENW("Show icon in tray for actions"), "TrayIconFlags", GC_EVENT_ACTION, 0 }, + { LPGENW("Show icon in tray for highlights"), "TrayIconFlags", GC_EVENT_HIGHLIGHT, 1 }, + { LPGENW("Show icon in tray for users leaving"), "TrayIconFlags", GC_EVENT_PART, 0 }, + { LPGENW("Show icon in tray for users kicking other user"), "TrayIconFlags", GC_EVENT_KICK, 0 }, + { LPGENW("Show icon in tray for notices"), "TrayIconFlags", GC_EVENT_NOTICE, 0 }, + { LPGENW("Show icon in tray for name changes"), "TrayIconFlags", GC_EVENT_NICK, 0 }, + { LPGENW("Show icon in tray for information messages"), "TrayIconFlags", GC_EVENT_INFORMATION, 0 }, + { LPGENW("Show icon in tray for status changes"), "TrayIconFlags", GC_EVENT_ADDSTATUS, 0 }, +}; + +static const struct branch_t branch6[] = { + { LPGENW("Show popups only when the chat room is not active"), "PopupInactiveOnly", 0, 1 }, + { LPGENW("Show popup for topic changes"), "PopupFlags", GC_EVENT_TOPIC, 0 }, + { LPGENW("Show popup for users joining"), "PopupFlags", GC_EVENT_JOIN, 0 }, + { LPGENW("Show popup for users disconnecting"), "PopupFlags", GC_EVENT_QUIT, 0 }, + { LPGENW("Show popup for messages"), "PopupFlags", GC_EVENT_MESSAGE, 0 }, + { LPGENW("Show popup for actions"), "PopupFlags", GC_EVENT_ACTION, 0 }, + { LPGENW("Show popup for highlights"), "PopupFlags", GC_EVENT_HIGHLIGHT, 0 }, + { LPGENW("Show popup for users leaving"), "PopupFlags", GC_EVENT_PART, 0 }, + { LPGENW("Show popup for users kicking other user"), "PopupFlags", GC_EVENT_KICK, 0 }, + { LPGENW("Show popup for notices"), "PopupFlags", GC_EVENT_NOTICE, 0 }, + { LPGENW("Show popup for name changes"), "PopupFlags", GC_EVENT_NICK, 0 }, + { LPGENW("Show popup for information messages"), "PopupFlags", GC_EVENT_INFORMATION, 0 }, + { LPGENW("Show popup for status changes"), "PopupFlags", GC_EVENT_ADDSTATUS, 0 }, +}; + +HTREEITEM hItemB0[_countof(branch0)]; +HTREEITEM hItemB1[_countof(branch1)]; +HTREEITEM hItemB2[_countof(branch2)]; +HTREEITEM hItemB3[_countof(branch3)]; +HTREEITEM hItemB4[_countof(branch4)]; +HTREEITEM hItemB5[_countof(branch5)]; +HTREEITEM hItemB6[_countof(branch6)]; + +static HTREEITEM InsertBranch(HWND hwndTree, char* pszDescr, BOOL bExpanded) +{ + TVINSERTSTRUCT tvis = { 0 }; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_STATE; + tvis.item.pszText = Langpack_PcharToTchar(pszDescr); + tvis.item.stateMask = bExpanded ? TVIS_STATEIMAGEMASK | TVIS_EXPANDED : TVIS_STATEIMAGEMASK; + tvis.item.state = bExpanded ? INDEXTOSTATEIMAGEMASK(1) | TVIS_EXPANDED : INDEXTOSTATEIMAGEMASK(1); + HTREEITEM res = TreeView_InsertItem(hwndTree, &tvis); + mir_free(tvis.item.pszText); + return res; +} + +static void FillBranch(HWND hwndTree, HTREEITEM hParent, const struct branch_t *branch, HTREEITEM *hItemB, int nValues, DWORD defaultval) +{ + int iState; + + if (hParent == 0) + return; + + TVINSERTSTRUCT tvis; + tvis.hParent = hParent; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_STATE; + for (int i = 0; i < nValues; i++) { + tvis.item.pszText = TranslateW(branch[i].szDescr); + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + if (branch[i].iMode) + iState = ((db_get_dw(NULL, CHAT_MODULE, branch[i].szDBName, defaultval)&branch[i].iMode)&branch[i].iMode) != 0 ? 2 : 1; + else + iState = db_get_b(NULL, CHAT_MODULE, branch[i].szDBName, branch[i].bDefault) != 0 ? 2 : 1; + tvis.item.state = INDEXTOSTATEIMAGEMASK(iState); + hItemB[i] = TreeView_InsertItem(hwndTree, &tvis); + } +} + +static void SaveBranch(HWND hwndTree, const struct branch_t *branch, HTREEITEM *hItemB, int nValues) +{ + int iState = 0; + + TVITEM tvi; + tvi.mask = TVIF_HANDLE | TVIF_STATE; + for (int i = 0; i < nValues; i++) { + tvi.hItem = hItemB[i]; + TreeView_GetItem(hwndTree, &tvi); + BYTE bChecked = (((tvi.state & TVIS_STATEIMAGEMASK) >> 12) == 1) ? 0 : 1; + if (branch[i].iMode) { + if (bChecked) + iState |= branch[i].iMode; + if (iState & GC_EVENT_ADDSTATUS) + iState |= GC_EVENT_REMOVESTATUS; + db_set_dw(NULL, CHAT_MODULE, branch[i].szDBName, (DWORD)iState); + } + else db_set_b(NULL, CHAT_MODULE, branch[i].szDBName, bChecked); + } +} + +static void CheckHeading(HWND hwndTree, HTREEITEM hHeading) +{ + BOOL bChecked = TRUE; + + if (hHeading == 0) + return; + + TVITEM tvi; + tvi.mask = TVIF_HANDLE | TVIF_STATE; + tvi.hItem = TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD); + while (tvi.hItem && bChecked) { + if (tvi.hItem != hItemB1[0] && tvi.hItem != hItemB1[1]) { + TreeView_GetItem(hwndTree, &tvi); + if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 1)) + bChecked = FALSE; + } + tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); + } + tvi.stateMask = TVIS_STATEIMAGEMASK; + tvi.state = INDEXTOSTATEIMAGEMASK(bChecked ? 2 : 1); + tvi.hItem = hHeading; + TreeView_SetItem(hwndTree, &tvi); +} + +static void CheckBranches(HWND hwndTree, HTREEITEM hHeading) +{ + BOOL bChecked = TRUE; + + if (hHeading == 0) + return; + + TVITEM tvi; + tvi.mask = TVIF_HANDLE | TVIF_STATE; + tvi.hItem = hHeading; + TreeView_GetItem(hwndTree, &tvi); + if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2)) + bChecked = FALSE; + tvi.hItem = TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD); + tvi.stateMask = TVIS_STATEIMAGEMASK; + while (tvi.hItem) { + tvi.state = INDEXTOSTATEIMAGEMASK(bChecked ? 2 : 1); + if (tvi.hItem != hItemB1[0] && tvi.hItem != hItemB1[1]) + TreeView_SetItem(hwndTree, &tvi); + tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); + } +} + +static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData) +{ + wchar_t szDir[MAX_PATH]; + switch (uMsg) { + case BFFM_INITIALIZED: + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData); + break; + + case BFFM_SELCHANGED: + if (SHGetPathFromIDList((LPITEMIDLIST)lp, szDir)) + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir); + break; + } + return 0; +} + +// add icons to the skinning module + +static IconItem iconList[] = +{ + { LPGEN("Window icon"), "chat_window", IDI_CHANMGR, 0 }, + { LPGEN("Text color"), "chat_fgcol", IDI_COLOR, 0 }, + { LPGEN("Background color"), "chat_bkgcol", IDI_BKGCOLOR, 0 }, + { LPGEN("Bold"), "chat_bold", IDI_BBOLD, 0 }, + { LPGEN("Italics"), "chat_italics", IDI_BITALICS, 0 }, + { LPGEN("Underlined"), "chat_underline", IDI_BUNDERLINE, 0 }, + { LPGEN("Smiley button"), "chat_smiley", IDI_BSMILEY, 0 }, + { LPGEN("Room history"), "chat_history", IDI_HISTORY, 0 }, + { LPGEN("Room settings"), "chat_settings", IDI_TOPICBUT, 0 }, + { LPGEN("Event filter disabled"), "chat_filter", IDI_FILTER, 0 }, + { LPGEN("Event filter enabled"), "chat_filter2", IDI_FILTER2, 0 }, + { LPGEN("Hide nick list"), "chat_nicklist", IDI_NICKLIST, 0 }, + { LPGEN("Show nick list"), "chat_nicklist2", IDI_NICKLIST2, 0 }, + { LPGEN("Icon overlay"), "chat_overlay", IDI_OVERLAY, 0 }, + { LPGEN("Close"), "chat_close", IDI_CLOSE, 0 }, + + { LPGEN("Status 1 (10x10)"), "chat_status0", IDI_STATUS0, 10 }, + { LPGEN("Status 2 (10x10)"), "chat_status1", IDI_STATUS1, 10 }, + { LPGEN("Status 3 (10x10)"), "chat_status2", IDI_STATUS2, 10 }, + { LPGEN("Status 4 (10x10)"), "chat_status3", IDI_STATUS3, 10 }, + { LPGEN("Status 5 (10x10)"), "chat_status4", IDI_STATUS4, 10 }, + { LPGEN("Status 6 (10x10)"), "chat_status5", IDI_STATUS5, 10 }, + + { LPGEN("Message in (10x10)"), "chat_log_message_in", IDI_MESSAGE, 10 }, + { LPGEN("Message out (10x10)"), "chat_log_message_out", IDI_MESSAGEOUT, 10 }, + { LPGEN("Action (10x10)"), "chat_log_action", IDI_ACTION, 10 }, + { LPGEN("Add status (10x10)"), "chat_log_addstatus", IDI_ADDSTATUS, 10 }, + { LPGEN("Remove status (10x10)"), "chat_log_removestatus", IDI_REMSTATUS, 10 }, + { LPGEN("Join (10x10)"), "chat_log_join", IDI_JOIN, 10 }, + { LPGEN("Leave (10x10)"), "chat_log_part", IDI_PART, 10 }, + { LPGEN("Quit (10x10)"), "chat_log_quit", IDI_QUIT, 10 }, + { LPGEN("Kick (10x10)"), "chat_log_kick", IDI_KICK, 10 }, + { LPGEN("Nick change (10x10)"), "chat_log_nick", IDI_NICK, 10 }, + { LPGEN("Notice (10x10)"), "chat_log_notice", IDI_NOTICE, 10 }, + { LPGEN("Topic (10x10)"), "chat_log_topic", IDI_TOPIC, 10 }, + { LPGEN("Highlight (10x10)"), "chat_log_highlight", IDI_HIGHLIGHT, 10 }, + { LPGEN("Information (10x10)"), "chat_log_info", IDI_INFO, 10 } +}; + +void AddIcons(void) +{ + Icon_Register(g_hInst, LPGEN("Messaging") "/" LPGEN("Group chats"), iconList, 21); + Icon_Register(g_hInst, LPGEN("Messaging") "/" LPGEN("Group chats log"), iconList + 21, 14); +} + +// load icons from the skinning module if available +HICON LoadIconEx(const char *pszIcoLibName, bool big) +{ + char szTemp[256]; + mir_snprintf(szTemp, "chat_%s", pszIcoLibName); + return IcoLib_GetIcon(szTemp, big); +} + +HANDLE GetIconHandle(const char *pszIcoLibName) +{ + char szTemp[256]; + mir_snprintf(szTemp, "chat_%s", pszIcoLibName); + return IcoLib_GetIconHandle(szTemp); +} + +static void InitSetting(wchar_t** ppPointer, char* pszSetting, wchar_t* pszDefault) +{ + DBVARIANT dbv; + if (!db_get_ws(NULL, CHAT_MODULE, pszSetting, &dbv)) { + replaceStrW(*ppPointer, dbv.ptszVal); + db_free(&dbv); + } + else replaceStrW(*ppPointer, pszDefault); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// General options + +#define OPT_FIXHEADINGS (WM_USER+1) + +static HTREEITEM hListHeading0, hListHeading1, hListHeading2, hListHeading3, hListHeading4, hListHeading5, hListHeading6; + +static INT_PTR CALLBACK DlgProcOptions1(HWND hwndDlg, UINT uMsg, WPARAM, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); + hListHeading0 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Options for using a tabbed interface"), db_get_b(NULL, CHAT_MODULE, "Branch0Exp", 0) ? TRUE : FALSE); + hListHeading1 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Appearance and functionality of chat room windows"), db_get_b(NULL, CHAT_MODULE, "Branch1Exp", 0) ? TRUE : FALSE); + hListHeading2 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Appearance of the message log"), db_get_b(NULL, CHAT_MODULE, "Branch2Exp", 0) ? TRUE : FALSE); + hListHeading3 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Default events to show in new chat rooms if the 'event filter' is enabled"), db_get_b(NULL, CHAT_MODULE, "Branch3Exp", 0) ? TRUE : FALSE); + hListHeading4 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Icons to display in the message log"), db_get_b(NULL, CHAT_MODULE, "Branch4Exp", 0) ? TRUE : FALSE); + hListHeading5 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Icons to display in the tray"), db_get_b(NULL, CHAT_MODULE, "Branch5Exp", 0) ? TRUE : FALSE); + if (PopupInstalled) + hListHeading6 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), LPGEN("Popups to display"), db_get_b(NULL, CHAT_MODULE, "Branch6Exp", 0) ? TRUE : FALSE); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading0, branch0, hItemB0, _countof(branch0), 0); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, branch1, hItemB1, _countof(branch1), 0); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, branch2, hItemB2, _countof(branch2), 0); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading3, branch3, hItemB3, _countof(branch3), 0x03E0); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading4, branch4, hItemB4, _countof(branch4), 0x0000); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading5, branch5, hItemB5, _countof(branch5), 0x1000); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading6, branch6, hItemB6, _countof(branch6), 0x0000); + SendMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0); + break; + + case OPT_FIXHEADINGS: + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading3); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading4); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading5); + CheckHeading(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading6); + break; + + case WM_COMMAND: + if (lParam != 0) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->idFrom) { + case IDC_CHECKBOXES: + if (((LPNMHDR)lParam)->code == NM_CLICK) { + TVHITTESTINFO hti; + hti.pt.x = (short)LOWORD(GetMessagePos()); + hti.pt.y = (short)HIWORD(GetMessagePos()); + ScreenToClient(((LPNMHDR)lParam)->hwndFrom, &hti.pt); + if (TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom, &hti)) { + if (hti.flags & TVHT_ONITEMSTATEICON) { + TVITEM tvi = { 0 }; + tvi.mask = TVIF_HANDLE | TVIF_STATE; + tvi.hItem = hti.hItem; + TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &tvi); + if (tvi.hItem == hItemB1[0] && INDEXTOSTATEIMAGEMASK(1) == tvi.state) + TreeView_SetItemState(((LPNMHDR)lParam)->hwndFrom, hItemB1[1], INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK); + if (tvi.hItem == hItemB1[1] && INDEXTOSTATEIMAGEMASK(1) == tvi.state) + TreeView_SetItemState(((LPNMHDR)lParam)->hwndFrom, hItemB1[0], INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK); + + if (tvi.hItem == hListHeading0) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading0); + else if (tvi.hItem == hListHeading1) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1); + else if (tvi.hItem == hListHeading2) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2); + else if (tvi.hItem == hListHeading3) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading3); + else if (tvi.hItem == hListHeading4) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading4); + else if (tvi.hItem == hListHeading5) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading5); + else if (tvi.hItem == hListHeading6) + CheckBranches(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading6); + else + PostMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + } + break; + + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + BYTE b = db_get_b(NULL, CHAT_MODULE, "Tabs", 1); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch0, hItemB0, _countof(branch0)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch1, hItemB1, _countof(branch1)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch2, hItemB2, _countof(branch2)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch3, hItemB3, _countof(branch3)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch4, hItemB4, _countof(branch4)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch5, hItemB5, _countof(branch5)); + if (PopupInstalled) + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch6, hItemB6, _countof(branch6)); + g_Settings.dwIconFlags = db_get_dw(NULL, CHAT_MODULE, "IconFlags", 0x0000); + g_Settings.dwTrayIconFlags = db_get_dw(NULL, CHAT_MODULE, "TrayIconFlags", 0x1000); + g_Settings.dwPopupFlags = db_get_dw(NULL, CHAT_MODULE, "PopupFlags", 0x0000); + g_Settings.bStripFormat = db_get_b(NULL, CHAT_MODULE, "TrimFormatting", 0) != 0; + g_Settings.bTrayIconInactiveOnly = db_get_b(NULL, CHAT_MODULE, "TrayIconInactiveOnly", 1) != 0; + g_Settings.bPopupInactiveOnly = db_get_b(NULL, CHAT_MODULE, "PopupInactiveOnly", 1) != 0; + g_Settings.bLogIndentEnabled = db_get_b(NULL, CHAT_MODULE, "LogIndentEnabled", 1) != 0; + + if (b != db_get_b(NULL, CHAT_MODULE, "Tabs", 1)) { + pci->SM_BroadcastMessage(NULL, GC_CLOSEWINDOW, 0, 1, FALSE); + g_Settings.bTabsEnable = db_get_b(NULL, CHAT_MODULE, "Tabs", 1) != 0; + } + else pci->SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); + + return TRUE; + } + } + break; + + case WM_DESTROY: + BYTE b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, TVIS_EXPANDED)&TVIS_EXPANDED ? 1 : 0; + db_set_b(NULL, CHAT_MODULE, "Branch1Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, TVIS_EXPANDED)&TVIS_EXPANDED ? 1 : 0; + db_set_b(NULL, CHAT_MODULE, "Branch2Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading3, TVIS_EXPANDED)&TVIS_EXPANDED ? 1 : 0; + db_set_b(NULL, CHAT_MODULE, "Branch3Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading4, TVIS_EXPANDED)&TVIS_EXPANDED ? 1 : 0; + db_set_b(NULL, CHAT_MODULE, "Branch4Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading5, TVIS_EXPANDED)&TVIS_EXPANDED ? 1 : 0; + db_set_b(NULL, CHAT_MODULE, "Branch5Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading0, TVIS_EXPANDED)&TVIS_EXPANDED ? 1 : 0; + db_set_b(NULL, CHAT_MODULE, "Branch0Exp", b); + if (PopupInstalled) { + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading6, TVIS_EXPANDED)&TVIS_EXPANDED ? 1 : 0; + db_set_b(NULL, CHAT_MODULE, "Branch6Exp", b); + } + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Log & other options + +static INT_PTR CALLBACK DlgProcOptions2(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SendDlgItemMessage(hwndDlg, IDC_SPIN2, UDM_SETRANGE, 0, MAKELONG(5000, 0)); + SendDlgItemMessage(hwndDlg, IDC_SPIN2, UDM_SETPOS, 0, MAKELONG(db_get_w(NULL, CHAT_MODULE, "LogLimit", 100), 0)); + SendDlgItemMessage(hwndDlg, IDC_SPIN3, UDM_SETRANGE, 0, MAKELONG(10000, 0)); + SendDlgItemMessage(hwndDlg, IDC_SPIN3, UDM_SETPOS, 0, MAKELONG(db_get_w(NULL, CHAT_MODULE, "LoggingLimit", 100), 0)); + SendDlgItemMessage(hwndDlg, IDC_SPIN4, UDM_SETRANGE, 0, MAKELONG(255, 10)); + SendDlgItemMessage(hwndDlg, IDC_SPIN4, UDM_SETPOS, 0, MAKELONG(db_get_b(NULL, CHAT_MODULE, "NicklistRowDist", 12), 0)); + { + wchar_t* pszGroup = NULL; + InitSetting(&pszGroup, "AddToGroup", L"Chat rooms"); + SetDlgItemText(hwndDlg, IDC_GROUP, pszGroup); + mir_free(pszGroup); + } + { + wchar_t szTemp[MAX_PATH]; + PathToRelativeT(g_Settings.pszLogDir, szTemp); + SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, szTemp); + } + SetDlgItemText(hwndDlg, IDC_HIGHLIGHTWORDS, g_Settings.pszHighlightWords); + SetDlgItemText(hwndDlg, IDC_LOGTIMESTAMP, g_Settings.pszTimeStampLog); + SetDlgItemText(hwndDlg, IDC_TIMESTAMP, g_Settings.pszTimeStamp); + SetDlgItemText(hwndDlg, IDC_OUTSTAMP, g_Settings.pszOutgoingNick); + SetDlgItemText(hwndDlg, IDC_INSTAMP, g_Settings.pszIncomingNick); + CheckDlgButton(hwndDlg, IDC_HIGHLIGHT, g_Settings.bHighlightEnabled ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIGHLIGHTWORDS), g_Settings.bHighlightEnabled ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_LOGGING, g_Settings.bLoggingEnabled ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), g_Settings.bLoggingEnabled ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FONTCHOOSE), g_Settings.bLoggingEnabled ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), g_Settings.bLoggingEnabled ? TRUE : FALSE); + break; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_INSTAMP + || LOWORD(wParam) == IDC_OUTSTAMP + || LOWORD(wParam) == IDC_TIMESTAMP + || LOWORD(wParam) == IDC_LOGLIMIT + || LOWORD(wParam) == IDC_HIGHLIGHTWORDS + || LOWORD(wParam) == IDC_LOGDIRECTORY + || LOWORD(wParam) == IDC_LOGTIMESTAMP + || LOWORD(wParam) == IDC_NICKROW2 + || LOWORD(wParam) == IDC_GROUP + || LOWORD(wParam) == IDC_LIMIT) + && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0; + + switch (LOWORD(wParam)) { + case IDC_LOGGING: + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FONTCHOOSE), IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); + break; + + case IDC_FONTCHOOSE: + { + wchar_t szDirectory[MAX_PATH]; + wchar_t szTemp[MAX_PATH]; + + BROWSEINFO bi = { 0 }; + bi.hwndOwner = hwndDlg; + bi.pszDisplayName = szDirectory; + bi.lpszTitle = TranslateT("Select folder"); + bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_RETURNONLYFSDIRS; + bi.lpfn = BrowseCallbackProc; + bi.lParam = (LPARAM)szDirectory; + LPITEMIDLIST idList = SHBrowseForFolder(&bi); + if (idList) { + SHGetPathFromIDList(idList, szDirectory); + mir_wstrcat(szDirectory, L"\\"); + PathToRelativeT(szDirectory, szTemp); + SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, mir_wstrlen(szTemp) > 1 ? szTemp : L"Logs\\"); + CoTaskMemFree(idList); + } + } + break; + + case IDC_HIGHLIGHT: + EnableWindow(GetDlgItem(hwndDlg, IDC_HIGHLIGHTWORDS), IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHT) == BST_CHECKED ? TRUE : FALSE); + break; + } + + if (lParam != 0) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) { + wchar_t * pszText = NULL; + int iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_HIGHLIGHTWORDS)); + if (iLen > 0) { + wchar_t *ptszText = (wchar_t *)mir_alloc((iLen + 2) * sizeof(wchar_t)); + wchar_t *p2 = NULL; + + if (ptszText) { + GetDlgItemText(hwndDlg, IDC_HIGHLIGHTWORDS, ptszText, iLen + 1); + p2 = wcschr(ptszText, ','); + while (p2) { + *p2 = ' '; + p2 = wcschr(ptszText, ','); + } + db_set_ws(NULL, CHAT_MODULE, "HighlightWords", ptszText); + mir_free(ptszText); + } + } + else db_unset(NULL, CHAT_MODULE, "HighlightWords"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY)); + if (iLen > 0) { + pszText = (wchar_t *)mir_realloc(pszText, (iLen + 1) * sizeof(wchar_t)); + GetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, pszText, iLen + 1); + db_set_ws(NULL, CHAT_MODULE, "LogDirectory", pszText); + } + else db_unset(NULL, CHAT_MODULE, "LogDirectory"); + pci->SM_InvalidateLogDirectories(); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGTIMESTAMP)); + if (iLen > 0) { + pszText = (wchar_t *)mir_realloc(pszText, (iLen + 1) * sizeof(wchar_t)); + GetDlgItemText(hwndDlg, IDC_LOGTIMESTAMP, pszText, iLen + 1); + db_set_ws(NULL, CHAT_MODULE, "LogTimestamp", pszText); + } + else db_unset(NULL, CHAT_MODULE, "LogTimestamp"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_TIMESTAMP)); + if (iLen > 0) { + pszText = (wchar_t *)mir_realloc(pszText, (iLen + 1) * sizeof(wchar_t)); + GetDlgItemText(hwndDlg, IDC_TIMESTAMP, pszText, iLen + 1); + db_set_ws(NULL, CHAT_MODULE, "HeaderTime", pszText); + } + else db_unset(NULL, CHAT_MODULE, "HeaderTime"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_INSTAMP)); + if (iLen > 0) { + pszText = (wchar_t *)mir_realloc(pszText, (iLen + 1) * sizeof(wchar_t)); + GetDlgItemText(hwndDlg, IDC_INSTAMP, pszText, iLen + 1); + db_set_ws(NULL, CHAT_MODULE, "HeaderIncoming", pszText); + } + else db_unset(NULL, CHAT_MODULE, "HeaderIncoming"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_OUTSTAMP)); + if (iLen > 0) { + pszText = (wchar_t *)mir_realloc(pszText, (iLen + 1) * sizeof(wchar_t)); + GetDlgItemText(hwndDlg, IDC_OUTSTAMP, pszText, iLen + 1); + db_set_ws(NULL, CHAT_MODULE, "HeaderOutgoing", pszText); + } + else db_unset(NULL, CHAT_MODULE, "HeaderOutgoing"); + + g_Settings.bHighlightEnabled = IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHT) == BST_CHECKED; + db_set_b(NULL, CHAT_MODULE, "HighlightEnabled", g_Settings.bHighlightEnabled); + + g_Settings.bLoggingEnabled = IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED; + db_set_b(NULL, CHAT_MODULE, "LoggingEnabled", g_Settings.bLoggingEnabled); + + iLen = SendDlgItemMessage(hwndDlg, IDC_SPIN2, UDM_GETPOS, 0, 0); + db_set_w(NULL, CHAT_MODULE, "LogLimit", (WORD)iLen); + iLen = SendDlgItemMessage(hwndDlg, IDC_SPIN3, UDM_GETPOS, 0, 0); + db_set_w(NULL, CHAT_MODULE, "LoggingLimit", (WORD)iLen); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_GROUP)); + if (iLen > 0) { + pszText = (wchar_t *)mir_realloc(pszText, (iLen + 1) * sizeof(wchar_t)); + GetDlgItemText(hwndDlg, IDC_GROUP, pszText, iLen + 1); + db_set_ws(NULL, CHAT_MODULE, "AddToGroup", pszText); + } + else db_set_s(NULL, CHAT_MODULE, "AddToGroup", ""); + mir_free(pszText); + + iLen = SendDlgItemMessage(hwndDlg, IDC_SPIN4, UDM_GETPOS, 0, 0); + if (iLen > 0) + db_set_b(NULL, CHAT_MODULE, "NicklistRowDist", (BYTE)iLen); + else + db_unset(NULL, CHAT_MODULE, "NicklistRowDist"); + + pci->ReloadSettings(); + pci->SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); + return TRUE; + } + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Popup options + +static INT_PTR CALLBACK DlgProcOptionsPopup(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + SendDlgItemMessage(hwndDlg, IDC_BKG, CPM_SETCOLOUR, 0, g_Settings.crPUBkgColour); + SendDlgItemMessage(hwndDlg, IDC_TEXT, CPM_SETCOLOUR, 0, g_Settings.crPUTextColour); + + if (g_Settings.iPopupStyle == 2) + CheckDlgButton(hwndDlg, IDC_RADIO2, BST_CHECKED); + else if (g_Settings.iPopupStyle == 3) + CheckDlgButton(hwndDlg, IDC_RADIO3, BST_CHECKED); + else + CheckDlgButton(hwndDlg, IDC_RADIO1, BST_CHECKED); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG), IsDlgButtonChecked(hwndDlg, IDC_RADIO3) == BST_CHECKED ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT), IsDlgButtonChecked(hwndDlg, IDC_RADIO3) == BST_CHECKED ? TRUE : FALSE); + + SendDlgItemMessage(hwndDlg, IDC_SPIN1, UDM_SETRANGE, 0, MAKELONG(100, -1)); + SendDlgItemMessage(hwndDlg, IDC_SPIN1, UDM_SETPOS, 0, MAKELONG(g_Settings.iPopupTimeout, 0)); + break; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_TIMEOUT) && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) + return 0; + + if (lParam != 0) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + switch (LOWORD(wParam)) { + + case IDC_RADIO1: + case IDC_RADIO2: + case IDC_RADIO3: + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG), IsDlgButtonChecked(hwndDlg, IDC_RADIO3) == BST_CHECKED ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT), IsDlgButtonChecked(hwndDlg, IDC_RADIO3) == BST_CHECKED ? TRUE : FALSE); + break; + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) { + int iLen; + + if (IsDlgButtonChecked(hwndDlg, IDC_RADIO2) == BST_CHECKED) + iLen = 2; + else if (IsDlgButtonChecked(hwndDlg, IDC_RADIO3) == BST_CHECKED) + iLen = 3; + else + iLen = 1; + + g_Settings.iPopupStyle = iLen; + db_set_b(NULL, CHAT_MODULE, "PopupStyle", (BYTE)iLen); + + iLen = SendDlgItemMessage(hwndDlg, IDC_SPIN1, UDM_GETPOS, 0, 0); + g_Settings.iPopupTimeout = iLen; + db_set_w(NULL, CHAT_MODULE, "PopupTimeout", (WORD)iLen); + + g_Settings.crPUBkgColour = SendDlgItemMessage(hwndDlg, IDC_BKG, CPM_GETCOLOUR, 0, 0); + db_set_dw(NULL, CHAT_MODULE, "PopupColorBG", (DWORD)SendDlgItemMessage(hwndDlg, IDC_BKG, CPM_GETCOLOUR, 0, 0)); + g_Settings.crPUTextColour = SendDlgItemMessage(hwndDlg, IDC_TEXT, CPM_GETCOLOUR, 0, 0); + db_set_dw(NULL, CHAT_MODULE, "PopupColorText", (DWORD)SendDlgItemMessage(hwndDlg, IDC_TEXT, CPM_GETCOLOUR, 0, 0)); + return TRUE; + } + break; + } + return FALSE; +} + +int OptionsInitialize(WPARAM wParam, LPARAM) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.position = 910000000; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS1); + odp.szGroup.a = LPGEN("Message sessions"); + odp.szTitle.a = LPGEN("Group chats"); + odp.szTab.a = LPGEN("General"); + odp.pfnDlgProc = DlgProcOptions1; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + + odp.position = 910000001; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS2); + odp.szTab.a = LPGEN("Chat log"); + odp.pfnDlgProc = DlgProcOptions2; + Options_AddPage(wParam, &odp); + + if (PopupInstalled) { + odp.position = 910000002; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONSPOPUP); + odp.szTitle.a = LPGEN(CHAT_MODULE); + odp.szGroup.a = LPGEN("Popups"); + odp.szTab.a = NULL; + odp.pfnDlgProc = DlgProcOptionsPopup; + Options_AddPage(wParam, &odp); + } + return 0; +} diff --git a/src/core/stdmsg/src/chat_util.cpp b/src/core/stdmsg/src/chat_util.cpp new file mode 100644 index 0000000000..73e0751bc7 --- /dev/null +++ b/src/core/stdmsg/src/chat_util.cpp @@ -0,0 +1,482 @@ +/* + +Copyright 2000-12 Miranda IM, 2012-16 Miranda NG project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + + +// The code for streaming the text is to a large extent copied from +// the srmm module and then modified to fit the chat module. + +static DWORD CALLBACK Log_StreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + LOGSTREAMDATA *lstrdat = (LOGSTREAMDATA *) dwCookie; + if (lstrdat) { + // create the RTF + if (lstrdat->buffer == NULL) { + lstrdat->bufferOffset = 0; + lstrdat->buffer = pci->Log_CreateRTF(lstrdat); + lstrdat->bufferLen = (int)mir_strlen(lstrdat->buffer); + } + + // give the RTF to the RE control + *pcb = min(cb, lstrdat->bufferLen - lstrdat->bufferOffset); + memcpy(pbBuff, lstrdat->buffer + lstrdat->bufferOffset, *pcb); + lstrdat->bufferOffset += *pcb; + + // free stuff if the streaming operation is complete + if (lstrdat->bufferOffset == lstrdat->bufferLen) { + mir_free(lstrdat->buffer); + lstrdat->buffer = NULL; + } + } + + return 0; +} + +void Log_StreamInEvent(HWND hwndDlg, LOGINFO* lin, SESSION_INFO *si, BOOL bRedraw, BOOL) +{ + CHARRANGE oldsel, sel, newsel; + POINT point ={0}; + WPARAM wp; + + if (hwndDlg == 0 || lin == 0 || si == 0) + return; + + if (!bRedraw && si->iType == GCW_CHATROOM && si->bFilterEnabled && (si->iLogFilterFlags & lin->iType) == 0) + return; + + HWND hwndRich = GetDlgItem(hwndDlg, IDC_LOG); + + LOGSTREAMDATA streamData; + memset(&streamData, 0, sizeof(streamData)); + streamData.hwnd = hwndRich; + streamData.si = si; + streamData.lin = lin; + streamData.bStripFormat = FALSE; + + BOOL bFlag = FALSE; + + EDITSTREAM stream = { 0 }; + stream.pfnCallback = Log_StreamCallback; + stream.dwCookie = (DWORD_PTR) & streamData; + + SCROLLINFO scroll; + scroll.cbSize = sizeof(SCROLLINFO); + scroll.fMask= SIF_RANGE | SIF_POS|SIF_PAGE; + GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &scroll); + SendMessage(hwndRich, EM_GETSCROLLPOS, 0, (LPARAM) &point); + + // do not scroll to bottom if there is a selection + SendMessage(hwndRich, EM_EXGETSEL, 0, (LPARAM) &oldsel); + if (oldsel.cpMax != oldsel.cpMin) + SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0); + + //set the insertion point at the bottom + sel.cpMin = sel.cpMax = GetRichTextLength(hwndRich); + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM) &sel); + + // fix for the indent... must be a M$ bug + if (sel.cpMax == 0) + bRedraw = TRUE; + + // should the event(s) be appended to the current log + wp = bRedraw?SF_RTF:SFF_SELECTION|SF_RTF; + + //get the number of pixels per logical inch + if (bRedraw) { + HDC hdc = GetDC(NULL); + pci->logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + pci->logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(NULL, hdc); + SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0); + bFlag = TRUE; + } + + // stream in the event(s) + streamData.lin = lin; + streamData.bRedraw = bRedraw; + SendMessage(hwndRich, EM_STREAMIN, wp, (LPARAM) & stream); + + // do smileys + if (SmileyAddInstalled && (bRedraw + || (lin->ptszText + && lin->iType != GC_EVENT_JOIN + && lin->iType != GC_EVENT_NICK + && lin->iType != GC_EVENT_ADDSTATUS + && lin->iType != GC_EVENT_REMOVESTATUS ))) + { + SMADD_RICHEDIT3 sm = {0}; + + newsel.cpMax = -1; + newsel.cpMin = sel.cpMin; + if (newsel.cpMin < 0) + newsel.cpMin = 0; + memset(&sm, 0, sizeof(sm)); + sm.cbSize = sizeof(sm); + sm.hwndRichEditControl = hwndRich; + sm.Protocolname = si->pszModule; + sm.rangeToReplace = bRedraw?NULL:&newsel; + sm.disableRedraw = TRUE; + sm.hContact = si->hContact; + CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm); + } + + // scroll log to bottom if the log was previously scrolled to bottom, else restore old position + if (bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax-scroll.nPage-5 || scroll.nMax-scroll.nMin-scroll.nPage < 50) + SendMessage(GetParent(hwndRich), GC_SCROLLTOBOTTOM, 0, 0); + else + SendMessage(hwndRich, EM_SETSCROLLPOS, 0, (LPARAM) &point); + + // do we need to restore the selection + if (oldsel.cpMax != oldsel.cpMin) { + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM) & oldsel); + SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0); + InvalidateRect(hwndRich, NULL, TRUE); + } + + // need to invalidate the window + if (bFlag) { + sel.cpMin = sel.cpMax = GetRichTextLength(hwndRich); + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM) &sel); + SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0); + InvalidateRect(hwndRich, NULL, TRUE); +} } + +///////////////////////////////////////////////////////////////////////////////////////// + +static DWORD CALLBACK Message_StreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + static DWORD dwRead; + char ** ppText = (char **)dwCookie; + + if (*ppText == NULL) { + *ppText = (char *)mir_alloc(cb + 1); + memcpy(*ppText, pbBuff, cb); + (*ppText)[cb] = 0; + *pcb = cb; + dwRead = cb; + } + else { + char *p = (char *)mir_alloc(dwRead + cb + 1); + memcpy(p, *ppText, dwRead); + memcpy(p + dwRead, pbBuff, cb); + p[dwRead + cb] = 0; + mir_free(*ppText); + *ppText = p; + *pcb = cb; + dwRead += cb; + } + + return 0; +} + +char* Message_GetFromStream(HWND hwndDlg, SESSION_INFO *si) +{ + EDITSTREAM stream; + char* pszText = NULL; + DWORD dwFlags; + + if (hwndDlg == 0 || si == 0) + return NULL; + + memset(&stream, 0, sizeof(stream)); + stream.pfnCallback = Message_StreamCallback; + stream.dwCookie = (DWORD_PTR)&pszText; // pass pointer to pointer + + dwFlags = SF_RTFNOOBJS | SFF_PLAINRTF | SF_USECODEPAGE | (CP_UTF8 << 16); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_STREAMOUT, dwFlags, (LPARAM)& stream); + return pszText; // pszText contains the text +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void ShowRoom(SESSION_INFO *si, WPARAM wp, BOOL bSetForeground) +{ + if (!si) + return; + + if (g_Settings.bTabsEnable) { + // the session is not the current tab, so we copy the necessary + // details into the SESSION_INFO for the tabbed window + if (!si->hWnd) { + g_TabSession.iEventCount = si->iEventCount; + g_TabSession.iStatusCount = si->iStatusCount; + g_TabSession.iType = si->iType; + g_TabSession.nUsersInNicklist = si->nUsersInNicklist; + g_TabSession.pLog = si->pLog; + g_TabSession.pLogEnd = si->pLogEnd; + g_TabSession.pMe = si->pMe; + g_TabSession.pStatuses = si->pStatuses; + g_TabSession.ptszID = si->ptszID; + g_TabSession.pszModule = si->pszModule; + g_TabSession.ptszName = si->ptszName; + g_TabSession.ptszStatusbarText = si->ptszStatusbarText; + g_TabSession.ptszTopic = si->ptszTopic; + g_TabSession.pUsers = si->pUsers; + g_TabSession.hContact = si->hContact; + g_TabSession.wStatus = si->wStatus; + g_TabSession.lpCommands = si->lpCommands; + g_TabSession.lpCurrentCommand = NULL; + } + + // Do we need to create a tabbed window? + if (g_TabSession.hWnd == NULL) + g_TabSession.hWnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CHANNEL), NULL, RoomWndProc, (LPARAM)&g_TabSession); + + SetWindowLongPtr(g_TabSession.hWnd, GWL_EXSTYLE, GetWindowLongPtr(g_TabSession.hWnd, GWL_EXSTYLE) | WS_EX_APPWINDOW); + + // if the session was not the current tab we need to tell the window to + // redraw to show the contents of the current SESSION_INFO + if (!si->hWnd) { + SM_SetTabbedWindowHwnd(si, g_TabSession.hWnd); + SendMessage(g_TabSession.hWnd, GC_ADDTAB, -1, (LPARAM)si); + SendMessage(g_TabSession.hWnd, GC_TABCHANGE, 0, (LPARAM)&g_TabSession); + } + + pci->SetActiveSession(si->ptszID, si->pszModule); + + if (!IsWindowVisible(g_TabSession.hWnd) || wp == WINDOW_HIDDEN) + SendMessage(g_TabSession.hWnd, GC_CONTROL_MSG, wp, 0); + else { + if (IsIconic(g_TabSession.hWnd)) + ShowWindow(g_TabSession.hWnd, SW_NORMAL); + + PostMessage(g_TabSession.hWnd, WM_SIZE, 0, 0); + if (si->iType != GCW_SERVER) + SendMessage(g_TabSession.hWnd, GC_UPDATENICKLIST, 0, 0); + else + SendMessage(g_TabSession.hWnd, GC_UPDATETITLE, 0, 0); + SendMessage(g_TabSession.hWnd, GC_REDRAWLOG, 0, 0); + SendMessage(g_TabSession.hWnd, GC_UPDATESTATUSBAR, 0, 0); + ShowWindow(g_TabSession.hWnd, SW_SHOW); + if (bSetForeground) + SetForegroundWindow(g_TabSession.hWnd); + } + SendMessage(g_TabSession.hWnd, WM_MOUSEACTIVATE, 0, 0); + SetFocus(GetDlgItem(g_TabSession.hWnd, IDC_MESSAGE)); + return; + } + + // Do we need to create a window? + if (si->hWnd == NULL) + si->hWnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CHANNEL), NULL, RoomWndProc, (LPARAM)si); + + SetWindowLongPtr(si->hWnd, GWL_EXSTYLE, GetWindowLongPtr(si->hWnd, GWL_EXSTYLE) | WS_EX_APPWINDOW); + if (!IsWindowVisible(si->hWnd) || wp == WINDOW_HIDDEN) + SendMessage(si->hWnd, GC_CONTROL_MSG, wp, 0); + else { + if (IsIconic(si->hWnd)) + ShowWindow(si->hWnd, SW_NORMAL); + ShowWindow(si->hWnd, SW_SHOW); + SetForegroundWindow(si->hWnd); + } + + SendMessage(si->hWnd, WM_MOUSEACTIVATE, 0, 0); + SetFocus(GetDlgItem(si->hWnd, IDC_MESSAGE)); +} + +bool LoadMessageFont(LOGFONT *lf, COLORREF *colour) +{ + char str[32]; + int i = 8; // MSGFONTID_MESSAGEAREA + + if (colour) { + mir_snprintf(str, "SRMFont%dCol", i); + *colour = db_get_dw(NULL, "SRMM", str, 0); + } + if (lf) { + mir_snprintf(str, "SRMFont%dSize", i); + lf->lfHeight = (char)db_get_b(NULL, "SRMM", str, -12); + lf->lfWidth = 0; + lf->lfEscapement = 0; + lf->lfOrientation = 0; + mir_snprintf(str, "SRMFont%dSty", i); + int style = db_get_b(NULL, "SRMM", str, 0); + lf->lfWeight = style & DBFONTF_BOLD ? FW_BOLD : FW_NORMAL; + lf->lfItalic = style & DBFONTF_ITALIC ? 1 : 0; + lf->lfUnderline = 0; + lf->lfStrikeOut = 0; + lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf->lfQuality = DEFAULT_QUALITY; + lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + mir_snprintf(str, "SRMFont%d", i); + + DBVARIANT dbv; + if (db_get_ws(NULL, "SRMM", str, &dbv)) + mir_wstrcpy(lf->lfFaceName, L"Arial"); + else { + mir_wstrncpy(lf->lfFaceName, dbv.ptszVal, _countof(lf->lfFaceName)); + db_free(&dbv); + } + mir_snprintf(str, "SRMFont%dSet", i); + lf->lfCharSet = db_get_b(NULL, "SRMM", str, DEFAULT_CHARSET); + } + return true; +} + +int GetRichTextLength(HWND hwnd) +{ + GETTEXTLENGTHEX gtl; + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + return (int)SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); +} + +int GetColorIndex(const char* pszModule, COLORREF cr) +{ + MODULEINFO * pMod = pci->MM_FindModule(pszModule); + int i = 0; + + if (!pMod || pMod->nColorCount == 0) + return -1; + + for (i = 0; i < pMod->nColorCount; i++) + if (pMod->crColors[i] == cr) + return i; + + return -1; +} + +// obscure function that is used to make sure that any of the colors +// passed by the protocol is used as fore- or background color +// in the messagebox. THis is to vvercome limitations in the richedit +// that I do not know currently how to fix + +void CheckColorsInModule(const char* pszModule) +{ + MODULEINFO *pMod = pci->MM_FindModule(pszModule); + int i = 0; + COLORREF crBG = (COLORREF)db_get_dw(NULL, CHAT_MODULE, "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + + if (!pMod) + return; + + for (i = 0; i < pMod->nColorCount; i++) { + if (pMod->crColors[i] == g_Settings.MessageAreaColor || pMod->crColors[i] == crBG) { + if (pMod->crColors[i] == RGB(255, 255, 255)) + pMod->crColors[i]--; + else + pMod->crColors[i]++; + } + } +} + +UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO *si, wchar_t* pszUID, wchar_t* pszWordText) +{ + HMENU hSubMenu = 0; + *hMenu = GetSubMenu(g_hMenu, iIndex); + TranslateMenu(*hMenu); + + GCMENUITEMS gcmi = { 0 }; + gcmi.pszID = si->ptszID; + gcmi.pszModule = si->pszModule; + gcmi.pszUID = pszUID; + + if (iIndex == 1) { + int i = GetRichTextLength(GetDlgItem(hwndDlg, IDC_LOG)); + + EnableMenuItem(*hMenu, ID_CLEARLOG, MF_ENABLED); + EnableMenuItem(*hMenu, ID_COPYALL, MF_ENABLED); + ModifyMenu(*hMenu, 4, MF_GRAYED | MF_BYPOSITION, 4, NULL); + if (!i) { + EnableMenuItem(*hMenu, ID_COPYALL, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(*hMenu, ID_CLEARLOG, MF_BYCOMMAND | MF_GRAYED); + if (pszWordText && pszWordText[0]) + ModifyMenu(*hMenu, 4, MF_ENABLED | MF_BYPOSITION, 4, NULL); + } + + if (pszWordText && pszWordText[0]) { + wchar_t szMenuText[4096]; + mir_snwprintf(szMenuText, TranslateT("Look up '%s':"), pszWordText); + ModifyMenu(*hMenu, 4, MF_STRING | MF_BYPOSITION, 4, szMenuText); + } + else ModifyMenu(*hMenu, 4, MF_STRING | MF_GRAYED | MF_BYPOSITION, 4, TranslateT("No word to look up")); + gcmi.Type = MENU_ON_LOG; + } + else if (iIndex == 0) { + wchar_t szTemp[50]; + if (pszWordText) + mir_snwprintf(szTemp, TranslateT("&Message %s"), pszWordText); + else + mir_wstrncpy(szTemp, TranslateT("&Message"), _countof(szTemp) - 1); + + if (mir_wstrlen(szTemp) > 40) + mir_wstrcpy(szTemp + 40, L"..."); + ModifyMenu(*hMenu, ID_MESS, MF_STRING | MF_BYCOMMAND, ID_MESS, szTemp); + gcmi.Type = MENU_ON_NICKLIST; + } + + NotifyEventHooks(pci->hBuildMenuEvent, 0, (WPARAM)&gcmi); + + if (gcmi.nItems > 0) + AppendMenu(*hMenu, MF_SEPARATOR, 0, 0); + + for (int i = 0; i < gcmi.nItems; i++) { + wchar_t* ptszText = TranslateW(gcmi.Item[i].pszDesc); + DWORD dwState = gcmi.Item[i].bDisabled ? MF_GRAYED : 0; + + if (gcmi.Item[i].uType == MENU_NEWPOPUP) { + hSubMenu = CreateMenu(); + AppendMenu(*hMenu, dwState | MF_POPUP, (UINT_PTR)hSubMenu, ptszText); + } + else if (gcmi.Item[i].uType == MENU_POPUPHMENU) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPITEM) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPCHECK) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPSEPARATOR) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, MF_SEPARATOR, 0, ptszText); + else if (gcmi.Item[i].uType == MENU_SEPARATOR) + AppendMenu(*hMenu, MF_SEPARATOR, 0, ptszText); + else if (gcmi.Item[i].uType == MENU_HMENU) + AppendMenu(*hMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_ITEM) + AppendMenu(*hMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_CHECK) + AppendMenu(*hMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); + } + return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); +} + +void DestroyGCMenu(HMENU *hMenu, int iIndex) +{ + MENUITEMINFO mii = { 0 }; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU; + while (GetMenuItemInfo(*hMenu, iIndex, TRUE, &mii)) { + if (mii.hSubMenu != NULL) + DestroyMenu(mii.hSubMenu); + RemoveMenu(*hMenu, iIndex, MF_BYPOSITION); + } +} + +void ValidateFilename(wchar_t *filename) +{ + wchar_t *p1 = filename; + wchar_t szForbidden[] = L"\\/:*?\"<>|"; + while (*p1 != '\0') { + if (wcschr(szForbidden, *p1)) + *p1 = '_'; + p1 += 1; + } +} diff --git a/src/core/stdmsg/src/chat_window.cpp b/src/core/stdmsg/src/chat_window.cpp new file mode 100644 index 0000000000..ccf26ee80e --- /dev/null +++ b/src/core/stdmsg/src/chat_window.cpp @@ -0,0 +1,2610 @@ +/* +Chat module plugin for Miranda IM + +Copyright 2000-12 Miranda IM, 2012-16 Miranda NG project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +static HKL hkl = NULL; + +struct MESSAGESUBDATA +{ + time_t lastEnterTime; + wchar_t szTabSave[20]; +}; + +static wchar_t szTrimString[] = L":;,.!?\'\"><()[]- \r\n"; + +static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + RECT rc; + + switch (msg) { + case WM_NCHITTEST: + return HTCLIENT; + + case WM_SETCURSOR: + GetClientRect(hwnd, &rc); + SetCursor(rc.right > rc.bottom ? LoadCursor(NULL, IDC_SIZENS) : LoadCursor(NULL, IDC_SIZEWE)); + return TRUE; + + case WM_LBUTTONDOWN: + SetCapture(hwnd); + return 0; + + case WM_MOUSEMOVE: + if (GetCapture() == hwnd) { + GetClientRect(hwnd, &rc); + SendMessage(GetParent(hwnd), GC_SPLITTERMOVED, rc.right > rc.bottom ? (short)HIWORD(GetMessagePos()) + rc.bottom / 2 : (short)LOWORD(GetMessagePos()) + rc.right / 2, (LPARAM)hwnd); + } + return 0; + + case WM_LBUTTONUP: + ReleaseCapture(); + PostMessage(GetParent(hwnd), WM_SIZE, 0, 0); + return 0; + } + return mir_callNextSubclass(hwnd, SplitterSubclassProc, msg, wParam, lParam); +} + +static void InitButtons(HWND hwndDlg, SESSION_INFO *si) +{ + SendDlgItemMessage(hwndDlg, IDC_SMILEY, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("smiley", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_BOLD, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("bold", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_ITALICS, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("italics", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_UNDERLINE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("underline", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_COLOR, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("fgcol", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOR, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("bkgcol", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_HISTORY, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("history", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_CHANMGR, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("settings", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_CLOSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx("close", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_SHOWNICKLIST, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx(si->bNicklistEnabled ? "nicklist" : "nicklist2", FALSE)); + SendDlgItemMessage(hwndDlg, IDC_FILTER, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx(si->bFilterEnabled ? "filter" : "filter2", FALSE)); + + SendDlgItemMessage(hwndDlg, IDC_SMILEY, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_BOLD, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_ITALICS, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_UNDERLINE, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOR, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_COLOR, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_HISTORY, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_SHOWNICKLIST, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_CHANMGR, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_FILTER, BUTTONSETASFLATBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_CLOSE, BUTTONSETASFLATBTN, TRUE, 0); + + SendDlgItemMessage(hwndDlg, IDC_SMILEY, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Insert a smiley"), 0); + SendDlgItemMessage(hwndDlg, IDC_BOLD, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Make the text bold (CTRL+B)"), 0); + SendDlgItemMessage(hwndDlg, IDC_ITALICS, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Make the text italicized (CTRL+I)"), 0); + SendDlgItemMessage(hwndDlg, IDC_UNDERLINE, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Make the text underlined (CTRL+U)"), 0); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOR, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Select a background color for the text (CTRL+L)"), 0); + SendDlgItemMessage(hwndDlg, IDC_COLOR, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Select a foreground color for the text (CTRL+K)"), 0); + SendDlgItemMessage(hwndDlg, IDC_HISTORY, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Show the history (CTRL+H)"), 0); + SendDlgItemMessage(hwndDlg, IDC_SHOWNICKLIST, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Show/hide the nick list (CTRL+N)"), 0); + SendDlgItemMessage(hwndDlg, IDC_CHANMGR, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Control this room (CTRL+O)"), 0); + SendDlgItemMessage(hwndDlg, IDC_FILTER, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Enable/disable the event filter (CTRL+F)"), 0); + SendDlgItemMessage(hwndDlg, IDC_CLOSE, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Close current tab (CTRL+F4)"), 0); + SendDlgItemMessage(hwndDlg, IDC_BOLD, BUTTONSETASPUSHBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_ITALICS, BUTTONSETASPUSHBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_UNDERLINE, BUTTONSETASPUSHBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_COLOR, BUTTONSETASPUSHBTN, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOR, BUTTONSETASPUSHBTN, TRUE, 0); + + MODULEINFO *pInfo = pci->MM_FindModule(si->pszModule); + if (pInfo) { + EnableWindow(GetDlgItem(hwndDlg, IDC_BOLD), pInfo->bBold); + EnableWindow(GetDlgItem(hwndDlg, IDC_ITALICS), pInfo->bItalics); + EnableWindow(GetDlgItem(hwndDlg, IDC_UNDERLINE), pInfo->bUnderline); + EnableWindow(GetDlgItem(hwndDlg, IDC_COLOR), pInfo->bColor); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKGCOLOR), pInfo->bBkgColor); + if (si->iType == GCW_CHATROOM) + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANMGR), pInfo->bChanMgr); + } +} + +static int RoomWndResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc) +{ + SESSION_INFO *si = (SESSION_INFO*)lParam; + + BOOL bControl = (BOOL)db_get_b(NULL, CHAT_MODULE, "ShowTopButtons", 1); + BOOL bFormat = (BOOL)db_get_b(NULL, CHAT_MODULE, "ShowFormatButtons", 1); + BOOL bToolbar = bFormat || bControl; + BOOL bSend = (BOOL)db_get_b(NULL, CHAT_MODULE, "ShowSend", 0); + BOOL bNick = si->iType != GCW_SERVER && si->bNicklistEnabled; + BOOL bTabs = g_Settings.bTabsEnable; + BOOL bTabBottom = g_Settings.TabsAtBottom; + + RECT rc, rcTabs; + GetClientRect(GetDlgItem(hwndDlg, IDC_TAB), &rcTabs); + int TabHeight = rcTabs.bottom - rcTabs.top; + TabCtrl_AdjustRect(GetDlgItem(hwndDlg, IDC_TAB), FALSE, &rcTabs); + TabHeight -= (rcTabs.bottom - rcTabs.top); + ShowWindow(GetDlgItem(hwndDlg, IDC_SMILEY), (SmileyAddInstalled && bFormat) ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_BOLD), bFormat ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_UNDERLINE), bFormat ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_ITALICS), bFormat ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_COLOR), bFormat ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_BKGCOLOR), bFormat ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_HISTORY), bControl ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST), bControl ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_FILTER), bControl ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_CHANMGR), bControl ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDOK), bSend ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SPLITTERX), bNick ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_CLOSE), g_Settings.bTabsEnable ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_TAB), g_Settings.bTabsEnable ? SW_SHOW : SW_HIDE); + if (si->iType != GCW_SERVER) + ShowWindow(GetDlgItem(hwndDlg, IDC_LIST), si->bNicklistEnabled ? SW_SHOW : SW_HIDE); + else + ShowWindow(GetDlgItem(hwndDlg, IDC_LIST), SW_HIDE); + + if (si->iType == GCW_SERVER) { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANMGR), FALSE); + } + else { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER), TRUE); + if (si->iType == GCW_CHATROOM) + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANMGR), pci->MM_FindModule(si->pszModule)->bChanMgr); + } + + switch (urc->wId) { + case IDOK: + GetWindowRect(si->hwndStatus, &rc); + urc->rcItem.left = bSend ? 315 : urc->dlgNewSize.cx; + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY + 23; + urc->rcItem.bottom = urc->dlgNewSize.cy - (rc.bottom - rc.top) - 1; + return RD_ANCHORX_RIGHT | RD_ANCHORY_CUSTOM; + + case IDC_TAB: + urc->rcItem.top = 1; + urc->rcItem.left = 0; + urc->rcItem.right = urc->dlgNewSize.cx - 24; + urc->rcItem.bottom = urc->dlgNewSize.cy - si->iSplitterY; + if (!bToolbar) + urc->rcItem.bottom += 20; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + + case IDC_LOG: + urc->rcItem.top = bTabs ? (bTabBottom ? 0 : rcTabs.top - 1) : 0; + urc->rcItem.left = 0; + urc->rcItem.right = bNick ? urc->dlgNewSize.cx - si->iSplitterX : urc->dlgNewSize.cx; + LBL_CalcBottom: + urc->rcItem.bottom = urc->dlgNewSize.cy - si->iSplitterY; + if (bTabs && bTabBottom) urc->rcItem.bottom += 6 - TabHeight; + if (!bToolbar) urc->rcItem.bottom += 20; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + + case IDC_LIST: + urc->rcItem.top = bTabs ? (bTabBottom ? 0 : rcTabs.top - 1) : 0; + urc->rcItem.right = urc->dlgNewSize.cx; + urc->rcItem.left = urc->dlgNewSize.cx - si->iSplitterX + 2; + goto LBL_CalcBottom; + + case IDC_SPLITTERX: + urc->rcItem.top = bTabs ? rcTabs.top : 1; + urc->rcItem.left = urc->dlgNewSize.cx - si->iSplitterX; + urc->rcItem.right = urc->rcItem.left + 2; + goto LBL_CalcBottom; + + case IDC_SPLITTERY: + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY; + if (!bToolbar) + urc->rcItem.top += 20; + urc->rcItem.bottom = urc->rcItem.top + 2; + return RD_ANCHORX_WIDTH | RD_ANCHORY_CUSTOM; + + case IDC_MESSAGE: + GetWindowRect(si->hwndStatus, &rc); + urc->rcItem.right = bSend ? urc->dlgNewSize.cx - 64 : urc->dlgNewSize.cx; + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY + 22; + urc->rcItem.bottom = urc->dlgNewSize.cy - (rc.bottom - rc.top) - 1; + return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM; + + case IDC_SMILEY: + case IDC_ITALICS: + case IDC_BOLD: + case IDC_UNDERLINE: + case IDC_COLOR: + case IDC_BKGCOLOR: + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY + 3; + urc->rcItem.bottom = urc->rcItem.top + 16; + return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM; + + case IDC_HISTORY: + case IDC_CHANMGR: + case IDC_SHOWNICKLIST: + case IDC_FILTER: + urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY + 3; + urc->rcItem.bottom = urc->rcItem.top + 16; + return RD_ANCHORX_RIGHT | RD_ANCHORY_CUSTOM; + + case IDC_CLOSE: + urc->rcItem.left = urc->dlgNewSize.cx - 19; + urc->rcItem.right = urc->rcItem.left + 16; + urc->rcItem.top = bTabBottom ? (bToolbar ? urc->dlgNewSize.cy - si->iSplitterY - 18 : urc->dlgNewSize.cy - si->iSplitterY - 18 + 20) : 3; + urc->rcItem.bottom = urc->rcItem.top + 16; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; +} + +static LRESULT CALLBACK MessageSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SESSION_INFO *Parentsi = (SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); + MESSAGESUBDATA *dat = (MESSAGESUBDATA*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch (msg) { + case EM_SUBCLASSED: + dat = (MESSAGESUBDATA*)mir_alloc(sizeof(MESSAGESUBDATA)); + + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat); + dat->szTabSave[0] = '\0'; + dat->lastEnterTime = 0; + return 0; + + case WM_MOUSEWHEEL: + SendDlgItemMessage(GetParent(hwnd), IDC_LOG, WM_MOUSEWHEEL, wParam, lParam); + dat->lastEnterTime = 0; + return TRUE; + + case EM_REPLACESEL: + PostMessage(hwnd, EM_ACTIVATE, 0, 0); + break; + + case EM_ACTIVATE: + SetActiveWindow(GetParent(hwnd)); + break; + + case WM_CHAR: + { + BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000; + BOOL isAlt = GetKeyState(VK_MENU) & 0x8000; + + if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY) + break; + + if (wParam == 9 && isCtrl && !isAlt) // ctrl-i (italics) + return TRUE; + + if (wParam == VK_SPACE && isCtrl && !isAlt) // ctrl-space (paste clean text) + return TRUE; + + if (wParam == '\n' || wParam == '\r') { + if ((isCtrl != 0) ^ (0 != db_get_b(NULL, CHAT_MODULE, "SendOnEnter", 1))) { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + if (db_get_b(NULL, CHAT_MODULE, "SendOnDblEnter", 0)) { + if (dat->lastEnterTime + 2 < time(NULL)) + dat->lastEnterTime = time(NULL); + else { + SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0); + SendMessage(hwnd, WM_KEYUP, VK_BACK, 0); + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + } + } + else + dat->lastEnterTime = 0; + + if (wParam == 1 && isCtrl && !isAlt) { //ctrl-a + SendMessage(hwnd, EM_SETSEL, 0, -1); + return 0; + } + } + break; + + case WM_KEYDOWN: + { + static int start, end; + BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000; + BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000; + BOOL isAlt = GetKeyState(VK_MENU) & 0x8000; + if (wParam == VK_RETURN) { + dat->szTabSave[0] = '\0'; + if ((isCtrl != 0) ^ (0 != db_get_b(NULL, CHAT_MODULE, "SendOnEnter", 1))) + return 0; + + if (db_get_b(NULL, CHAT_MODULE, "SendOnDblEnter", 0)) + if (dat->lastEnterTime + 2 >= time(NULL)) + return 0; + + break; + } + + if (wParam == VK_TAB && isShift && !isCtrl) { // SHIFT-TAB (go to nick list) + SetFocus(GetDlgItem(GetParent(hwnd), IDC_LIST)); + return TRUE; + } + + if (wParam == VK_TAB && isCtrl && !isShift) { // CTRL-TAB (switch tab/window) + if (g_Settings.bTabsEnable) + SendMessage(GetParent(hwnd), GC_SWITCHNEXTTAB, 0, 0); + else + pci->ShowRoom(SM_GetNextWindow(Parentsi), WINDOW_VISIBLE, TRUE); + return TRUE; + } + + if (wParam == VK_TAB && isCtrl && isShift) { // CTRL_SHIFT-TAB (switch tab/window) + if (g_Settings.bTabsEnable) + SendMessage(GetParent(hwnd), GC_SWITCHPREVTAB, 0, 0); + else + pci->ShowRoom(SM_GetPrevWindow(Parentsi), WINDOW_VISIBLE, TRUE); + return TRUE; + } + + if (wParam <= '9' && wParam >= '1' && isCtrl && !isAlt) // CTRL + 1 -> 9 (switch tab) + if (g_Settings.bTabsEnable) + SendMessage(GetParent(hwnd), GC_SWITCHTAB, 0, (int)wParam - (int)'1'); + + if (wParam <= VK_NUMPAD9 && wParam >= VK_NUMPAD1 && isCtrl && !isAlt) // CTRL + 1 -> 9 (switch tab) + if (g_Settings.bTabsEnable) + SendMessage(GetParent(hwnd), GC_SWITCHTAB, 0, (int)wParam - (int)VK_NUMPAD1); + + if (wParam == VK_TAB && !isCtrl && !isShift) { //tab-autocomplete + wchar_t* pszText = NULL; + LRESULT lResult = (LRESULT)SendMessage(hwnd, EM_GETSEL, 0, 0); + + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + start = LOWORD(lResult); + end = HIWORD(lResult); + SendMessage(hwnd, EM_SETSEL, end, end); + + GETTEXTLENGTHEX gtl = { 0 }; + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); + if (iLen > 0) { + pszText = (wchar_t *)mir_alloc(sizeof(wchar_t)*(iLen + 100)); + + GETTEXTEX gt = { 0 }; + gt.cb = iLen + 99; + gt.flags = GT_DEFAULT; + gt.codepage = 1200; + + SendMessage(hwnd, EM_GETTEXTEX, (WPARAM)>, (LPARAM)pszText); + while (start > 0 && pszText[start - 1] != ' ' && pszText[start - 1] != 13 && pszText[start - 1] != VK_TAB) + start--; + while (end < iLen && pszText[end] != ' ' && pszText[end] != 13 && pszText[end - 1] != VK_TAB) + end++; + + if (dat->szTabSave[0] == '\0') + mir_wstrncpy(dat->szTabSave, pszText + start, end - start + 1); + + wchar_t *pszSelName = (wchar_t *)mir_alloc(sizeof(wchar_t)*(end - start + 1)); + mir_wstrncpy(pszSelName, pszText + start, end - start + 1); + + wchar_t *pszName = pci->UM_FindUserAutoComplete(Parentsi->pUsers, dat->szTabSave, pszSelName); + if (pszName == NULL) { + pszName = dat->szTabSave; + SendMessage(hwnd, EM_SETSEL, start, end); + if (end != start) + SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM)pszName); + dat->szTabSave[0] = '\0'; + } + else { + SendMessage(hwnd, EM_SETSEL, start, end); + if (end != start) + SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM)pszName); + } + mir_free(pszText); + mir_free(pszSelName); + } + + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + return 0; + } + + if (dat->szTabSave[0] != '\0' && wParam != VK_RIGHT && wParam != VK_LEFT && wParam != VK_SPACE && wParam != VK_RETURN && wParam != VK_BACK && wParam != VK_DELETE) { + if (g_Settings.bAddColonToAutoComplete && start == 0) + SendMessageA(hwnd, EM_REPLACESEL, FALSE, (LPARAM) ": "); + + dat->szTabSave[0] = '\0'; + } + + if (wParam == VK_F4 && isCtrl && !isAlt) { // ctrl-F4 (close tab) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CLOSE, BN_CLICKED), 0); + return TRUE; + } + + if (wParam == 0x49 && isCtrl && !isAlt) { // ctrl-i (italics) + CheckDlgButton(GetParent(hwnd), IDC_ITALICS, IsDlgButtonChecked(GetParent(hwnd), IDC_ITALICS) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0); + return TRUE; + } + + if (wParam == 0x42 && isCtrl && !isAlt) { // ctrl-b (bold) + CheckDlgButton(GetParent(hwnd), IDC_BOLD, IsDlgButtonChecked(GetParent(hwnd), IDC_BOLD) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_BOLD, 0), 0); + return TRUE; + } + + if (wParam == 0x55 && isCtrl && !isAlt) { // ctrl-u (paste clean text) + CheckDlgButton(GetParent(hwnd), IDC_UNDERLINE, IsDlgButtonChecked(GetParent(hwnd), IDC_UNDERLINE) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_UNDERLINE, 0), 0); + return TRUE; + } + + if (wParam == 0x4b && isCtrl && !isAlt) { // ctrl-k (paste clean text) + CheckDlgButton(GetParent(hwnd), IDC_COLOR, IsDlgButtonChecked(GetParent(hwnd), IDC_COLOR) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0); + return TRUE; + } + + if (wParam == VK_SPACE && isCtrl && !isAlt) { // ctrl-space (paste clean text) + CheckDlgButton(GetParent(hwnd), IDC_BKGCOLOR, BST_UNCHECKED); + CheckDlgButton(GetParent(hwnd), IDC_COLOR, BST_UNCHECKED); + CheckDlgButton(GetParent(hwnd), IDC_BOLD, BST_UNCHECKED); + CheckDlgButton(GetParent(hwnd), IDC_UNDERLINE, BST_UNCHECKED); + CheckDlgButton(GetParent(hwnd), IDC_ITALICS, BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_BOLD, 0), 0); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_UNDERLINE, 0), 0); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0); + return TRUE; + } + + if (wParam == 0x4c && isCtrl && !isAlt) { // ctrl-l (paste clean text) + CheckDlgButton(GetParent(hwnd), IDC_BKGCOLOR, IsDlgButtonChecked(GetParent(hwnd), IDC_BKGCOLOR) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0); + return TRUE; + } + + if (wParam == 0x46 && isCtrl && !isAlt) { // ctrl-f (paste clean text) + if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_FILTER))) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_FILTER, 0), 0); + return TRUE; + } + + if (wParam == 0x4e && isCtrl && !isAlt) { // ctrl-n (nicklist) + if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_SHOWNICKLIST))) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_SHOWNICKLIST, 0), 0); + return TRUE; + } + + if (wParam == 0x48 && isCtrl && !isAlt) { // ctrl-h (history) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_HISTORY, 0), 0); + return TRUE; + } + + if (wParam == 0x4f && isCtrl && !isAlt) { // ctrl-o (options) + if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_CHANMGR))) + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHANMGR, 0), 0); + return TRUE; + } + + if ((wParam == 45 && isShift || wParam == 0x56 && isCtrl) && !isAlt) { // ctrl-v (paste clean text) + SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); + return TRUE; + } + + if (wParam == 0x57 && isCtrl && !isAlt) { // ctrl-w (close window) + PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return TRUE; + } + + if (wParam == VK_NEXT || wParam == VK_PRIOR) { + HWND htemp = GetParent(hwnd); + SendDlgItemMessage(htemp, IDC_LOG, msg, wParam, lParam); + dat->lastEnterTime = 0; + return TRUE; + } + + if (wParam == VK_UP && isCtrl && !isAlt) { + char* lpPrevCmd = pci->SM_GetPrevCommand(Parentsi->ptszID, Parentsi->pszModule); + + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + + if (lpPrevCmd) { + SETTEXTEX ste; + ste.flags = ST_DEFAULT; + ste.codepage = CP_ACP; + SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd); + } + else SetWindowText(hwnd, L""); + + GETTEXTLENGTHEX gtl = { 0 }; + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); + SendMessage(hwnd, EM_SCROLLCARET, 0, 0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + SendMessage(hwnd, EM_SETSEL, iLen, iLen); + dat->lastEnterTime = 0; + return TRUE; + } + + if (wParam == VK_DOWN && isCtrl && !isAlt) { + char* lpPrevCmd = pci->SM_GetNextCommand(Parentsi->ptszID, Parentsi->pszModule); + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + + if (lpPrevCmd) { + SETTEXTEX ste; + ste.flags = ST_DEFAULT; + ste.codepage = CP_ACP; + SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd); + } + else SetWindowText(hwnd, L""); + + GETTEXTLENGTHEX gtl = { 0 }; + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); + SendMessage(hwnd, EM_SCROLLCARET, 0, 0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + SendMessage(hwnd, EM_SETSEL, iLen, iLen); + dat->lastEnterTime = 0; + return TRUE; + } + } + //fall through + + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_KILLFOCUS: + dat->lastEnterTime = 0; + break; + + case WM_RBUTTONDOWN: + { + CHARRANGE sel, all = { 0, -1 }; + HMENU hSubMenu = GetSubMenu(g_hMenu, 4); + TranslateMenu(hSubMenu); + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + + EnableMenuItem(hSubMenu, ID_MESSAGE_UNDO, SendMessage(hwnd, EM_CANUNDO, 0, 0) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hSubMenu, ID_MESSAGE_REDO, SendMessage(hwnd, EM_CANREDO, 0, 0) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hSubMenu, ID_MESSAGE_COPY, sel.cpMax != sel.cpMin ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hSubMenu, ID_MESSAGE_CUT, sel.cpMax != sel.cpMin ? MF_ENABLED : MF_GRAYED); + + dat->lastEnterTime = 0; + + POINT pt; + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + ClientToScreen(hwnd, &pt); + + UINT uID = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL); + switch (uID) { + case 0: + break; + + case ID_MESSAGE_UNDO: + SendMessage(hwnd, EM_UNDO, 0, 0); + break; + + case ID_MESSAGE_REDO: + SendMessage(hwnd, EM_REDO, 0, 0); + break; + + case ID_MESSAGE_COPY: + SendMessage(hwnd, WM_COPY, 0, 0); + break; + + case ID_MESSAGE_CUT: + SendMessage(hwnd, WM_CUT, 0, 0); + break; + + case ID_MESSAGE_PASTE: + SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); + break; + + case ID_MESSAGE_SELECTALL: + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)& all); + break; + + case ID_MESSAGE_CLEAR: + SetWindowText(hwnd, L""); + break; + } + PostMessage(hwnd, WM_KEYUP, 0, 0); + } + break; + + case WM_KEYUP: + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + { + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_BACKCOLOR | CFM_COLOR; + SendMessage(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + + MODULEINFO *pmi = pci->MM_FindModule(Parentsi->pszModule); + if (pmi && pmi->bColor) { + int index = GetColorIndex(Parentsi->pszModule, cf.crTextColor); + UINT u = IsDlgButtonChecked(GetParent(hwnd), IDC_COLOR); + + if (index >= 0) { + Parentsi->bFGSet = TRUE; + Parentsi->iFG = index; + } + + if (u == BST_UNCHECKED && cf.crTextColor != g_Settings.MessageAreaColor) + CheckDlgButton(GetParent(hwnd), IDC_COLOR, BST_CHECKED); + else if (u == BST_CHECKED && cf.crTextColor == g_Settings.MessageAreaColor) + CheckDlgButton(GetParent(hwnd), IDC_COLOR, BST_UNCHECKED); + } + + if (pmi && pmi->bBkgColor) { + int index = GetColorIndex(Parentsi->pszModule, cf.crBackColor); + COLORREF crB = (COLORREF)db_get_dw(NULL, CHAT_MODULE, "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + UINT u = IsDlgButtonChecked(GetParent(hwnd), IDC_BKGCOLOR); + + if (index >= 0) { + Parentsi->bBGSet = TRUE; + Parentsi->iBG = index; + } + if (u == BST_UNCHECKED && cf.crBackColor != crB) + CheckDlgButton(GetParent(hwnd), IDC_BKGCOLOR, BST_CHECKED); + else if (u == BST_CHECKED && cf.crBackColor == crB) + CheckDlgButton(GetParent(hwnd), IDC_BKGCOLOR, BST_UNCHECKED); + } + + if (pmi && pmi->bBold) { + UINT u = IsDlgButtonChecked(GetParent(hwnd), IDC_BOLD); + UINT u2 = cf.dwEffects; + u2 &= CFE_BOLD; + if (u == BST_UNCHECKED && u2) + CheckDlgButton(GetParent(hwnd), IDC_BOLD, BST_CHECKED); + else if (u == BST_CHECKED && u2 == 0) + CheckDlgButton(GetParent(hwnd), IDC_BOLD, BST_UNCHECKED); + } + + if (pmi && pmi->bItalics) { + UINT u = IsDlgButtonChecked(GetParent(hwnd), IDC_ITALICS); + UINT u2 = cf.dwEffects; + u2 &= CFE_ITALIC; + if (u == BST_UNCHECKED && u2) + CheckDlgButton(GetParent(hwnd), IDC_ITALICS, BST_CHECKED); + else if (u == BST_CHECKED && u2 == 0) + CheckDlgButton(GetParent(hwnd), IDC_ITALICS, BST_UNCHECKED); + } + + if (pmi && pmi->bUnderline) { + UINT u = IsDlgButtonChecked(GetParent(hwnd), IDC_UNDERLINE); + UINT u2 = cf.dwEffects; + u2 &= CFE_UNDERLINE; + if (u == BST_UNCHECKED && u2) + CheckDlgButton(GetParent(hwnd), IDC_UNDERLINE, BST_CHECKED); + else if (u == BST_CHECKED && u2 == 0) + CheckDlgButton(GetParent(hwnd), IDC_UNDERLINE, BST_UNCHECKED); + } + } + break; + + case WM_DESTROY: + mir_free(dat); + return 0; + } + + return mir_callNextSubclass(hwnd, MessageSubclassProc, msg, wParam, lParam); +} + +static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static SESSION_INFO *si = NULL; + switch (uMsg) { + case WM_INITDIALOG: + si = (SESSION_INFO*)lParam; + CheckDlgButton(hwndDlg, IDC_1, si->iLogFilterFlags & GC_EVENT_ACTION ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_2, si->iLogFilterFlags & GC_EVENT_MESSAGE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_3, si->iLogFilterFlags & GC_EVENT_NICK ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_4, si->iLogFilterFlags & GC_EVENT_JOIN ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_5, si->iLogFilterFlags & GC_EVENT_PART ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_6, si->iLogFilterFlags & GC_EVENT_TOPIC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_7, si->iLogFilterFlags & GC_EVENT_ADDSTATUS ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_8, si->iLogFilterFlags & GC_EVENT_INFORMATION ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_9, si->iLogFilterFlags & GC_EVENT_QUIT ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_10, si->iLogFilterFlags & GC_EVENT_KICK ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_11, si->iLogFilterFlags & GC_EVENT_NOTICE ? BST_CHECKED : BST_UNCHECKED); + break; + + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + SetTextColor((HDC)wParam, RGB(60, 60, 150)); + SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); + return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); + + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) { + int iFlags = 0; + + if (IsDlgButtonChecked(hwndDlg, IDC_1) == BST_CHECKED) + iFlags |= GC_EVENT_ACTION; + if (IsDlgButtonChecked(hwndDlg, IDC_2) == BST_CHECKED) + iFlags |= GC_EVENT_MESSAGE; + if (IsDlgButtonChecked(hwndDlg, IDC_3) == BST_CHECKED) + iFlags |= GC_EVENT_NICK; + if (IsDlgButtonChecked(hwndDlg, IDC_4) == BST_CHECKED) + iFlags |= GC_EVENT_JOIN; + if (IsDlgButtonChecked(hwndDlg, IDC_5) == BST_CHECKED) + iFlags |= GC_EVENT_PART; + if (IsDlgButtonChecked(hwndDlg, IDC_6) == BST_CHECKED) + iFlags |= GC_EVENT_TOPIC; + if (IsDlgButtonChecked(hwndDlg, IDC_7) == BST_CHECKED) + iFlags |= GC_EVENT_ADDSTATUS; + if (IsDlgButtonChecked(hwndDlg, IDC_8) == BST_CHECKED) + iFlags |= GC_EVENT_INFORMATION; + if (IsDlgButtonChecked(hwndDlg, IDC_9) == BST_CHECKED) + iFlags |= GC_EVENT_QUIT; + if (IsDlgButtonChecked(hwndDlg, IDC_10) == BST_CHECKED) + iFlags |= GC_EVENT_KICK; + if (IsDlgButtonChecked(hwndDlg, IDC_11) == BST_CHECKED) + iFlags |= GC_EVENT_NOTICE; + + if (iFlags&GC_EVENT_ADDSTATUS) + iFlags |= GC_EVENT_REMOVESTATUS; + + SendMessage(GetParent(hwndDlg), GC_CHANGEFILTERFLAG, 0, (LPARAM)iFlags); + if (si->bFilterEnabled) + SendMessage(GetParent(hwndDlg), GC_REDRAWLOG, 0, 0); + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + } + + return(FALSE); +} + +static LRESULT CALLBACK ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_RBUTTONUP: + if (db_get_b(NULL, CHAT_MODULE, "RightClickFilter", 0) != 0) { + if (GetDlgItem(GetParent(hwnd), IDC_FILTER) == hwnd) + SendMessage(GetParent(hwnd), GC_SHOWFILTERMENU, 0, 0); + if (GetDlgItem(GetParent(hwnd), IDC_COLOR) == hwnd) + SendMessage(GetParent(hwnd), GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_COLOR); + if (GetDlgItem(GetParent(hwnd), IDC_BKGCOLOR) == hwnd) + SendMessage(GetParent(hwnd), GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_BKGCOLOR); + } + break; + } + + return mir_callNextSubclass(hwnd, ButtonSubclassProc, msg, wParam, lParam); +} + +static LRESULT CALLBACK LogSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_LBUTTONUP: + { + CHARRANGE sel; + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin != sel.cpMax) { + SendMessage(hwnd, WM_COPY, 0, 0); + sel.cpMin = sel.cpMax; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + } + SetFocus(GetDlgItem(GetParent(hwnd), IDC_MESSAGE)); + } + break; + case WM_KEYDOWN: + if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) + PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return TRUE; + } + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) { + CHARRANGE sel; + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin != sel.cpMax) { + sel.cpMin = sel.cpMax; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + } + } + break; + + case WM_CHAR: + SetFocus(GetDlgItem(GetParent(hwnd), IDC_MESSAGE)); + SendDlgItemMessage(GetParent(hwnd), IDC_MESSAGE, WM_CHAR, wParam, lParam); + break; + } + + return mir_callNextSubclass(hwnd, LogSubclassProc, msg, wParam, lParam); +} + +static LRESULT CALLBACK TabSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static BOOL bDragging = FALSE; + static int iBeginIndex = 0; + switch (msg) { + case WM_LBUTTONDOWN: + { + TCHITTESTINFO tci = { 0 }; + tci.pt.x = (short)LOWORD(GetMessagePos()); + tci.pt.y = (short)HIWORD(GetMessagePos()); + if (DragDetect(hwnd, tci.pt) && TabCtrl_GetItemCount(hwnd) > 1) { + int i; + tci.flags = TCHT_ONITEM; + + ScreenToClient(hwnd, &tci.pt); + i = TabCtrl_HitTest(hwnd, &tci); + if (i != -1) { + TCITEM tc; + SESSION_INFO *s = NULL; + + tc.mask = TCIF_PARAM; + TabCtrl_GetItem(hwnd, i, &tc); + s = (SESSION_INFO*)tc.lParam; + if (s) { + BOOL bOnline = db_get_w(s->hContact, s->pszModule, "Status", ID_STATUS_OFFLINE) == ID_STATUS_ONLINE ? TRUE : FALSE; + MODULEINFO *mi = pci->MM_FindModule(s->pszModule); + bDragging = TRUE; + iBeginIndex = i; + ImageList_BeginDrag(hIconsList, bOnline ? mi->OnlineIconIndex : mi->OfflineIconIndex, 8, 8); + ImageList_DragEnter(hwnd, tci.pt.x, tci.pt.y); + SetCapture(hwnd); + } + return TRUE; + } + } + else PostMessage(GetParent(hwnd), GC_TABCLICKED, 0, 0); + } + break; + + case WM_CAPTURECHANGED: + bDragging = FALSE; + ImageList_DragLeave(hwnd); + ImageList_EndDrag(); + break; + + case WM_MOUSEMOVE: + if (bDragging) { + TCHITTESTINFO tci = { 0 }; + tci.pt.x = (short)LOWORD(GetMessagePos()); + tci.pt.y = (short)HIWORD(GetMessagePos()); + ScreenToClient(hwnd, &tci.pt); + ImageList_DragMove(tci.pt.x, tci.pt.y); + } + break; + + case WM_LBUTTONUP: + if (bDragging && ReleaseCapture()) { + TCHITTESTINFO tci = { 0 }; + tci.pt.x = (short)LOWORD(GetMessagePos()); + tci.pt.y = (short)HIWORD(GetMessagePos()); + tci.flags = TCHT_ONITEM; + bDragging = FALSE; + ImageList_DragLeave(hwnd); + ImageList_EndDrag(); + + ScreenToClient(hwnd, &tci.pt); + int i = TabCtrl_HitTest(hwnd, &tci); + if (i != -1 && i != iBeginIndex) + SendMessage(GetParent(hwnd), GC_DROPPEDTAB, (WPARAM)i, (LPARAM)iBeginIndex); + } + break; + + case WM_LBUTTONDBLCLK: + { + TCHITTESTINFO tci = { 0 }; + tci.pt.x = (short)LOWORD(GetMessagePos()); + tci.pt.y = (short)HIWORD(GetMessagePos()); + tci.flags = TCHT_ONITEM; + + ScreenToClient(hwnd, &tci.pt); + int i = TabCtrl_HitTest(hwnd, &tci); + if (i != -1 && g_Settings.TabCloseOnDblClick) + PostMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CLOSE, BN_CLICKED), 0); + } + break; + + case WM_MBUTTONUP: + TCHITTESTINFO tci = { 0 }; + tci.pt.x = (short)LOWORD(GetMessagePos()); + tci.pt.y = (short)HIWORD(GetMessagePos()); + tci.flags = TCHT_ONITEM; + + ScreenToClient(hwnd, &tci.pt); + int i = TabCtrl_HitTest(hwnd, &tci); + if (i != -1) { + TCITEM tc; + tc.mask = TCIF_PARAM; + TabCtrl_GetItem(hwnd, i, &tc); + SESSION_INFO *si = (SESSION_INFO*)tc.lParam; + if (si) + SendMessage(GetParent(hwnd), GC_REMOVETAB, 1, (LPARAM)si); + } + break; + } + + return mir_callNextSubclass(hwnd, TabSubclassProc, msg, wParam, lParam); +} + +static void ProcessNickListHovering(HWND hwnd, int hoveredItem, SESSION_INFO *si) +{ + static int currentHovered = -1; + static HWND hwndToolTip = NULL; + static HWND oldParent = NULL; + + if (hoveredItem == currentHovered) + return; + + currentHovered = hoveredItem; + + if (oldParent != hwnd && hwndToolTip) { + SendMessage(hwndToolTip, TTM_DELTOOL, 0, 0); + DestroyWindow(hwndToolTip); + hwndToolTip = NULL; + } + if (hoveredItem == -1) { + SendMessage(hwndToolTip, TTM_ACTIVATE, 0, 0); + return; + } + + BOOL bNewTip = FALSE; + if (!hwndToolTip) { + hwndToolTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, + WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + hwnd, NULL, g_hInst, NULL); + bNewTip = TRUE; + } + + RECT clientRect; + GetClientRect(hwnd, &clientRect); + TOOLINFO ti = { sizeof(TOOLINFO) }; + ti.uFlags = TTF_SUBCLASS; + ti.hinst = g_hInst; + ti.hwnd = hwnd; + ti.uId = 1; + ti.rect = clientRect; + + wchar_t tszBuf[1024]; tszBuf[0] = 0; + USERINFO *ui = pci->SM_GetUserFromIndex(si->ptszID, si->pszModule, currentHovered); + if (ui) { + if (ProtoServiceExists(si->pszModule, MS_GC_PROTO_GETTOOLTIPTEXT)) { + wchar_t *p = (wchar_t*)CallProtoService(si->pszModule, MS_GC_PROTO_GETTOOLTIPTEXT, (WPARAM)si->ptszID, (LPARAM)ui->pszUID); + if (p != NULL) { + wcsncpy_s(tszBuf, p, _TRUNCATE); + mir_free(p); + } + } + + if (tszBuf[0] == 0) + mir_snwprintf(tszBuf, L"%s: %s\r\n%s: %s\r\n%s: %s", + TranslateT("Nickname"), ui->pszNick, + TranslateT("Unique ID"), ui->pszUID, + TranslateT("Status"), pci->TM_WordToString(si->pStatuses, ui->Status)); + + ti.lpszText = tszBuf; + } + + SendMessage(hwndToolTip, bNewTip ? TTM_ADDTOOL : TTM_UPDATETIPTEXT, 0, (LPARAM)&ti); + SendMessage(hwndToolTip, TTM_ACTIVATE, ti.lpszText != NULL, 0); + SendMessage(hwndToolTip, TTM_SETMAXTIPWIDTH, 0, 400); +} + +static LRESULT CALLBACK NicklistSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SESSION_INFO *si = (SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); + + switch (msg) { + case WM_ERASEBKGND: + { + HDC dc = (HDC)wParam; + if (dc == NULL) + return 0; + + int index = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); + if (index == LB_ERR || si->nUsersInNicklist <= 0) + return 0; + + int height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); + if (height == LB_ERR) + return 0; + + RECT rc = { 0 }; + GetClientRect(hwnd, &rc); + + int items = si->nUsersInNicklist - index; + if (rc.bottom - rc.top > items * height) { + rc.top = items * height; + FillRect(dc, &rc, pci->hListBkgBrush); + } + } + return 1; + + case WM_KEYDOWN: + if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) + PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return TRUE; + } + break; + + case WM_RBUTTONDOWN: + SendMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam); + break; + + case WM_RBUTTONUP: + SendMessage(hwnd, WM_LBUTTONUP, wParam, lParam); + break; + + case WM_MEASUREITEM: + { + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; + if (mis->CtlType == ODT_MENU) + return Menu_MeasureItem(lParam); + } + return FALSE; + + case WM_DRAWITEM: + { + DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; + if (dis->CtlType == ODT_MENU) + return Menu_DrawItem(lParam); + } + return FALSE; + + case WM_CONTEXTMENU: + TVHITTESTINFO hti; + { + int height = 0; + hti.pt.x = GET_X_LPARAM(lParam); + hti.pt.y = GET_Y_LPARAM(lParam); + if (hti.pt.x == -1 && hti.pt.y == -1) { + int index = SendMessage(hwnd, LB_GETCURSEL, 0, 0); + int top = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); + height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); + hti.pt.x = 4; + hti.pt.y = (index - top)*height + 1; + } + else ScreenToClient(hwnd, &hti.pt); + + int item = LOWORD(SendDlgItemMessage(GetParent(hwnd), IDC_LIST, LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); + USERINFO *ui = pci->SM_GetUserFromIndex(si->ptszID, si->pszModule, item); + if (ui) { + USERINFO uinew; + memcpy(&uinew, ui, sizeof(USERINFO)); + if (hti.pt.x == -1 && hti.pt.y == -1) + hti.pt.y += height - 4; + ClientToScreen(hwnd, &hti.pt); + + HMENU hMenu = 0; + UINT uID = CreateGCMenu(hwnd, &hMenu, 0, hti.pt, si, uinew.pszUID, uinew.pszNick); + switch (uID) { + case 0: + break; + + case ID_MESS: + pci->DoEventHookAsync(GetParent(hwnd), si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, 0); + break; + + default: + pci->DoEventHookAsync(GetParent(hwnd), si->ptszID, si->pszModule, GC_USER_NICKLISTMENU, ui->pszUID, NULL, (LPARAM)uID); + break; + } + DestroyGCMenu(&hMenu, 1); + return TRUE; + } + } + break; + + case WM_MOUSEMOVE: + POINT pt = { LOWORD(lParam), HIWORD(lParam) }; + RECT clientRect; + GetClientRect(hwnd, &clientRect); + BOOL bInClient = PtInRect(&clientRect, pt); + // Mouse capturing/releasing + if (bInClient && GetCapture() != hwnd) + SetCapture(hwnd); + else if (!bInClient) + ReleaseCapture(); + + if (bInClient) { + // hit test item under mouse + DWORD nItemUnderMouse = (DWORD)SendMessage(hwnd, LB_ITEMFROMPOINT, 0, lParam); + if (HIWORD(nItemUnderMouse) == 1) + nItemUnderMouse = (DWORD)(-1); + else + nItemUnderMouse &= 0xFFFF; + + ProcessNickListHovering(hwnd, (int)nItemUnderMouse, si); + } + else ProcessNickListHovering(hwnd, -1, NULL); + break; + } + + return mir_callNextSubclass(hwnd, NicklistSubclassProc, msg, wParam, lParam); +} + +static int RestoreWindowPosition(HWND hwnd, MCONTACT hContact, char * szModule, char * szNamePrefix, UINT showCmd) +{ + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + GetWindowPlacement(hwnd, &wp); + + char szSettingName[64]; + mir_snprintf(szSettingName, "%sx", szNamePrefix); + int x = db_get_dw(hContact, szModule, szSettingName, -1); + mir_snprintf(szSettingName, "%sy", szNamePrefix); + int y = (int)db_get_dw(hContact, szModule, szSettingName, -1); + mir_snprintf(szSettingName, "%swidth", szNamePrefix); + int width = db_get_dw(hContact, szModule, szSettingName, -1); + mir_snprintf(szSettingName, "%sheight", szNamePrefix); + int height = db_get_dw(hContact, szModule, szSettingName, -1); + + if (x == -1) + return 0; + + wp.rcNormalPosition.left = x; + wp.rcNormalPosition.top = y; + wp.rcNormalPosition.right = wp.rcNormalPosition.left + width; + wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + height; + wp.showCmd = showCmd; + SetWindowPlacement(hwnd, &wp); + return 1; +} + +int GetTextPixelSize(wchar_t* pszText, HFONT hFont, BOOL bWidth) +{ + if (!pszText || !hFont) + return 0; + + HDC hdc = GetDC(NULL); + HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); + RECT rc = { 0 }; + DrawText(hdc, pszText, -1, &rc, DT_CALCRECT); + SelectObject(hdc, hOldFont); + ReleaseDC(NULL, hdc); + return bWidth ? rc.right - rc.left : rc.bottom - rc.top; +} + +static void __cdecl phase2(void * lParam) +{ + SESSION_INFO *si = (SESSION_INFO*)lParam; + Sleep(30); + if (si && si->hWnd) + PostMessage(si->hWnd, GC_REDRAWLOG3, 0, 0); +} + +INT_PTR CALLBACK RoomWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + SESSION_INFO *si = (SESSION_INFO*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + RECT rc; + + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + HWND hNickList = GetDlgItem(hwndDlg, IDC_LIST); + si = (SESSION_INFO*)lParam; + si->pAccPropServicesForNickList = NULL; + CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER, IID_IAccPropServices, (LPVOID *)si->pAccPropServicesForNickList); + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)si); + mir_subclassWindow(GetDlgItem(hwndDlg, IDC_SPLITTERX), SplitterSubclassProc); + mir_subclassWindow(GetDlgItem(hwndDlg, IDC_SPLITTERY), SplitterSubclassProc); + mir_subclassWindow(hNickList, NicklistSubclassProc); + mir_subclassWindow(GetDlgItem(hwndDlg, IDC_TAB), TabSubclassProc); + mir_subclassWindow(GetDlgItem(hwndDlg, IDC_LOG), LogSubclassProc); + mir_subclassWindow(GetDlgItem(hwndDlg, IDC_FILTER), ButtonSubclassProc); + mir_subclassWindow(GetDlgItem(hwndDlg, IDC_COLOR), ButtonSubclassProc); + mir_subclassWindow(GetDlgItem(hwndDlg, IDC_BKGCOLOR), ButtonSubclassProc); + mir_subclassWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), MessageSubclassProc); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SUBCLASSED, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, 1, 0); + int mask = (int)SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETEVENTMASK, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, mask | ENM_LINK | ENM_MOUSEEVENTS); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_LIMITTEXT, (WPARAM)sizeof(wchar_t) * 0x7FFFFFFF, 0); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM)& reOleCallback); + + si->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP | SBT_TOOLTIPS, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL); + SendMessage(si->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0); + TabCtrl_SetMinTabWidth(GetDlgItem(hwndDlg, IDC_TAB), 80); + TabCtrl_SetImageList(GetDlgItem(hwndDlg, IDC_TAB), hIconsList); + + // restore previous tabs + if (g_Settings.bTabsEnable && g_Settings.TabRestore) { + TABLIST *node = g_TabList; + while (node) { + SESSION_INFO *s = pci->SM_FindSession(node->pszID, node->pszModule); + if (s) + SendMessage(hwndDlg, GC_ADDTAB, -1, (LPARAM)s); + + node = node->next; + } + } + + TabM_RemoveAll(); + + EnableWindow(GetDlgItem(hwndDlg, IDC_SMILEY), TRUE); + + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_HIDESELECTION, TRUE, 0); + + SendMessage(hwndDlg, GC_SETWNDPROPS, 0, 0); + SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0); + SendMessage(hwndDlg, GC_UPDATETITLE, 0, 0); + SendMessage(hwndDlg, GC_SETWINDOWPOS, 0, 0); + } + break; + + case GC_SETWNDPROPS: + { + // LoadGlobalSettings(); !!!!!!!!!!!!!!!!!!!!!! + InitButtons(hwndDlg, si); + + // stupid hack to make icons show. I dunno why this is needed currently + MODULEINFO *mi = pci->MM_FindModule(si->pszModule); + HICON hIcon = si->wStatus == ID_STATUS_ONLINE ? mi->hOnlineIcon : mi->hOfflineIcon; + if (!hIcon) { + pci->MM_IconsChanged(); + hIcon = (si->wStatus == ID_STATUS_ONLINE) ? mi->hOnlineIcon : mi->hOfflineIcon; + } + + SendMessage(hwndDlg, GC_FIXTABICONS, 0, 0); + SendMessage(si->hwndStatus, SB_SETICON, 0, (LPARAM)hIcon); + Window_SetIcon_IcoLib(hwndDlg, GetIconHandle("window")); + + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETBKGNDCOLOR, 0, g_Settings.crLogBackground); + + if (g_Settings.bTabsEnable) { + LONG_PTR mask = GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TAB), GWL_STYLE); + if (g_Settings.TabsAtBottom) + mask |= TCS_BOTTOM; + else + mask &= ~TCS_BOTTOM; + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TAB), GWL_STYLE, (LONG_PTR)mask); + } + { + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = CFM_COLOR | CFM_BOLD | CFM_UNDERLINE | CFM_BACKCOLOR; + cf.dwEffects = 0; + cf.crTextColor = g_Settings.MessageAreaColor; + cf.crBackColor = (COLORREF)db_get_dw(NULL, CHAT_MODULE, "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETBKGNDCOLOR, 0, db_get_dw(NULL, CHAT_MODULE, "ColorMessageBG", GetSysColor(COLOR_WINDOW))); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM)g_Settings.MessageAreaFont, MAKELPARAM(TRUE, 0)); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&cf); + + // nicklist + int ih = GetTextPixelSize(L"AQGglo", g_Settings.UserListFont, FALSE); + int ih2 = GetTextPixelSize(L"AQGglo", g_Settings.UserListHeadingsFont, FALSE); + int height = db_get_b(NULL, CHAT_MODULE, "NicklistRowDist", 12); + int font = ih > ih2 ? ih : ih2; + + // make sure we have space for icon! + if (g_Settings.bShowContactStatus) + font = font > 16 ? font : 16; + + SendDlgItemMessage(hwndDlg, IDC_LIST, LB_SETITEMHEIGHT, 0, (LPARAM)height > font ? height : font); + InvalidateRect(GetDlgItem(hwndDlg, IDC_LIST), NULL, TRUE); + } + SendMessage(hwndDlg, WM_SIZE, 0, 0); + SendMessage(hwndDlg, GC_REDRAWLOG2, 0, 0); + } + break; + + case GC_UPDATETITLE: + { + wchar_t szTemp[100]; + switch (si->iType) { + case GCW_CHATROOM: + mir_snwprintf(szTemp, + (si->nUsersInNicklist == 1) ? TranslateT("%s: chat room (%u user)") : TranslateT("%s: chat room (%u users)"), + si->ptszName, si->nUsersInNicklist); + break; + case GCW_PRIVMESS: + mir_snwprintf(szTemp, + (si->nUsersInNicklist == 1) ? TranslateT("%s: message session") : TranslateT("%s: message session (%u users)"), + si->ptszName, si->nUsersInNicklist); + break; + case GCW_SERVER: + mir_snwprintf(szTemp, L"%s: Server", si->ptszName); + break; + } + SetWindowText(hwndDlg, szTemp); + } + break; + + case GC_UPDATESTATUSBAR: + { + MODULEINFO *mi = pci->MM_FindModule(si->pszModule); + wchar_t* ptszDispName = mi->ptszModDispName; + int x = 12; + x += GetTextPixelSize(ptszDispName, (HFONT)SendMessage(si->hwndStatus, WM_GETFONT, 0, 0), TRUE); + x += GetSystemMetrics(SM_CXSMICON); + int iStatusbarParts[2] = { x, -1 }; + SendMessage(si->hwndStatus, SB_SETPARTS, 2, (LPARAM)&iStatusbarParts); + + // stupid hack to make icons show. I dunno why this is needed currently + HICON hIcon = si->wStatus == ID_STATUS_ONLINE ? mi->hOnlineIcon : mi->hOfflineIcon; + if (!hIcon) { + pci->MM_IconsChanged(); + hIcon = si->wStatus == ID_STATUS_ONLINE ? mi->hOnlineIcon : mi->hOfflineIcon; + } + + SendMessage(si->hwndStatus, SB_SETICON, 0, (LPARAM)hIcon); + SendMessage(hwndDlg, GC_FIXTABICONS, 0, 0); + + SendMessage(si->hwndStatus, SB_SETTEXT, 0, (LPARAM)ptszDispName); + + SendMessage(si->hwndStatus, SB_SETTEXT, 1, (LPARAM)(si->ptszStatusbarText ? si->ptszStatusbarText : L"")); + SendMessage(si->hwndStatus, SB_SETTIPTEXT, 1, (LPARAM)(si->ptszStatusbarText ? si->ptszStatusbarText : L"")); + } + return TRUE; + + case GC_SETWINDOWPOS: + { + SESSION_INFO *pActive = pci->GetActiveSession(); + RECT screen; + int savePerContact = db_get_b(NULL, CHAT_MODULE, "SavePosition", 0); + + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0); + + if (si->iX) { + wp.rcNormalPosition.left = si->iX; + wp.rcNormalPosition.top = si->iY; + wp.rcNormalPosition.right = wp.rcNormalPosition.left + si->iWidth; + wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + si->iHeight; + wp.showCmd = SW_HIDE; + SetWindowPlacement(hwndDlg, &wp); + break; + } + if (savePerContact) { + if (RestoreWindowPosition(hwndDlg, g_Settings.bTabsEnable ? NULL : si->hContact, CHAT_MODULE, "room", SW_HIDE)) + break; + SetWindowPos(hwndDlg, 0, (screen.right - screen.left) / 2 - (550) / 2, (screen.bottom - screen.top) / 2 - (400) / 2, (550), (400), SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); + } + else SetWindowPos(hwndDlg, 0, (screen.right - screen.left) / 2 - (550) / 2, (screen.bottom - screen.top) / 2 - (400) / 2, (550), (400), SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); + + if (!g_Settings.bTabsEnable && pActive && pActive->hWnd && db_get_b(NULL, CHAT_MODULE, "CascadeWindows", 1)) { + RECT rcThis, rcNew; + int dwFlag = SWP_NOZORDER | SWP_NOACTIVATE; + if (!IsWindowVisible((HWND)wParam)) + dwFlag |= SWP_HIDEWINDOW; + + GetWindowRect(hwndDlg, &rcThis); + GetWindowRect(pActive->hWnd, &rcNew); + + int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME); + SetWindowPos((HWND)hwndDlg, 0, rcNew.left + offset, rcNew.top + offset, rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, dwFlag); + } + } + break; + + case GC_SAVEWNDPOS: + { + WINDOWPLACEMENT wp = { 0 }; + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + + g_Settings.iX = wp.rcNormalPosition.left; + g_Settings.iY = wp.rcNormalPosition.top; + g_Settings.iWidth = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + g_Settings.iHeight = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + + if (!lParam) { + si->iX = g_Settings.iX; + si->iY = g_Settings.iY; + si->iWidth = g_Settings.iWidth; + si->iHeight = g_Settings.iHeight; + } + } + break; + + case WM_SIZE: + if (wParam == SIZE_MAXIMIZED) + PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0); + + if (!IsIconic(hwndDlg)) { + SendMessage(si->hwndStatus, WM_SIZE, 0, 0); + + Utils_ResizeDialog(hwndDlg, g_hInst, MAKEINTRESOURCEA(IDD_CHANNEL), RoomWndResize, (LPARAM)si); + + InvalidateRect(si->hwndStatus, NULL, TRUE); + RedrawWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE); + RedrawWindow(GetDlgItem(hwndDlg, IDOK), NULL, NULL, RDW_INVALIDATE); + SendMessage(hwndDlg, GC_SAVEWNDPOS, 0, 1); + } + break; + + case GC_REDRAWWINDOW: + InvalidateRect(hwndDlg, NULL, TRUE); + break; + + case GC_REDRAWLOG: + si->LastTime = 0; + if (si->pLog) { + LOGINFO * pLog = si->pLog; + if (si->iEventCount > 60) { + int index = 0; + while (index < 59) { + if (pLog->next == NULL) + break; + + pLog = pLog->next; + if (si->iType != GCW_CHATROOM || !si->bFilterEnabled || (si->iLogFilterFlags&pLog->iType) != 0) + index++; + } + Log_StreamInEvent(hwndDlg, pLog, si, TRUE, FALSE); + mir_forkthread(phase2, si); + } + else Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, FALSE); + } + else SendMessage(hwndDlg, GC_CONTROL_MSG, WINDOW_CLEARLOG, 0); + break; + + case GC_REDRAWLOG2: + si->LastTime = 0; + if (si->pLog) + Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, FALSE); + break; + + case GC_REDRAWLOG3: + si->LastTime = 0; + if (si->pLog) + Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, TRUE); + break; + + case GC_ADDLOG: + if (si->pLogEnd) + Log_StreamInEvent(hwndDlg, si->pLog, si, FALSE, FALSE); + else + SendMessage(hwndDlg, GC_CONTROL_MSG, WINDOW_CLEARLOG, 0); + break; + + case GC_SWITCHNEXTTAB: + { + int total = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1 && total != -1 && total != 1) { + if (i < total - 1) + i++; + else + i = 0; + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), i); + PostMessage(hwndDlg, GC_TABCLICKED, 0, 0); + } + } + break; + + case GC_SWITCHPREVTAB: + { + int total = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1 && total != -1 && total != 1) { + if (i > 0) + i--; + else + i = total - 1; + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), i); + PostMessage(hwndDlg, GC_TABCLICKED, 0, 0); + } + } + break; + + case GC_SWITCHTAB: + { + int total = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1 && total != -1 && total != 1 && i != lParam && total > lParam) { + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), lParam); + PostMessage(hwndDlg, GC_TABCLICKED, 0, 0); + } + } + break; + + case GC_REMOVETAB: + { + SESSION_INFO* s2; + int i = -1; + SESSION_INFO* s1 = (SESSION_INFO*)lParam; + int tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + + if (s1) { + if (tabId) { + for (i = 0; i < tabId; i++) { + int ii; + TCITEM tci = { 0 }; + tci.mask = TCIF_PARAM; + ii = TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + if (ii != -1) { + s2 = (SESSION_INFO*)tci.lParam; + if (s1 == s2) + goto END_REMOVETAB; + } + } + } + } + else i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + + END_REMOVETAB: + if (i != -1 && i < tabId) { + TCITEM id = { 0 }; + SESSION_INFO *s; + TabCtrl_DeleteItem(GetDlgItem(hwndDlg, IDC_TAB), i); + id.mask = TCIF_PARAM; + if (!TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &id)) { + if (!TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i - 1, &id)) { + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + break; + } + } + + s = (SESSION_INFO*)id.lParam; + if (s) + pci->ShowRoom(s, (WPARAM)WINDOW_VISIBLE, wParam == 1 ? FALSE : TRUE); + } + } + break; + + case GC_ADDTAB: + { + TCITEM tci; + int tabId; + WORD w = 0; + int i = 0; + int indexfound = -1; + int lastlocked = -1; + BOOL bFound = FALSE; + SESSION_INFO* s2; + SESSION_INFO* s1 = (SESSION_INFO*)lParam; + + tci.mask = TCIF_PARAM; + tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + + // does the tab already exist? + for (i = 0; i < tabId; i++) { + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + s2 = (SESSION_INFO*)tci.lParam; + if (s2) { + if (s1 == s2 && !bFound) { + if (!bFound) { + bFound = TRUE; + indexfound = i; + } + } + + w = db_get_w(s2->hContact, s2->pszModule, "TabPosition", 0); + if (w) + lastlocked = (int)w; + } + } + + w = 0; + + if (!bFound) { // create a new tab + int insertat; + wchar_t szTemp[30]; + + mir_wstrncpy(szTemp, s1->ptszName, 21); + if (mir_wstrlen(s1->ptszName) > 20) + mir_wstrncpy(szTemp + 20, L"...", 4); + + tci.mask = TCIF_TEXT | TCIF_PARAM; + tci.pszText = szTemp; + tci.lParam = lParam; + + // determine insert position + w = db_get_w(s1->hContact, s1->pszModule, "TabPosition", 0); + if (wParam == -1) + insertat = w == 0 ? tabId : (int)w - 1; + else + insertat = (int)wParam; + + w = TabCtrl_InsertItem(GetDlgItem(hwndDlg, IDC_TAB), insertat, &tci); + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s1); + } + + if (wParam == -1) { + if (bFound) + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), indexfound); + else + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), w); + } + } + break; + + case GC_FIXTABICONS: + { + SESSION_INFO *s = (SESSION_INFO*)lParam; + if (s) { + int tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (int i = 0; i < tabId; i++) { + TCITEM tci; + tci.mask = TCIF_PARAM | TCIF_IMAGE; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + SESSION_INFO *s2 = (SESSION_INFO*)tci.lParam; + if (s2 && s == s2) { + int image = 0; + if (!(s2->wState & GC_EVENT_HIGHLIGHT)) { + MODULEINFO *mi = pci->MM_FindModule(s2->pszModule); + image = (s2->wStatus == ID_STATUS_ONLINE) ? mi->OnlineIconIndex : mi->OfflineIconIndex; + if (s2->wState & STATE_TALK) + image++; + } + + if (tci.iImage != image) { + tci.mask = TCIF_IMAGE; + tci.iImage = image; + TabCtrl_SetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + } + } + } + } + else RedrawWindow(GetDlgItem(hwndDlg, IDC_TAB), NULL, NULL, RDW_INVALIDATE); + } + break; + + case GC_SETMESSAGEHIGHLIGHT: + { + SESSION_INFO *s = (SESSION_INFO*)lParam; + if (s) { + int tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (int i = 0; i < tabId; i++) { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + SESSION_INFO *s2 = (SESSION_INFO*)tci.lParam; + if (s2 && s == s2) { // highlight + s2->wState |= GC_EVENT_HIGHLIGHT; + if (pci->SM_FindSession(si->ptszID, si->pszModule) == s2) + si->wState = s2->wState; + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s2); + if (g_Settings.bFlashWindowHighlight && GetActiveWindow() != hwndDlg && GetForegroundWindow() != hwndDlg) + SetTimer(hwndDlg, TIMERID_FLASHWND, 900, NULL); + break; + } + } + } + else RedrawWindow(GetDlgItem(hwndDlg, IDC_TAB), NULL, NULL, RDW_INVALIDATE); + } + break; + + case GC_SETTABHIGHLIGHT: + { + SESSION_INFO *s = (SESSION_INFO*)lParam; + if (s) { + int tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (int i = 0; i < tabId; i++) { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + SESSION_INFO *s2 = (SESSION_INFO*)tci.lParam; + if (s2 && s == s2) { // highlight + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s2); + if (g_Settings.bFlashWindow && GetActiveWindow() != hwndDlg && GetForegroundWindow() != hwndDlg) + SetTimer(hwndDlg, TIMERID_FLASHWND, 900, NULL); + break; + } + } + } + else RedrawWindow(GetDlgItem(hwndDlg, IDC_TAB), NULL, NULL, RDW_INVALIDATE); + } + break; + + case GC_TABCHANGE: + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam); + PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0); + break; + + case GC_TABCLICKED: + { + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1) { + TCITEM id = { 0 }; + id.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &id); + SESSION_INFO *s = (SESSION_INFO*)id.lParam; + if (s) { + if (s->wState & STATE_TALK) { + s->wState &= ~STATE_TALK; + db_set_w(s->hContact, s->pszModule, "ApparentMode", (LPARAM)0); + } + + if (s->wState & GC_EVENT_HIGHLIGHT) { + s->wState &= ~GC_EVENT_HIGHLIGHT; + + if (pcli->pfnGetEvent(s->hContact, 0)) + pcli->pfnRemoveEvent(s->hContact, GC_FAKE_EVENT); + } + + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s); + if (!s->hWnd) { + pci->ShowRoom(s, (WPARAM)WINDOW_VISIBLE, TRUE); + SendMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0); + } + } + } + } + break; + + case GC_DROPPEDTAB: + { + int begin = (int)lParam; + int end = (int)wParam; + if (begin == end) + break; + + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), begin, &tci); + SESSION_INFO *s = (SESSION_INFO*)tci.lParam; + if (s) { + TabCtrl_DeleteItem(GetDlgItem(hwndDlg, IDC_TAB), begin); + + SendMessage(hwndDlg, GC_ADDTAB, end, (LPARAM)s); + + // fix the "fixed" positions + int tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (int i = 0; i < tabId; i++) { + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + s = (SESSION_INFO*)tci.lParam; + if (s && s->hContact && db_get_w(s->hContact, s->pszModule, "TabPosition", 0) != 0) + db_set_w(s->hContact, s->pszModule, "TabPosition", (WORD)(i + 1)); + } + } + } + break; + + case GC_SESSIONNAMECHANGE: + { + SESSION_INFO* s1 = (SESSION_INFO*)lParam; + int tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)); + for (int i = 0; i < tabId; i++) { + TCITEM tci; + tci.mask = TCIF_PARAM; + int j = TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + if (j != -1) { + SESSION_INFO *s2 = (SESSION_INFO*)tci.lParam; + if (s1 == s2) { + tci.mask = TCIF_TEXT; + tci.pszText = s1->ptszName; + TabCtrl_SetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + } + } + } + } + break; + + case WM_CTLCOLORLISTBOX: + SetBkColor((HDC)wParam, g_Settings.crUserListBGColor); + return (INT_PTR)pci->hListBkgBrush; + + case WM_MEASUREITEM: + { + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; + if (mis->CtlType == ODT_MENU) + return Menu_MeasureItem(lParam); + + int ih = GetTextPixelSize(L"AQGgl'", g_Settings.UserListFont, FALSE); + int ih2 = GetTextPixelSize(L"AQGg'", g_Settings.UserListHeadingsFont, FALSE); + int font = ih > ih2 ? ih : ih2; + int height = db_get_b(NULL, CHAT_MODULE, "NicklistRowDist", 12); + + // make sure we have space for icon! + if (g_Settings.bShowContactStatus) + font = font > 16 ? font : 16; + + mis->itemHeight = height > font ? height : font; + } + return TRUE; + + case WM_DRAWITEM: + { + DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; + if (dis->CtlType == ODT_MENU) + return Menu_DrawItem(lParam); + + if (dis->CtlID == IDC_LIST) { + int index = dis->itemID; + USERINFO *ui = pci->SM_GetUserFromIndex(si->ptszID, si->pszModule, index); + if (ui) { + int x_offset = 2; + + int height = dis->rcItem.bottom - dis->rcItem.top; + if (height & 1) + height++; + + int offset = (height == 10) ? 0 : height / 2 - 4; + HFONT hFont = (ui->iStatusEx == 0) ? g_Settings.UserListFont : g_Settings.UserListHeadingsFont; + HFONT hOldFont = (HFONT)SelectObject(dis->hDC, hFont); + SetBkMode(dis->hDC, TRANSPARENT); + + if (dis->itemAction == ODA_FOCUS && dis->itemState & ODS_SELECTED) + FillRect(dis->hDC, &dis->rcItem, pci->hListSelectedBkgBrush); + else //if (dis->itemState & ODS_INACTIVE) + FillRect(dis->hDC, &dis->rcItem, pci->hListBkgBrush); + + if (g_Settings.bShowContactStatus && g_Settings.bContactStatusFirst && ui->ContactStatus) { + HICON hIcon = Skin_LoadProtoIcon(si->pszModule, ui->ContactStatus); + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 3, hIcon, 16, 16, 0, NULL, DI_NORMAL); + x_offset += 18; + } + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset, pci->SM_GetStatusIcon(si, ui), 10, 10, 0, NULL, DI_NORMAL); + x_offset += 12; + if (g_Settings.bShowContactStatus && !g_Settings.bContactStatusFirst && ui->ContactStatus) { + HICON hIcon = Skin_LoadProtoIcon(si->pszModule, ui->ContactStatus); + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 3, hIcon, 16, 16, 0, NULL, DI_NORMAL); + x_offset += 18; + } + + SetTextColor(dis->hDC, ui->iStatusEx == 0 ? g_Settings.crUserListColor : g_Settings.crUserListHeadingsColor); + TextOut(dis->hDC, dis->rcItem.left + x_offset, dis->rcItem.top, ui->pszNick, (int)mir_wstrlen(ui->pszNick)); + SelectObject(dis->hDC, hOldFont); + + if (si->pAccPropServicesForNickList) { + wchar_t *nick = mir_wstrdup(ui->pszNick); + si->pAccPropServicesForNickList->SetHwndPropStr(GetDlgItem(hwndDlg, IDC_LIST), OBJID_CLIENT, dis->itemID + 1, PROPID_ACC_NAME, nick); + mir_free(nick); + } + } + return TRUE; + } + } + break; + + case GC_UPDATENICKLIST: + { + int i = SendDlgItemMessage(hwndDlg, IDC_LIST, LB_GETTOPINDEX, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_LIST, LB_SETCOUNT, si->nUsersInNicklist, 0); + SendDlgItemMessage(hwndDlg, IDC_LIST, LB_SETTOPINDEX, i, 0); + SendMessage(hwndDlg, GC_UPDATETITLE, 0, 0); + } + break; + + case GC_CONTROL_MSG: + switch (wParam) { + case SESSION_OFFLINE: + SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0); + SendMessage(si->hWnd, GC_UPDATENICKLIST, 0, 0); + return TRUE; + + case SESSION_ONLINE: + SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0); + return TRUE; + + case WINDOW_HIDDEN: + SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0); + return TRUE; + + case WINDOW_CLEARLOG: + SetDlgItemText(hwndDlg, IDC_LOG, L""); + return TRUE; + + case SESSION_TERMINATE: + SendMessage(hwndDlg, GC_SAVEWNDPOS, 0, 0); + if (db_get_b(NULL, CHAT_MODULE, "SavePosition", 0)) { + db_set_dw(si->hContact, CHAT_MODULE, "roomx", si->iX); + db_set_dw(si->hContact, CHAT_MODULE, "roomy", si->iY); + db_set_dw(si->hContact, CHAT_MODULE, "roomwidth", si->iWidth); + db_set_dw(si->hContact, CHAT_MODULE, "roomheight", si->iHeight); + } + if (pcli->pfnGetEvent(si->hContact, 0)) + pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); + si->wState &= ~STATE_TALK; + db_set_w(si->hContact, si->pszModule, "ApparentMode", 0); + SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0); + return TRUE; + + case WINDOW_MINIMIZE: + ShowWindow(hwndDlg, SW_MINIMIZE); + goto LABEL_SHOWWINDOW; + + case WINDOW_MAXIMIZE: + ShowWindow(hwndDlg, SW_MAXIMIZE); + goto LABEL_SHOWWINDOW; + + case SESSION_INITDONE: + if (db_get_b(NULL, CHAT_MODULE, "PopupOnJoin", 0) != 0) + return TRUE; + // fall through + case WINDOW_VISIBLE: + if (IsIconic(hwndDlg)) + ShowWindow(hwndDlg, SW_NORMAL); + LABEL_SHOWWINDOW: + SendMessage(hwndDlg, WM_SIZE, 0, 0); + SendMessage(hwndDlg, GC_REDRAWLOG, 0, 0); + SendMessage(hwndDlg, GC_UPDATENICKLIST, 0, 0); + SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0); + ShowWindow(hwndDlg, SW_SHOW); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + SetForegroundWindow(hwndDlg); + return TRUE; + } + break; + + case GC_SPLITTERMOVED: + { + POINT pt; + RECT rcLog; + BOOL bFormat = IsWindowVisible(GetDlgItem(hwndDlg, IDC_SMILEY)); + + static int x = 0; + + GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog); + if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SPLITTERX)) { + int oldSplitterX; + GetClientRect(hwndDlg, &rc); + pt.x = wParam; pt.y = 0; + ScreenToClient(hwndDlg, &pt); + + oldSplitterX = si->iSplitterX; + si->iSplitterX = rc.right - pt.x + 1; + if (si->iSplitterX < 35) + si->iSplitterX = 35; + if (si->iSplitterX > rc.right - rc.left - 35) + si->iSplitterX = rc.right - rc.left - 35; + g_Settings.iSplitterX = si->iSplitterX; + } + else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SPLITTERY)) { + int oldSplitterY; + GetClientRect(hwndDlg, &rc); + pt.x = 0; pt.y = wParam; + ScreenToClient(hwndDlg, &pt); + + oldSplitterY = si->iSplitterY; + si->iSplitterY = bFormat ? rc.bottom - pt.y + 1 : rc.bottom - pt.y + 20; + if (si->iSplitterY < 63) + si->iSplitterY = 63; + if (si->iSplitterY > rc.bottom - rc.top - 40) + si->iSplitterY = rc.bottom - rc.top - 40; + g_Settings.iSplitterY = si->iSplitterY; + } + if (x == 2) { + PostMessage(hwndDlg, WM_SIZE, 0, 0); + x = 0; + } + else x++; + } + break; + + case GC_FIREHOOK: + if (lParam) { + GCHOOK *gch = (GCHOOK *)lParam; + NotifyEventHooks(pci->hSendEvent, 0, (WPARAM)gch); + if (gch->pDest) { + mir_free((void*)gch->pDest->ptszID); + mir_free((void*)gch->pDest->pszModule); + mir_free(gch->pDest); + } + mir_free((void*)gch->ptszText); + mir_free((void*)gch->ptszUID); + mir_free(gch); + } + break; + + case GC_CHANGEFILTERFLAG: + si->iLogFilterFlags = lParam; + break; + + case GC_SHOWFILTERMENU: + { + HWND hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER), hwndDlg, FilterWndProc, (LPARAM)si); + TranslateDialogDefault(hwnd); + GetWindowRect(GetDlgItem(hwndDlg, IDC_FILTER), &rc); + SetWindowPos(hwnd, HWND_TOP, rc.left - 85, (IsWindowVisible(GetDlgItem(hwndDlg, IDC_FILTER)) || IsWindowVisible(GetDlgItem(hwndDlg, IDC_BOLD))) ? rc.top - 206 : rc.top - 186, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + } + break; + + case GC_SHOWCOLORCHOOSER: + pci->ColorChooser(si, lParam == IDC_COLOR, hwndDlg, GetDlgItem(hwndDlg, IDC_MESSAGE), GetDlgItem(hwndDlg, lParam)); + break; + + case GC_SCROLLTOBOTTOM: + if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL) != 0) { + SCROLLINFO scroll = { 0 }; + scroll.cbSize = sizeof(scroll); + scroll.fMask = SIF_PAGE | SIF_RANGE; + GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &scroll); + + scroll.fMask = SIF_POS; + scroll.nPos = scroll.nMax - scroll.nPage + 1; + SetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &scroll, TRUE); + + CHARRANGE sel; + sel.cpMin = sel.cpMax = GetRichTextLength(GetDlgItem(hwndDlg, IDC_LOG)); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXSETSEL, 0, (LPARAM)&sel); + PostMessage(GetDlgItem(hwndDlg, IDC_LOG), WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0); + } + break; + + case WM_TIMER: + if (wParam == TIMERID_FLASHWND) + FlashWindow(hwndDlg, TRUE); + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) != WA_ACTIVE) + break; + + //fall through + case WM_MOUSEACTIVATE: + { + WINDOWPLACEMENT wp = { 0 }; + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + g_Settings.iX = wp.rcNormalPosition.left; + g_Settings.iY = wp.rcNormalPosition.top; + g_Settings.iWidth = wp.rcNormalPosition.right - wp.rcNormalPosition.left; + g_Settings.iHeight = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + + if (g_Settings.bTabsEnable) { + int i = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if (i != -1) { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &tci); + SESSION_INFO *s = (SESSION_INFO*)tci.lParam; + if (s) { + s->wState &= ~GC_EVENT_HIGHLIGHT; + s->wState &= ~STATE_TALK; + SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)s); + } + } + } + + if (uMsg != WM_ACTIVATE) + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + + pci->SetActiveSession(si->ptszID, si->pszModule); + + if (KillTimer(hwndDlg, TIMERID_FLASHWND)) + FlashWindow(hwndDlg, FALSE); + if (db_get_w(si->hContact, si->pszModule, "ApparentMode", 0) != 0) + db_set_w(si->hContact, si->pszModule, "ApparentMode", (LPARAM)0); + if (pcli->pfnGetEvent(si->hContact, 0)) + pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); + } + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) { + case NM_RCLICK: + if (((LPNMHDR)lParam)->idFrom == IDC_TAB) { + int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom); + if (i == -1) + break; + + TCHITTESTINFO tci = { 0 }; + tci.pt.x = (short)LOWORD(GetMessagePos()); + tci.pt.y = (short)HIWORD(GetMessagePos()); + tci.flags = TCHT_ONITEM; + ScreenToClient(GetDlgItem(hwndDlg, IDC_TAB), &tci.pt); + if ((i = TabCtrl_HitTest(((LPNMHDR)lParam)->hwndFrom, &tci)) == -1) + break; + + TCITEM id = { 0 }; + id.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &id); + SESSION_INFO *s = (SESSION_INFO*)id.lParam; + + ClientToScreen(GetDlgItem(hwndDlg, IDC_TAB), &tci.pt); + HMENU hSubMenu = GetSubMenu(g_hMenu, 5); + TranslateMenu(hSubMenu); + if (s) { + WORD w = db_get_w(s->hContact, s->pszModule, "TabPosition", 0); + if (w == 0) + CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_UNCHECKED); + else + CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_CHECKED); + } + else CheckMenuItem(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND | MF_UNCHECKED); + + switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, tci.pt.x, tci.pt.y, 0, hwndDlg, NULL)) { + case ID_CLOSE: + if (TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)) == i) + PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CLOSE, BN_CLICKED), 0); + else + TabCtrl_DeleteItem(GetDlgItem(hwndDlg, IDC_TAB), i); + break; + + case ID_CLOSEOTHER: + { + int tabId = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)) - 1; + if (tabId > 0) { + if (TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)) != i) + if (s) + pci->ShowRoom(s, WINDOW_VISIBLE, TRUE); + + for (tabId; tabId >= 0; tabId--) { + if (tabId == i) + continue; + + TabCtrl_DeleteItem(GetDlgItem(hwndDlg, IDC_TAB), tabId); + } + } + } + break; + + case ID_LOCKPOSITION: + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), i, &id); + if (s != 0) { + if (!(GetMenuState(hSubMenu, ID_LOCKPOSITION, MF_BYCOMMAND)&MF_CHECKED)) { + if (s->hContact) + db_set_w(s->hContact, s->pszModule, "TabPosition", (WORD)(i + 1)); + } + else db_unset(s->hContact, s->pszModule, "TabPosition"); + } + break; + } + } + break; + + case EN_MSGFILTER: + if (((LPNMHDR)lParam)->idFrom == IDC_LOG && ((MSGFILTER *)lParam)->msg == WM_RBUTTONUP) { + CHARRANGE sel, all = { 0, -1 }; + POINT pt; + UINT uID = 0; + HMENU hMenu = 0; + wchar_t pszWord[4096]; + + pt.x = (short)LOWORD(((ENLINK *)lParam)->lParam); + pt.y = (short)HIWORD(((ENLINK *)lParam)->lParam); + ClientToScreen(((LPNMHDR)lParam)->hwndFrom, &pt); + + // fixing stuff for searches + pszWord[0] = '\0'; + + POINTL ptl = { (LONG)pt.x, (LONG)pt.y }; + ScreenToClient(GetDlgItem(hwndDlg, IDC_LOG), (LPPOINT)&ptl); + long iCharIndex = SendDlgItemMessage(hwndDlg, IDC_LOG, EM_CHARFROMPOS, 0, (LPARAM)&ptl); + if (iCharIndex < 0) + break; + + long start = SendDlgItemMessage(hwndDlg, IDC_LOG, EM_FINDWORDBREAK, WB_LEFT, iCharIndex);//-iChars; + long end = SendDlgItemMessage(hwndDlg, IDC_LOG, EM_FINDWORDBREAK, WB_RIGHT, iCharIndex);//-iChars; + + if (end - start > 0) { + TEXTRANGE tr; + memset(&tr, 0, sizeof(TEXTRANGE)); + + CHARRANGE cr; + cr.cpMin = start; + cr.cpMax = end; + tr.chrg = cr; + tr.lpstrText = pszWord; + long iRes = SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETTEXTRANGE, 0, (LPARAM)&tr); + if (iRes > 0) + for (size_t iLen = mir_wstrlen(pszWord) - 1; wcschr(szTrimString, pszWord[iLen]); iLen--) + pszWord[iLen] = 0; + } + + uID = CreateGCMenu(hwndDlg, &hMenu, 1, pt, si, NULL, pszWord); + switch (uID) { + case 0: + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0); + break; + + case ID_COPYALL: + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)&sel); + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM)& all); + SendMessage(((LPNMHDR)lParam)->hwndFrom, WM_COPY, 0, 0); + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM)&sel); + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0); + break; + + case ID_CLEARLOG: + { + SESSION_INFO *s = pci->SM_FindSession(si->ptszID, si->pszModule); + if (s) { + SetDlgItemText(hwndDlg, IDC_LOG, L""); + pci->LM_RemoveAll(&s->pLog, &s->pLogEnd); + s->iEventCount = 0; + s->LastTime = 0; + si->iEventCount = 0; + si->LastTime = 0; + si->pLog = s->pLog; + si->pLogEnd = s->pLogEnd; + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0); + } + } + break; + + case ID_SEARCH_GOOGLE: + if (pszWord[0]) + Utils_OpenUrlT(CMStringW(FORMAT, L"http://www.google.com/search?q=%s", pszWord)); + + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0); + break; + + case ID_SEARCH_WIKIPEDIA: + if (pszWord[0]) + Utils_OpenUrlT(CMStringW(FORMAT, L"http://en.wikipedia.org/wiki/%s", pszWord)); + + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0); + break; + + default: + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0); + pci->DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_LOGMENU, NULL, NULL, (LPARAM)uID); + break; + } + DestroyGCMenu(&hMenu, 5); + } + break; + + case EN_LINK: + if (((LPNMHDR)lParam)->idFrom == IDC_LOG) { + switch (((ENLINK *)lParam)->msg) { + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + { + CHARRANGE sel; + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin != sel.cpMax) + break; + + TEXTRANGE tr; + tr.chrg = ((ENLINK *)lParam)->chrg; + tr.lpstrText = (LPTSTR)mir_alloc(sizeof(wchar_t)*(tr.chrg.cpMax - tr.chrg.cpMin + 1)); + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr); + + if (((ENLINK *)lParam)->msg == WM_RBUTTONDOWN) { + HMENU hSubMenu; + POINT pt; + + hSubMenu = GetSubMenu(g_hMenu, 2); + TranslateMenu(hSubMenu); + pt.x = (short)LOWORD(((ENLINK *)lParam)->lParam); + pt.y = (short)HIWORD(((ENLINK *)lParam)->lParam); + ClientToScreen(((NMHDR *)lParam)->hwndFrom, &pt); + switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) { + case ID_NEW: + Utils_OpenUrlT(tr.lpstrText); + break; + + case ID_CURR: + Utils_OpenUrlT(tr.lpstrText, false); + break; + + case ID_COPY: + { + HGLOBAL hData; + if (!OpenClipboard(hwndDlg)) + break; + EmptyClipboard(); + hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(wchar_t)*(mir_wstrlen(tr.lpstrText) + 1)); + mir_wstrcpy((wchar_t*)GlobalLock(hData), tr.lpstrText); + GlobalUnlock(hData); + SetClipboardData(CF_UNICODETEXT, hData); + CloseClipboard(); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + break; + } + } + mir_free(tr.lpstrText); + return TRUE; + } + + Utils_OpenUrlT(tr.lpstrText); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + mir_free(tr.lpstrText); + break; + } + } + } + break; + + case TTN_NEEDTEXT: + if (((LPNMHDR)lParam)->idFrom == (UINT_PTR)GetDlgItem(hwndDlg, IDC_LIST)) { + LPNMTTDISPINFO lpttd = (LPNMTTDISPINFO)lParam; + SESSION_INFO* parentdat = (SESSION_INFO*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + POINT p; + GetCursorPos(&p); + ScreenToClient(GetDlgItem(hwndDlg, IDC_LIST), &p); + int item = LOWORD(SendDlgItemMessage(hwndDlg, IDC_LIST, LB_ITEMFROMPOINT, 0, MAKELPARAM(p.x, p.y))); + USERINFO *ui = pci->SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, item); + if (ui != NULL) { + static wchar_t ptszBuf[1024]; + mir_snwprintf(ptszBuf, L"%s: %s\r\n%s: %s\r\n%s: %s", + TranslateT("Nickname"), ui->pszNick, + TranslateT("Unique ID"), ui->pszUID, + TranslateT("Status"), pci->TM_WordToString(parentdat->pStatuses, ui->Status)); + lpttd->lpszText = ptszBuf; + } + } + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_LIST: + if (HIWORD(wParam) == LBN_DBLCLK) { + TVHITTESTINFO hti; + hti.pt.x = (short)LOWORD(GetMessagePos()); + hti.pt.y = (short)HIWORD(GetMessagePos()); + ScreenToClient(GetDlgItem(hwndDlg, IDC_LIST), &hti.pt); + + int item = LOWORD(SendDlgItemMessage(hwndDlg, IDC_LIST, LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); + USERINFO *ui = pci->SM_GetUserFromIndex(si->ptszID, si->pszModule, item); + if (ui) { + if (GetKeyState(VK_SHIFT) & 0x8000) { + LRESULT lResult = (LRESULT)SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETSEL, 0, 0); + int start = LOWORD(lResult); + size_t dwNameLenMax = (mir_wstrlen(ui->pszUID) + 3); + wchar_t* pszName = (wchar_t*)alloca(sizeof(wchar_t) * dwNameLenMax); + if (start == 0) + mir_snwprintf(pszName, dwNameLenMax, L"%s: ", ui->pszUID); + else + mir_snwprintf(pszName, dwNameLenMax, L"%s ", ui->pszUID); + + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REPLACESEL, FALSE, (LPARAM)pszName); + PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0); + } + else pci->DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, 0); + } + + return TRUE; + } + + if (HIWORD(wParam) == LBN_KILLFOCUS) + RedrawWindow(GetDlgItem(hwndDlg, IDC_LIST), NULL, NULL, RDW_INVALIDATE); + break; + + case IDOK: + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDOK))) { + ptrA pszRtf(Message_GetFromStream(hwndDlg, si)); + if (pszRtf == NULL) + break; + + MODULEINFO *mi = pci->MM_FindModule(si->pszModule); + if (mi == NULL) + break; + + pci->SM_AddCommand(si->ptszID, si->pszModule, pszRtf); + + CMStringW ptszText(ptrW(mir_utf8decodeW(pszRtf))); + pci->DoRtfToTags(ptszText, mi->nColorCount, mi->crColors); + ptszText.Trim(); + ptszText.Replace(L"%", L"%%"); + + if (mi->bAckMsg) { + EnableWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), FALSE); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETREADONLY, TRUE, 0); + } + else SetDlgItemText(hwndDlg, IDC_MESSAGE, L""); + + EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); + + pci->DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, ptszText, 0); + + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + } + break; + + case IDC_SHOWNICKLIST: + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST))) + break; + if (si->iType == GCW_SERVER) + break; + + si->bNicklistEnabled = !si->bNicklistEnabled; + + SendDlgItemMessage(hwndDlg, IDC_SHOWNICKLIST, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx(si->bNicklistEnabled ? "nicklist" : "nicklist2", FALSE)); + SendMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + break; + + case IDC_MESSAGE: + EnableWindow(GetDlgItem(hwndDlg, IDOK), GetRichTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) != 0); + break; + + case IDC_SMILEY: + GetWindowRect(GetDlgItem(hwndDlg, IDC_SMILEY), &rc); + + if (SmileyAddInstalled) { + SMADD_SHOWSEL3 smaddInfo = { sizeof(smaddInfo) }; + smaddInfo.hwndTarget = GetDlgItem(hwndDlg, IDC_MESSAGE); + smaddInfo.targetMessage = EM_REPLACESEL; + smaddInfo.targetWParam = TRUE; + smaddInfo.Protocolname = si->pszModule; + smaddInfo.Direction = 3; + smaddInfo.xPosition = rc.left + 3; + smaddInfo.yPosition = rc.top - 1; + smaddInfo.hContact = si->hContact; + smaddInfo.hwndParent = hwndDlg; + CallService(MS_SMILEYADD_SHOWSELECTION, 0, (LPARAM)&smaddInfo); + } + break; + + case IDC_HISTORY: + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_HISTORY))) { + MODULEINFO *pInfo = pci->MM_FindModule(si->pszModule); + if (pInfo) { + wchar_t szFile[MAX_PATH], szName[MAX_PATH], szFolder[MAX_PATH]; + wcsncpy_s(szName, (pInfo->ptszModDispName ? pInfo->ptszModDispName : _A2T(si->pszModule)), _TRUNCATE); + ValidateFilename(szName); + + mir_snwprintf(szFolder, L"%s\\%s", g_Settings.pszLogDir, szName); + mir_snwprintf(szName, L"%s.log", si->ptszID); + ValidateFilename(szName); + + mir_snwprintf(szFile, L"%s\\%s", szFolder, szName); + ShellExecute(hwndDlg, L"open", szFile, NULL, NULL, SW_SHOW); + } + } + break; + + case IDC_CLOSE: + SendMessage(hwndDlg, GC_REMOVETAB, 0, 0); + break; + + case IDC_CHANMGR: + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHANMGR))) + pci->DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_CHANMGR, NULL, NULL, 0); + break; + + case IDC_FILTER: + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FILTER))) + break; + + si->bFilterEnabled = !si->bFilterEnabled; + SendDlgItemMessage(hwndDlg, IDC_FILTER, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIconEx(si->bFilterEnabled ? "filter" : "filter2", FALSE)); + if (si->bFilterEnabled && db_get_b(NULL, CHAT_MODULE, "RightClickFilter", 0) == 0) { + SendMessage(hwndDlg, GC_SHOWFILTERMENU, 0, 0); + break; + } + SendMessage(hwndDlg, GC_REDRAWLOG, 0, 0); + break; + + case IDC_BKGCOLOR: + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BKGCOLOR))) { + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwEffects = 0; + + if (IsDlgButtonChecked(hwndDlg, IDC_BKGCOLOR)) { + if (db_get_b(NULL, CHAT_MODULE, "RightClickFilter", 0) == 0) + SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_BKGCOLOR); + else if (si->bBGSet) { + cf.dwMask = CFM_BACKCOLOR; + cf.crBackColor = pci->MM_FindModule(si->pszModule)->crColors[si->iBG]; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + } + else { + cf.dwMask = CFM_BACKCOLOR; + cf.crBackColor = (COLORREF)db_get_dw(NULL, CHAT_MODULE, "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + } + break; + + case IDC_COLOR: + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_COLOR))) { + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwEffects = 0; + + if (IsDlgButtonChecked(hwndDlg, IDC_COLOR)) { + if (db_get_b(NULL, CHAT_MODULE, "RightClickFilter", 0) == 0) + SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_COLOR); + else if (si->bFGSet) { + cf.dwMask = CFM_COLOR; + cf.crTextColor = pci->MM_FindModule(si->pszModule)->crColors[si->iFG]; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + } + else { + cf.dwMask = CFM_COLOR; + cf.crTextColor = g_Settings.MessageAreaColor; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + } + break; + + case IDC_BOLD: + case IDC_ITALICS: + case IDC_UNDERLINE: + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE; + cf.dwEffects = 0; + + if (LOWORD(wParam) == IDC_BOLD && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BOLD))) + break; + if (LOWORD(wParam) == IDC_ITALICS && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_ITALICS))) + break; + if (LOWORD(wParam) == IDC_UNDERLINE && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_UNDERLINE))) + break; + if (IsDlgButtonChecked(hwndDlg, IDC_BOLD)) + cf.dwEffects |= CFE_BOLD; + if (IsDlgButtonChecked(hwndDlg, IDC_ITALICS)) + cf.dwEffects |= CFE_ITALIC; + if (IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE)) + cf.dwEffects |= CFE_UNDERLINE; + + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + break; + + case WM_KEYDOWN: + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + break; + + case WM_MOVE: + SendMessage(hwndDlg, GC_SAVEWNDPOS, 0, 1); + break; + + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO*)lParam; + mmi->ptMinTrackSize.x = si->iSplitterX + 43; + if (mmi->ptMinTrackSize.x < 350) + mmi->ptMinTrackSize.x = 350; + + mmi->ptMinTrackSize.y = si->iSplitterY + 80; + } + break; + + case WM_LBUTTONDBLCLK: + if (LOWORD(lParam) < 30) + PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0); + break; + + case WM_CLOSE: + if (g_Settings.bTabsEnable && g_Settings.TabRestore && lParam != 1) { + TCITEM id = { 0 }; + int j = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_TAB)) - 1; + id.mask = TCIF_PARAM; + for (j; j >= 0; j--) { + TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_TAB), j, &id); + SESSION_INFO *s = (SESSION_INFO*)id.lParam; + if (s) + TabM_AddTab(s->ptszID, s->pszModule); + } + } + + SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0); + break; + + case GC_CLOSEWINDOW: + if (g_Settings.bTabsEnable) + SM_SetTabbedWindowHwnd(0, 0); + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + SendMessage(hwndDlg, GC_SAVEWNDPOS, 0, 0); + + si->hWnd = NULL; + si->wState &= ~STATE_TALK; + DestroyWindow(si->hwndStatus); + si->hwndStatus = NULL; + + if (si->pAccPropServicesForNickList) si->pAccPropServicesForNickList->Release(); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + break; + } + return FALSE; +} diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp index ad192efb95..879a294db4 100644 --- a/src/core/stdmsg/src/msgdialog.cpp +++ b/src/core/stdmsg/src/msgdialog.cpp @@ -212,7 +212,6 @@ static void SetEditorText(HWND hwnd, const wchar_t* txt) SendMessage(hwnd, EM_SETSEL, -1, -1);
}
-#define EM_SUBCLASSED (WM_USER+0x101)
#define ENTERCLICKTIME 1000 //max time in ms during which a double-tap on enter will cause a send
static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
diff --git a/src/core/stdmsg/src/msgs.cpp b/src/core/stdmsg/src/msgs.cpp index c35b3821ef..ec7f46d28c 100644 --- a/src/core/stdmsg/src/msgs.cpp +++ b/src/core/stdmsg/src/msgs.cpp @@ -447,7 +447,7 @@ int LoadSendRecvMessageModule(void) return 0;
}
-int SplitmsgShutdown(void)
+void SplitmsgShutdown(void)
{
DestroyCursor(hCurSplitNS);
DestroyCursor(hCurHyperlinkHand);
@@ -461,7 +461,6 @@ int SplitmsgShutdown(void) FreeLibrary(hMsftEdit);
RichUtil_Unload();
msgQueue_destroy();
- return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/stdmsg/src/resource.h b/src/core/stdmsg/src/resource.h index 894ce3a063..872db1500b 100644 --- a/src/core/stdmsg/src/resource.h +++ b/src/core/stdmsg/src/resource.h @@ -2,7 +2,51 @@ // Microsoft Visual C++ generated include file.
// Used by resource.rc
//
+#define IDD_CHANNEL 101
#define IDD_MSGSENDERROR 102
+#define IDD_OPTIONS2 103
+#define IDD_OPTIONS1 104
+#define IDD_FILTER 105
+#define IDD_OPTIONSPOPUP 106
+#define IDI_BUNDERLINE 120
+#define IDI_BBOLD 121
+#define IDI_BITALICS 122
+#define IDI_BSMILEY 123
+#define IDI_TOPICBUT 124
+#define IDI_BKGCOLOR 125
+#define IDI_CHANMGR 126
+#define IDI_COLOR 127
+#define IDI_FILTER 128
+#define IDI_HISTORY 129
+#define IDI_NICKLIST 130
+#define IDI_JOIN 131
+#define IDI_PART 132
+#define IDI_QUIT 133
+#define IDI_KICK 134
+#define IDI_NICK 135
+#define IDI_NOTICE 136
+#define IDI_MESSAGE 137
+#define IDI_MESSAGEOUT 138
+#define IDI_TOPIC 139
+#define IDI_INFO 140
+#define IDI_ADDSTATUS 141
+#define IDI_REMSTATUS 142
+#define IDI_ACTION 143
+#define IDI_HIGHLIGHT 144
+#define IDI_BLANK 146
+#define IDI_TAG1 149
+#define IDI_TAG2 150
+#define IDR_MENU 151
+#define IDI_STATUS3 153
+#define IDI_STATUS2 154
+#define IDI_STATUS4 155
+#define IDI_STATUS1 156
+#define IDI_STATUS0 157
+#define IDI_STATUS5 158
+#define IDI_CLOSE 159
+#define IDI_OVERLAY 160
+#define IDI_NICKLIST2 161
+#define IDI_FILTER2 162
#define IDR_CONTEXT 180
#define IDC_DROP 183
#define IDC_HYPERLINKHAND 214
@@ -13,17 +57,36 @@ #define IDD_OPT_MSGTYPE 275
#define IDI_INCOMING 276
#define IDI_OUTGOING 277
-#define IDI_NOTICE 282
+#define IDI_EXCL 282
#define IDD_MODERNOPT_MSGDLG 288
#define IDD_MODERNOPT_MSGLOG 289
+
#define IDC_LOG 1001
#define IDC_MESSAGE 1002
+#define IDC_SPLITTERX 1003
#define IDC_AUTOCLOSE 1004
#define IDC_AUTOMIN 1005
#define IDC_DONOTSTEALFOCUS 1006
+#define IDC_SMILEY 1007
+#define IDC_SPLITTERY 1008
+#define IDC_SPLITTER 1008
#define IDC_NAME 1009
-#define IDC_SPLITTER 1017
-#define IDC_SHOWNAMES 1024
+#define IDC_BOLD 1010
+#define IDC_ITALICS 1011
+#define IDC_UNDERLINE 1012
+#define IDC_FILTER 1013
+#define IDC_CHANMGR 1014
+#define IDC_SHOWNICKLIST 1016
+#define IDC_COLOR 1017
+#define IDC_CHECKBOXES 1018
+#define IDC_BKGCOLOR 1019
+#define IDC_NICKLISTBKG 1021
+#define IDC_HISTORY 1022
+#define IDC_CLOSE 1023
+#define IDC_NICKROW 1024
+#define IDC_LOGLIMIT 1024
+#define IDC_NICKROW2 1025
+#define IDC_SHOWNAMES 1026
#define IDC_SHOWSENDBTN 1029
#define IDC_SHOWLOGICONS 1032
#define IDC_SHOWTIMES 1033
@@ -42,11 +105,51 @@ #define IDC_LOADTIMEN 1045
#define IDC_LOADTIMESPIN 1046
#define IDC_LOADTIME 1047
-#define IDC_STMINSOLD 1051
-#define IDC_DETAILS 1069
-#define IDC_ADD 1070
-#define IDC_USERMENU 1071
-#define IDC_HISTORY 1080
+#define IDC_STMINSOLD 1048
+#define IDC_SPIN1 1049
+#define IDC_SPIN2 1050
+#define IDC_SPIN3 1051
+#define IDC_SPIN4 1052
+#define IDC_FONTLIST 1053
+#define IDC_CHOOSEFONT 1054
+#define IDC_FONTCOLOR 1055
+#define IDC_MESSAGEBKG 1056
+#define IDC_LOGBKG 1057
+#define IDC_HIGHLIGHTWORDS 1058
+#define IDC_INSTAMP 1059
+#define IDC_OUTSTAMP 1060
+#define IDC_TIMESTAMP 1061
+#define IDC_FONTCHOOSE 1062
+#define IDC_LOGDIRECTORY 1063
+#define IDC_LIMIT 1064
+#define IDC_LOGTIMESTAMP 1065
+#define IDC_GROUP 1066
+#define IDC_RADIO1 1067
+#define IDC_RADIO2 1068
+#define IDC_RADIO3 1069
+#define IDC_TEXT 1064
+#define IDC_BKG 1065
+#define IDC_TIMEOUT 1067
+#define IDC_HIGHLIGHT 1068
+#define IDC_TEXTO 1069
+#define IDC_LOGGING 1069
+#define IDC_LIST 1072
+#define IDC_TAB 1074
+#define IDC_1 1075
+#define IDC_2 1076
+#define IDC_3 1077
+#define IDC_4 1078
+#define IDC_5 1079
+#define IDC_6 1080
+#define IDC_7 1081
+#define IDC_8 1082
+#define IDC_9 1083
+#define IDC_10 1084
+#define IDC_11 1085
+
+#define IDC_DETAILS 1469
+#define IDC_ADD 1470
+#define IDC_USERMENU 1471
#define IDC_STMSGLOGGROUP 1442
#define IDC_PROTOCOL 1580
#define IDC_ERRORTEXT 1596
@@ -72,6 +175,7 @@ #define IDC_TXT_TITLE1 1617
#define IDC_TXT_TITLE2 1618
#define IDC_TXT_TITLE3 1619
+
#define IDM_CUT 40000
#define IDM_COPY 40001
#define IDM_PASTE 40002
@@ -85,6 +189,25 @@ #define IDM_OPENLINK 40014
#define IDM_COPYLINK 40016
+#define ID_MESS 40021
+#define ID_NEW 40022
+#define ID_CURR 40023
+#define ID_COPY 40024
+#define ID_COPYALL 40026
+#define ID_CLEARLOG 40029
+#define ID_MESSAGE_UNDO 40033
+#define ID_MESSAGE_COPY 40034
+#define ID_MESSAGE_CUT 40035
+#define ID_MESSAGE_CLEAR 40037
+#define ID_MESSAGE_SELECTALL 40038
+#define ID_MESSAGE_REDO 40039
+#define ID_MESSAGE_PASTE 40030
+#define ID_CLOSE 40042
+#define ID_CLOSEOTHER 40043
+#define ID_LOCKPOSITION 40044
+#define ID_SEARCH_GOOGLE 40047
+#define ID_SEARCH_WIKIPEDIA 40048
+
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
diff --git a/src/core/stdmsg/src/srmm.cpp b/src/core/stdmsg/src/srmm.cpp index 397b84676c..434d561160 100644 --- a/src/core/stdmsg/src/srmm.cpp +++ b/src/core/stdmsg/src/srmm.cpp @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h"
int LoadSendRecvMessageModule(void);
-int SplitmsgShutdown(void);
+void SplitmsgShutdown(void);
CLIST_INTERFACE *pcli;
HINSTANCE g_hInst;
@@ -52,17 +52,20 @@ extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD) return &pluginInfo;
}
-extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_SRMM, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_SRMM, MIID_LAST };
extern "C" int __declspec(dllexport) Load(void)
{
mir_getLP(&pluginInfo);
pcli = Clist_GetInterface();
+ Load_ChatModule();
return LoadSendRecvMessageModule();
}
extern "C" int __declspec(dllexport) Unload(void)
{
- return SplitmsgShutdown();
+ SplitmsgShutdown();
+ Unload_ChatModule();
+ return 0;
}
diff --git a/src/core/stdmsg/src/stdafx.h b/src/core/stdmsg/src/stdafx.h index 35acfc8216..d08445ca47 100644 --- a/src/core/stdmsg/src/stdafx.h +++ b/src/core/stdmsg/src/stdafx.h @@ -28,6 +28,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <shlobj.h>
#include <commctrl.h>
#include <vssym32.h>
+
+#include <Initguid.h>
+#include <Oleacc.h>
#include <Uxtheme.h>
#include <malloc.h>
@@ -52,6 +55,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <m_userinfo.h>
#include <m_history.h>
#include <m_addcontact.h>
+#include <m_chat_int.h>
#include <m_message.h>
#include <m_file.h>
#include <m_icolib.h>
@@ -59,6 +63,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <m_timezones.h>
#include <m_avatars.h>
#include <m_metacontacts.h>
+#include <m_ieview.h>
+#include <m_smileyadd.h>
+#include <m_popup.h>
#include "cmdlist.h"
#include "msgs.h"
@@ -66,7 +73,95 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "richutil.h"
#include "version.h"
+#define EM_SUBCLASSED (WM_USER+0x101)
+#define EM_ACTIVATE (WM_USER+0x102)
+
extern HINSTANCE g_hInst;
extern HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand;
extern HANDLE hHookWinEvt, hHookWinPopup, hHookWinWrite;
extern CREOleCallback reOleCallback;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct TABLIST
+{
+ wchar_t *pszID;
+ char *pszModule;
+ TABLIST *next;
+};
+
+struct MODULEINFO : public GCModuleInfoBase
+{
+ int OnlineIconIndex;
+ int OfflineIconIndex;
+};
+
+struct SESSION_INFO : public GCSessionInfoBase
+{
+ int iX, iY;
+ IAccPropServices* pAccPropServicesForNickList;
+};
+
+struct LOGSTREAMDATA : public GCLogStreamDataBase {};
+
+struct GlobalLogSettings : public GlobalLogSettingsBase
+{
+ int iX, iY;
+ bool bTabsEnable, TabsAtBottom, TabCloseOnDblClick, TabRestore;
+
+ HFONT MessageAreaFont;
+ COLORREF MessageAreaColor;
+};
+
+extern GlobalLogSettings g_Settings;
+extern SESSION_INFO g_TabSession;
+extern CHAT_MANAGER saveCI;
+extern TABLIST *g_TabList;
+extern HMENU g_hMenu;
+extern HIMAGELIST hIconsList;
+
+extern HINSTANCE g_hInst;
+extern BOOL SmileyAddInstalled, PopupInstalled;
+
+//main.c
+void LoadIcons(void);
+void Unload_ChatModule();
+void Load_ChatModule();
+
+// log.c
+void Log_StreamInEvent(HWND hwndDlg, LOGINFO* lin, SESSION_INFO *si, BOOL bRedraw, BOOL bPhaseTwo);
+void ValidateFilename(wchar_t * filename);
+char* Log_CreateRtfHeader(MODULEINFO * mi);
+
+// window.c
+INT_PTR CALLBACK RoomWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+int GetTextPixelSize(wchar_t* pszText, HFONT hFont, BOOL bWidth);
+
+BOOL SM_SetTabbedWindowHwnd(SESSION_INFO *si, HWND hwnd);
+SESSION_INFO* SM_GetPrevWindow(SESSION_INFO *si);
+SESSION_INFO* SM_GetNextWindow(SESSION_INFO *si);
+
+// options.c
+int OptionsInitialize(WPARAM wParam, LPARAM lParam);
+void AddIcons(void);
+HICON LoadIconEx(const char *pszIcoLibName, bool big);
+HANDLE GetIconHandle(const char *pszIcolibName);
+
+// services.c
+void ShowRoom(SESSION_INFO *si, WPARAM wp, BOOL bSetForeground);
+
+// tools.c
+int GetColorIndex(const char* pszModule, COLORREF cr);
+void CheckColorsInModule(const char* pszModule);
+int GetRichTextLength(HWND hwnd);
+UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO *si, wchar_t* pszUID, wchar_t* pszWordText);
+void DestroyGCMenu(HMENU *hMenu, int iIndex);
+bool LoadMessageFont(LOGFONT *lf, COLORREF *colour);
+
+// message.c
+char* Message_GetFromStream(HWND hwndDlg, SESSION_INFO *si);
+
+BOOL TabM_AddTab(const wchar_t *pszID, const char* pszModule);
+BOOL TabM_RemoveAll(void);
+
+#pragma comment(lib,"comctl32.lib")
diff --git a/src/mir_app/src/newplugins.cpp b/src/mir_app/src/newplugins.cpp index fda3a1c558..d5d197162d 100644 --- a/src/mir_app/src/newplugins.cpp +++ b/src/mir_app/src/newplugins.cpp @@ -46,7 +46,6 @@ LIST<pluginEntry> /////////////////////////////////////////////////////////////////////////////////////////
MUUID miid_last = MIID_LAST;
-MUUID miid_chat = MIID_CHAT;
MUUID miid_srmm = MIID_SRMM;
MUUID miid_clist = MIID_CLIST;
MUUID miid_database = MIID_DATABASE;
@@ -139,8 +138,7 @@ static MuuidReplacement pluginDefault[] = { MIID_USERONLINE, L"stduseronline", NULL }, // 8
{ MIID_SRAWAY, L"stdaway", NULL }, // 9
{ MIID_CLIST, L"stdclist", NULL }, // 10
- { MIID_CHAT, L"stdchat", NULL }, // 11
- { MIID_SRMM, L"stdmsg", NULL } // 12
+ { MIID_SRMM, L"stdmsg", NULL } // 11
};
int getDefaultPluginIdx(const MUUID &muuid)
@@ -162,7 +160,7 @@ int LoadStdPlugins() return 1;
}
- if (pluginDefault[12].pImpl == NULL)
+ if (pluginDefault[11].pImpl == NULL)
MessageBox(NULL, TranslateT("No messaging plugins loaded. Please install/enable one of the messaging plugins, for instance, \"StdMsg.dll\""), L"Miranda NG", MB_OK | MB_ICONWARNING);
return 0;
|