summaryrefslogtreecommitdiff
path: root/plugins/TabSRMM/chat
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-23 07:44:30 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-23 07:44:30 +0000
commitf3d44bc057201407373012b7f682881bda7b3d98 (patch)
treeddf031a82529c84e13222131cf184ecf176d3954 /plugins/TabSRMM/chat
parentc2d827972a16f1710406d15e58304aecc4e1c9b5 (diff)
some includes restored, mir_full.sln updated, some renaming of folders and projects
git-svn-id: http://svn.miranda-ng.org/main/trunk@140 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/TabSRMM/chat')
-rw-r--r--plugins/TabSRMM/chat/Icons/1.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/2.icobin0 -> 918 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/3.icobin0 -> 918 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/4.icobin0 -> 918 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/5.icobin0 -> 918 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/6.icobin0 -> 918 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/1.icobin0 -> 1742 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/2.icobin0 -> 1742 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/3.icobin0 -> 1742 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/4.icobin0 -> 1742 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/5.icobin0 -> 1742 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/6.icobin0 -> 1742 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/Bkgcolor.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/action.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/addmode.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/blank.icobin0 -> 318 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/filter.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/filter2.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/highlight.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/history.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/info.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/join.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/kick.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/message.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/messageout.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/nick.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/nicklist_hide.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/nicklist_show.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/notice.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/overlay.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/part.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/quit.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/removestatus.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/tag1.icobin0 -> 1590 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/tag2.icobin0 -> 4726 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/topic.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/topicbut.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/NOVA/window.icobin0 -> 2550 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/action.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/addmode.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/bkgcolor.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/blank.icobin0 -> 318 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/filter.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/filter2.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/highlight.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/history.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/info.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/join.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/kick.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/message.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/messageout.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/nick.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/nicklist_hide.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/nicklist_show.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/notice.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/overlay.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/part.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/quit.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/removestatus.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/tag1.icobin0 -> 1590 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/tag2.icobin0 -> 4726 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/topic.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/topicbut.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/Icons/window.icobin0 -> 2038 bytes
-rw-r--r--plugins/TabSRMM/chat/chat.h369
-rw-r--r--plugins/TabSRMM/chat/chat.rc411
-rw-r--r--plugins/TabSRMM/chat/chat_resource.h161
-rw-r--r--plugins/TabSRMM/chat/chatprototypes.h174
-rw-r--r--plugins/TabSRMM/chat/clist.cpp326
-rw-r--r--plugins/TabSRMM/chat/colorchooser.cpp281
-rw-r--r--plugins/TabSRMM/chat/log.cpp1352
-rw-r--r--plugins/TabSRMM/chat/main.cpp142
-rw-r--r--plugins/TabSRMM/chat/manager.cpp1541
-rw-r--r--plugins/TabSRMM/chat/message.cpp341
-rw-r--r--plugins/TabSRMM/chat/muchighlight.cpp427
-rw-r--r--plugins/TabSRMM/chat/muchighlight.h94
-rw-r--r--plugins/TabSRMM/chat/options.cpp1496
-rw-r--r--plugins/TabSRMM/chat/services.cpp909
-rw-r--r--plugins/TabSRMM/chat/tools.cpp1351
-rw-r--r--plugins/TabSRMM/chat/window.cpp3840
80 files changed, 13215 insertions, 0 deletions
diff --git a/plugins/TabSRMM/chat/Icons/1.ico b/plugins/TabSRMM/chat/Icons/1.ico
new file mode 100644
index 0000000000..2c7324149c
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/1.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/2.ico b/plugins/TabSRMM/chat/Icons/2.ico
new file mode 100644
index 0000000000..f212c16855
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/2.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/3.ico b/plugins/TabSRMM/chat/Icons/3.ico
new file mode 100644
index 0000000000..680cfd63e1
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/3.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/4.ico b/plugins/TabSRMM/chat/Icons/4.ico
new file mode 100644
index 0000000000..d39ae9ea76
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/4.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/5.ico b/plugins/TabSRMM/chat/Icons/5.ico
new file mode 100644
index 0000000000..a7186bed69
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/5.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/6.ico b/plugins/TabSRMM/chat/Icons/6.ico
new file mode 100644
index 0000000000..550c72285e
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/6.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/1.ico b/plugins/TabSRMM/chat/Icons/NOVA/1.ico
new file mode 100644
index 0000000000..51dcdc4648
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/1.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/2.ico b/plugins/TabSRMM/chat/Icons/NOVA/2.ico
new file mode 100644
index 0000000000..819ecc1d7a
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/2.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/3.ico b/plugins/TabSRMM/chat/Icons/NOVA/3.ico
new file mode 100644
index 0000000000..0928e257fe
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/3.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/4.ico b/plugins/TabSRMM/chat/Icons/NOVA/4.ico
new file mode 100644
index 0000000000..5dcea114fa
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/4.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/5.ico b/plugins/TabSRMM/chat/Icons/NOVA/5.ico
new file mode 100644
index 0000000000..6aa5806c53
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/5.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/6.ico b/plugins/TabSRMM/chat/Icons/NOVA/6.ico
new file mode 100644
index 0000000000..c35cc39ebc
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/6.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/Bkgcolor.ico b/plugins/TabSRMM/chat/Icons/NOVA/Bkgcolor.ico
new file mode 100644
index 0000000000..e3322ef34b
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/Bkgcolor.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/action.ico b/plugins/TabSRMM/chat/Icons/NOVA/action.ico
new file mode 100644
index 0000000000..44816c42d7
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/action.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/addmode.ico b/plugins/TabSRMM/chat/Icons/NOVA/addmode.ico
new file mode 100644
index 0000000000..a6a7e6f38c
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/addmode.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/blank.ico b/plugins/TabSRMM/chat/Icons/NOVA/blank.ico
new file mode 100644
index 0000000000..7845f62fed
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/blank.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/filter.ico b/plugins/TabSRMM/chat/Icons/NOVA/filter.ico
new file mode 100644
index 0000000000..7c99edb58c
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/filter.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/filter2.ico b/plugins/TabSRMM/chat/Icons/NOVA/filter2.ico
new file mode 100644
index 0000000000..701890522b
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/filter2.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/highlight.ico b/plugins/TabSRMM/chat/Icons/NOVA/highlight.ico
new file mode 100644
index 0000000000..552c912eaa
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/highlight.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/history.ico b/plugins/TabSRMM/chat/Icons/NOVA/history.ico
new file mode 100644
index 0000000000..537c9b52c5
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/history.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/info.ico b/plugins/TabSRMM/chat/Icons/NOVA/info.ico
new file mode 100644
index 0000000000..1acdb7190b
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/info.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/join.ico b/plugins/TabSRMM/chat/Icons/NOVA/join.ico
new file mode 100644
index 0000000000..151cd93211
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/join.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/kick.ico b/plugins/TabSRMM/chat/Icons/NOVA/kick.ico
new file mode 100644
index 0000000000..c93e92dd77
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/kick.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/message.ico b/plugins/TabSRMM/chat/Icons/NOVA/message.ico
new file mode 100644
index 0000000000..19957e4ac8
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/message.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/messageout.ico b/plugins/TabSRMM/chat/Icons/NOVA/messageout.ico
new file mode 100644
index 0000000000..637196b745
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/messageout.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/nick.ico b/plugins/TabSRMM/chat/Icons/NOVA/nick.ico
new file mode 100644
index 0000000000..3f199ffd50
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/nick.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/nicklist_hide.ico b/plugins/TabSRMM/chat/Icons/NOVA/nicklist_hide.ico
new file mode 100644
index 0000000000..f2f611d6a4
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/nicklist_hide.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/nicklist_show.ico b/plugins/TabSRMM/chat/Icons/NOVA/nicklist_show.ico
new file mode 100644
index 0000000000..cba204fe5e
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/nicklist_show.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/notice.ico b/plugins/TabSRMM/chat/Icons/NOVA/notice.ico
new file mode 100644
index 0000000000..1ba34d7244
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/notice.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/overlay.ico b/plugins/TabSRMM/chat/Icons/NOVA/overlay.ico
new file mode 100644
index 0000000000..28742d898d
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/overlay.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/part.ico b/plugins/TabSRMM/chat/Icons/NOVA/part.ico
new file mode 100644
index 0000000000..39c24868aa
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/part.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/quit.ico b/plugins/TabSRMM/chat/Icons/NOVA/quit.ico
new file mode 100644
index 0000000000..d7fbdaf4b7
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/quit.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/removestatus.ico b/plugins/TabSRMM/chat/Icons/NOVA/removestatus.ico
new file mode 100644
index 0000000000..ea3cef3fef
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/removestatus.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/tag1.ico b/plugins/TabSRMM/chat/Icons/NOVA/tag1.ico
new file mode 100644
index 0000000000..1dc687becd
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/tag1.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/tag2.ico b/plugins/TabSRMM/chat/Icons/NOVA/tag2.ico
new file mode 100644
index 0000000000..4fac50a4c8
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/tag2.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/topic.ico b/plugins/TabSRMM/chat/Icons/NOVA/topic.ico
new file mode 100644
index 0000000000..e4bb7da7e0
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/topic.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/topicbut.ico b/plugins/TabSRMM/chat/Icons/NOVA/topicbut.ico
new file mode 100644
index 0000000000..ddb72fb8ca
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/topicbut.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/NOVA/window.ico b/plugins/TabSRMM/chat/Icons/NOVA/window.ico
new file mode 100644
index 0000000000..5c21ea3052
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/NOVA/window.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/action.ico b/plugins/TabSRMM/chat/Icons/action.ico
new file mode 100644
index 0000000000..1bccf99db6
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/action.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/addmode.ico b/plugins/TabSRMM/chat/Icons/addmode.ico
new file mode 100644
index 0000000000..844b7c5d46
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/addmode.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/bkgcolor.ico b/plugins/TabSRMM/chat/Icons/bkgcolor.ico
new file mode 100644
index 0000000000..11c54ab502
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/bkgcolor.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/blank.ico b/plugins/TabSRMM/chat/Icons/blank.ico
new file mode 100644
index 0000000000..7845f62fed
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/blank.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/filter.ico b/plugins/TabSRMM/chat/Icons/filter.ico
new file mode 100644
index 0000000000..02aa5455f6
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/filter.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/filter2.ico b/plugins/TabSRMM/chat/Icons/filter2.ico
new file mode 100644
index 0000000000..3473eb9979
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/filter2.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/highlight.ico b/plugins/TabSRMM/chat/Icons/highlight.ico
new file mode 100644
index 0000000000..abdf6a0c2c
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/highlight.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/history.ico b/plugins/TabSRMM/chat/Icons/history.ico
new file mode 100644
index 0000000000..b2477bc7d3
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/history.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/info.ico b/plugins/TabSRMM/chat/Icons/info.ico
new file mode 100644
index 0000000000..db229094dc
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/info.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/join.ico b/plugins/TabSRMM/chat/Icons/join.ico
new file mode 100644
index 0000000000..3e062a1a95
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/join.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/kick.ico b/plugins/TabSRMM/chat/Icons/kick.ico
new file mode 100644
index 0000000000..e7de687686
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/kick.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/message.ico b/plugins/TabSRMM/chat/Icons/message.ico
new file mode 100644
index 0000000000..cb543ce737
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/message.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/messageout.ico b/plugins/TabSRMM/chat/Icons/messageout.ico
new file mode 100644
index 0000000000..4376f1e756
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/messageout.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/nick.ico b/plugins/TabSRMM/chat/Icons/nick.ico
new file mode 100644
index 0000000000..97b681f0c7
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/nick.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/nicklist_hide.ico b/plugins/TabSRMM/chat/Icons/nicklist_hide.ico
new file mode 100644
index 0000000000..7abd838725
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/nicklist_hide.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/nicklist_show.ico b/plugins/TabSRMM/chat/Icons/nicklist_show.ico
new file mode 100644
index 0000000000..9390b173b3
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/nicklist_show.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/notice.ico b/plugins/TabSRMM/chat/Icons/notice.ico
new file mode 100644
index 0000000000..31ebb310f6
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/notice.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/overlay.ico b/plugins/TabSRMM/chat/Icons/overlay.ico
new file mode 100644
index 0000000000..a3f7cf6c36
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/overlay.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/part.ico b/plugins/TabSRMM/chat/Icons/part.ico
new file mode 100644
index 0000000000..1444253dee
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/part.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/quit.ico b/plugins/TabSRMM/chat/Icons/quit.ico
new file mode 100644
index 0000000000..2d54d764cf
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/quit.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/removestatus.ico b/plugins/TabSRMM/chat/Icons/removestatus.ico
new file mode 100644
index 0000000000..7f4711e8a9
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/removestatus.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/tag1.ico b/plugins/TabSRMM/chat/Icons/tag1.ico
new file mode 100644
index 0000000000..1dc687becd
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/tag1.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/tag2.ico b/plugins/TabSRMM/chat/Icons/tag2.ico
new file mode 100644
index 0000000000..4fac50a4c8
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/tag2.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/topic.ico b/plugins/TabSRMM/chat/Icons/topic.ico
new file mode 100644
index 0000000000..5c7fff78a1
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/topic.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/topicbut.ico b/plugins/TabSRMM/chat/Icons/topicbut.ico
new file mode 100644
index 0000000000..48bec51143
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/topicbut.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/Icons/window.ico b/plugins/TabSRMM/chat/Icons/window.ico
new file mode 100644
index 0000000000..d64d924548
--- /dev/null
+++ b/plugins/TabSRMM/chat/Icons/window.ico
Binary files differ
diff --git a/plugins/TabSRMM/chat/chat.h b/plugins/TabSRMM/chat/chat.h
new file mode 100644
index 0000000000..e06634beef
--- /dev/null
+++ b/plugins/TabSRMM/chat/chat.h
@@ -0,0 +1,369 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: chat.h 12272 2010-08-04 08:24:08Z silvercircle $
+ *
+ */
+
+#ifndef _CHAT_H_
+#define _CHAT_H_
+
+#pragma warning( disable : 4786 ) // limitation in MSVC's debugger.
+#pragma warning( disable : 4996 ) // limitation in MSVC's debugger.
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "m_stdhdr.h"
+
+//defines
+#define OPTIONS_FONTCOUNT 20
+#define GC_UPDATETITLE (WM_USER+100)
+#define GC_CLOSEWINDOW (WM_USER+103)
+#define GC_GETITEMDATA (WM_USER+104)
+#define GC_SETITEMDATA (WM_USER+105)
+#define GC_UPDATESTATUSBAR (WM_USER+106)
+#define GC_SETVISIBILITY (WM_USER+107)
+#define GC_SETWNDPROPS (WM_USER+108)
+#define GC_REDRAWLOG (WM_USER+109)
+#define GC_FIREHOOK (WM_USER+110)
+#define GC_FILTERFIX (WM_USER+111)
+#define GC_CHANGEFILTERFLAG (WM_USER+112)
+#define GC_SHOWFILTERMENU (WM_USER+113)
+//#define GC_NICKLISTCLEAR (WM_USER+117)
+#define GC_REDRAWWINDOW (WM_USER+118)
+#define GC_SHOWCOLORCHOOSER (WM_USER+119)
+#define GC_ADDLOG (WM_USER+120)
+#define GC_ACKMESSAGE (WM_USER+121)
+//#define GC_ADDUSER (WM_USER+122)
+//#define GC_REMOVEUSER (WM_USER+123)
+//#define GC_NICKCHANGE (WM_USER+124)
+#define GC_UPDATENICKLIST (WM_USER+125)
+//#define GC_MODECHANGE (WM_USER+126)
+#define GC_SCROLLTOBOTTOM (WM_USER+129)
+#define GC_SESSIONNAMECHANGE (WM_USER+131)
+#define GC_SETMESSAGEHIGHLIGHT (WM_USER+139)
+#define GC_REDRAWLOG2 (WM_USER+140)
+#define GC_REDRAWLOG3 (WM_USER+141)
+
+#define EM_ACTIVATE (WM_USER+202)
+
+#define GC_EVENT_HIGHLIGHT 0x1000
+#define STATE_TALK 0x0001
+
+#define ICON_ACTION 0
+#define ICON_ADDSTATUS 1
+#define ICON_HIGHLIGHT 2
+#define ICON_INFO 3
+#define ICON_JOIN 4
+#define ICON_KICK 5
+#define ICON_MESSAGE 6
+#define ICON_MESSAGEOUT 7
+#define ICON_NICK 8
+#define ICON_NOTICE 9
+#define ICON_PART 10
+#define ICON_QUIT 11
+#define ICON_REMSTATUS 12
+#define ICON_TOPIC 13
+
+#define ICON_STATUS1 14
+#define ICON_STATUS2 15
+#define ICON_STATUS3 16
+#define ICON_STATUS4 17
+#define ICON_STATUS0 18
+#define ICON_STATUS5 19
+
+// special service for tweaking performance
+#define MS_GC_GETEVENTPTR "GChat/GetNewEventPtr"
+typedef INT_PTR (*GETEVENTFUNC)(WPARAM wParam, LPARAM lParam);
+typedef struct {
+ GETEVENTFUNC pfnAddEvent;
+}GCPTRS;
+
+class CMUCHighlight;
+
+//structs
+
+typedef struct MODULE_INFO_TYPE
+{
+ char* pszModule;
+ TCHAR* ptszModDispName;
+ char* pszHeader;
+ BOOL bBold;
+ BOOL bUnderline;
+ BOOL bItalics;
+ BOOL bColor;
+ BOOL bBkgColor;
+ BOOL bChanMgr;
+ BOOL bAckMsg;
+ int nColorCount;
+ COLORREF* crColors;
+ /*
+ HICON hOnlineIcon;
+ HICON hOfflineIcon;
+ HICON hOnlineTalkIcon;
+ HICON hOfflineTalkIcon;
+ int OnlineIconIndex;
+ int OfflineIconIndex;
+ */
+ int iMaxText;
+ DWORD idleTimeStamp;
+ DWORD lastIdleCheck;
+ TCHAR tszIdleMsg[60];
+ CMUCHighlight* Highlight;
+ struct MODULE_INFO_TYPE *next;
+}
+ MODULEINFO;
+
+typedef struct COMMAND_INFO_TYPE
+{
+ char* lpCommand;
+ struct COMMAND_INFO_TYPE *last, *next;
+}
+ COMMAND_INFO;
+
+typedef struct
+{
+ LOGFONT lf;
+ COLORREF color;
+}
+ FONTINFO;
+
+typedef struct LOG_INFO_TYPE
+{
+ TCHAR* ptszText;
+ TCHAR* ptszNick;
+ TCHAR* ptszUID;
+ TCHAR* ptszStatus;
+ TCHAR* ptszUserInfo;
+ BOOL bIsMe;
+ BOOL bIsHighlighted;
+ time_t time;
+ int iType;
+ DWORD dwFlags;
+ struct LOG_INFO_TYPE *next;
+ struct LOG_INFO_TYPE *prev;
+}
+ LOGINFO;
+
+typedef struct STATUSINFO_TYPE
+{
+ TCHAR* pszGroup;
+ HICON hIcon;
+ WORD Status;
+ struct STATUSINFO_TYPE *next;
+}
+ STATUSINFO;
+
+typedef struct USERINFO_TYPE
+{
+ TCHAR* pszNick;
+ TCHAR* pszUID;
+ WORD Status;
+ int iStatusEx;
+ WORD ContactStatus;
+ struct USERINFO_TYPE *next;
+}
+ USERINFO;
+
+typedef struct SESSIONINFO_TYPE
+{
+ HWND hWnd;
+
+ BOOL bFGSet;
+ BOOL bBGSet;
+ BOOL bFilterEnabled;
+ BOOL bNicklistEnabled;
+ BOOL bInitDone;
+
+ char* pszModule;
+ TCHAR* ptszID;
+ TCHAR* ptszName;
+ TCHAR* ptszStatusbarText;
+ TCHAR* ptszTopic;
+ TCHAR pszLogFileName[MAX_PATH + 50];
+
+ char* pszID; // ugly fix for returning static ANSI strings in GC_INFO
+ char* pszName; // just to fix a bug quickly, should die after porting IRC to Unicode
+
+ int iType;
+ int iFG;
+ int iBG;
+ int iSplitterY;
+ int iSplitterX;
+ int iLogFilterFlags;
+ int iLogPopupFlags;
+ int iLogTrayFlags;
+ int iDiskLogFlags;
+ int nUsersInNicklist;
+ int iEventCount;
+ int iStatusCount;
+
+ WORD wStatus;
+ WORD wState;
+ WORD wCommandsNum;
+ DWORD dwItemData;
+ DWORD dwFlags;
+ HANDLE hContact;
+ HWND hwndFilter;
+ time_t LastTime;
+ TCHAR szSearch[255];
+ int iSearchItem;
+ CMUCHighlight* Highlight;
+ COMMAND_INFO* lpCommands;
+ COMMAND_INFO* lpCurrentCommand;
+ LOGINFO* pLog;
+ LOGINFO* pLogEnd;
+ USERINFO* pUsers;
+ USERINFO* pMe;
+ STATUSINFO* pStatuses;
+ TContainerData *pContainer;
+ TWindowData *dat;
+ int wasTrimmed;
+ SESSIONINFO_TYPE* next;
+} SESSION_INFO;
+
+typedef struct
+{
+ char* buffer;
+ int bufferOffset, bufferLen;
+ HWND hwnd;
+ LOGINFO* lin;
+ BOOL bStripFormat;
+ BOOL bRedraw;
+ SESSION_INFO* si;
+ int crCount;
+ TWindowData* dat;
+}
+ LOGSTREAMDATA;
+
+struct TMUCSettings {
+ HICON hIconOverlay;
+ BOOL ShowTime;
+ BOOL ShowTimeIfChanged;
+ BOOL LoggingEnabled;
+ BOOL FlashWindow;
+ BOOL FlashWindowHightlight;
+ BOOL OpenInDefault;
+ BOOL HighlightEnabled;
+ BOOL LogIndentEnabled;
+ BOOL StripFormat;
+ BOOL BBCodeInPopups;
+ BOOL TrayIconInactiveOnly;
+ BOOL AddColonToAutoComplete;
+ BOOL LogLimitNames;
+ BOOL TimeStampEventColour;
+ DWORD dwIconFlags;
+ int LogTextIndent;
+ long LoggingLimit;
+ int iEventLimit;
+ int iEventLimitThreshold;
+ int iPopupStyle;
+ int iPopupTimeout;
+ int iSplitterX;
+ int iSplitterY;
+ TCHAR* pszTimeStamp;
+ TCHAR* pszTimeStampLog;
+ TCHAR* pszIncomingNick;
+ TCHAR* pszOutgoingNick;
+ TCHAR pszLogDir[MAX_PATH + 20];
+ LONG iNickListFontHeight;
+ HFONT UserListFont, UserListHeadingsFont;
+ HFONT NameFont;
+ COLORREF crUserListColor;
+ COLORREF crUserListBGColor;
+ COLORREF crUserListHeadingsColor;
+ COLORREF crPUTextColour;
+ COLORREF crPUBkgColour;
+ BYTE ClassicIndicators;
+ //MAD
+ BYTE LogClassicIndicators;
+ BYTE AlternativeSorting;
+ BYTE AnnoyingHighlight;
+ BYTE CreateWindowOnHighlight;
+ //MAD_
+ BYTE LogSymbols;
+ BYTE ClickableNicks;
+ BYTE ColorizeNicks;
+ BYTE ColorizeNicksInLog;
+ BYTE ScaleIcons;
+ BYTE UseDividers;
+ BYTE DividersUsePopupConfig;
+ BYTE MathMod;
+ COLORREF nickColors[8];
+ HBRUSH SelectionBGBrush;
+ BOOL DoubleClick4Privat;
+ BOOL ShowContactStatus;
+ BOOL ContactStatusFirst;
+ HANDLE hGroup;
+ CMUCHighlight* Highlight;
+};
+
+struct FLASH_PARAMS {
+ HANDLE hContact;
+ const char* sound;
+ int iEvent;
+ HICON hNotifyIcon;
+ BOOL bActiveTab, bHighlight, bInactive, bMustFlash, bMustAutoswitch;
+ HWND hWnd;
+};
+
+extern TMUCSettings g_Settings;
+
+typedef struct{
+ MODULEINFO* pModule;
+ int xPosition;
+ int yPosition;
+ HWND hWndTarget;
+ BOOL bForeground;
+ SESSION_INFO* si;
+} COLORCHOOSER;
+
+#pragma comment(lib,"comctl32.lib")
+
+//////////////////////////////////////////////////////////////////////////////////
+
+#include "chatprototypes.h"
+#include "chat_resource.h"
+
+#define mir_tstrdup mir_wstrdup
+
+TCHAR* a2t( const char* str );
+char* t2a( const TCHAR* str, DWORD codepage );
+TCHAR* a2tf( const TCHAR* str, int flags, DWORD cp );
+TCHAR* replaceStr( TCHAR** dest, const TCHAR* src );
+char* replaceStrA( char** dest, const char* src );
+
+extern char *szChatIconString;
+
+#define DEFLOGFILENAME _T("%miranda_logpath%\\%proto%\\%userid%.log")
+
+#endif
diff --git a/plugins/TabSRMM/chat/chat.rc b/plugins/TabSRMM/chat/chat.rc
new file mode 100644
index 0000000000..47c2a877fa
--- /dev/null
+++ b/plugins/TabSRMM/chat/chat.rc
@@ -0,0 +1,411 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "chat_resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+#include "richedit.h"
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_CHANNEL DIALOGEX 0, 0, 252, 140
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_SPLITTERX,"Static",SS_ENHMETAFILE,172,23,10,73
+ CONTROL "",IDC_SPLITTERY,"Static",SS_ENHMETAFILE,0,132,251,6
+ CONTROL "",IDC_CHAT_MESSAGE,"RichEdit20W",WS_VSCROLL | WS_TABSTOP | 0x1144,0,128,127,12,WS_EX_STATICEDGE
+ CONTROL "",IDC_CHAT_LOG,"RichEdit20W",WS_VSCROLL | 0x844,8,23,164,72,WS_EX_STATICEDGE
+ LISTBOX IDC_LIST,182,23,69,73,LBS_MULTIPLESEL | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | LBS_NODATA | NOT WS_BORDER | WS_VSCROLL | WS_TABSTOP,WS_EX_STATICEDGE
+ CONTROL "",IDC_PANELSPLITTER,"Static",SS_ENHMETAFILE,0,32,252,1,WS_EX_TRANSPARENT
+END
+
+IDD_ADDHIGHLIGHT DIALOG 0, 0, 212, 97
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_BORDER
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "",IDC_STATIC,0,0,211,97
+ LTEXT "",IDC_ADDHIGHLIGHTTITLE,7,3,201,12,SS_CENTERIMAGE
+ COMBOBOX IDC_ADDHIGHLIGHTNAME,17,24,178,17,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "You can add the user by user name or his id. Wildcards are allowed and recommended.",IDC_ADDHIGHLIGHTEXPLAIN,15,49,179,21
+ DEFPUSHBUTTON "OK",IDOK,152,76,55,14
+ DEFPUSHBUTTON "Cancel",IDCANCEL,91,76,55,14
+ EDITTEXT IDC_ADDHIGHLIGHTEDITLIST,9,18,192,47,ES_AUTOHSCROLL
+END
+
+IDD_FILTER DIALOG 0, 0, 201, 126
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_BORDER
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "",IDC_STATIC,0,0,201,124
+ LTEXT " Show these events",IDC_TEXTO,1,0,91,13,SS_CENTERIMAGE
+ CONTROL "Actions",IDC_1,"Button",BS_AUTO3STATE | WS_TABSTOP,3,13,114,10
+ CONTROL "Messages",IDC_2,"Button",BS_AUTO3STATE | WS_TABSTOP,3,23,114,10
+ CONTROL "Nick changes",IDC_3,"Button",BS_AUTO3STATE | WS_TABSTOP,3,33,114,10
+ CONTROL "Users joining",IDC_4,"Button",BS_AUTO3STATE | WS_TABSTOP,3,43,114,10
+ CONTROL "Users leaving",IDC_5,"Button",BS_AUTO3STATE | WS_TABSTOP,3,53,114,10
+ CONTROL "Topic changes",IDC_6,"Button",BS_AUTO3STATE | WS_TABSTOP,3,63,114,10
+ CONTROL "Status changes",IDC_7,"Button",BS_AUTO3STATE | WS_TABSTOP,3,73,114,10
+ CONTROL "Information",IDC_8,"Button",BS_AUTO3STATE | WS_TABSTOP,3,83,114,10
+ CONTROL "Disconnects",IDC_9,"Button",BS_AUTO3STATE | WS_TABSTOP,3,93,114,10
+ CONTROL "User kicks",IDC_10,"Button",BS_AUTO3STATE | WS_TABSTOP,3,103,114,10
+ CONTROL "Notices",IDC_11,"Button",BS_AUTO3STATE | WS_TABSTOP,3,113,82,10
+ CTEXT "Popup",IDC_TEXTO2,105,0,43,13,SS_CENTERIMAGE
+ CTEXT "Tray",IDC_TEXTO3,159,0,34,13,SS_CENTERIMAGE
+ CONTROL "",IDC_P1,"Button",BS_AUTO3STATE | WS_TABSTOP,123,13,21,10
+ CONTROL "",IDC_P2,"Button",BS_AUTO3STATE | WS_TABSTOP,123,23,21,10
+ CONTROL "",IDC_P3,"Button",BS_AUTO3STATE | WS_TABSTOP,123,33,21,10
+ CONTROL "",IDC_P4,"Button",BS_AUTO3STATE | WS_TABSTOP,123,43,21,10
+ CONTROL "",IDC_P5,"Button",BS_AUTO3STATE | WS_TABSTOP,123,53,21,10
+ CONTROL "",IDC_P6,"Button",BS_AUTO3STATE | WS_TABSTOP,123,63,21,10
+ CONTROL "",IDC_P7,"Button",BS_AUTO3STATE | WS_TABSTOP,123,73,21,10
+ CONTROL "",IDC_P8,"Button",BS_AUTO3STATE | WS_TABSTOP,123,83,21,10
+ CONTROL "",IDC_P9,"Button",BS_AUTO3STATE | WS_TABSTOP,123,93,21,10
+ CONTROL "",IDC_P10,"Button",BS_AUTO3STATE | WS_TABSTOP,123,103,21,10
+ CONTROL "",IDC_P11,"Button",BS_AUTO3STATE | WS_TABSTOP,123,113,21,10
+ CONTROL "",IDC_T1,"Button",BS_AUTO3STATE | WS_TABSTOP,173,13,21,10
+ CONTROL "",IDC_T2,"Button",BS_AUTO3STATE | WS_TABSTOP,173,23,21,10
+ CONTROL "",IDC_T3,"Button",BS_AUTO3STATE | WS_TABSTOP,173,33,21,10
+ CONTROL "",IDC_T4,"Button",BS_AUTO3STATE | WS_TABSTOP,173,43,21,10
+ CONTROL "",IDC_T5,"Button",BS_AUTO3STATE | WS_TABSTOP,173,53,21,10
+ CONTROL "",IDC_T6,"Button",BS_AUTO3STATE | WS_TABSTOP,173,63,21,10
+ CONTROL "",IDC_T7,"Button",BS_AUTO3STATE | WS_TABSTOP,173,73,21,10
+ CONTROL "",IDC_T8,"Button",BS_AUTO3STATE | WS_TABSTOP,173,83,21,10
+ CONTROL "",IDC_T9,"Button",BS_AUTO3STATE | WS_TABSTOP,173,93,21,10
+ CONTROL "",IDC_T10,"Button",BS_AUTO3STATE | WS_TABSTOP,173,103,21,10
+ CONTROL "",IDC_T11,"Button",BS_AUTO3STATE | WS_TABSTOP,173,113,21,10
+END
+
+IDD_OPTIONS1 DIALOGEX 0, 0, 306, 236
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Options",IDC_STATIC,3,0,300,229
+ CONTROL "",IDC_CHECKBOXES,"SysTreeView32",TVS_HASBUTTONS | TVS_DISABLEDRAGDROP | TVS_FULLROWSELECT | WS_BORDER | WS_TABSTOP,6,9,294,177
+ LTEXT "Add new rooms to group:",IDC_STATIC_ADD,10,213,132,8
+ EDITTEXT IDC_GROUP,152,210,50,14,ES_AUTOHSCROLL
+ LTEXT "Chat integration is disabled. You can enable it here, and then you to NEED RESTART Miranda after making this change.\n\nYou MUST disable the standard chat plugin when you enable the group chat support here. Otherwise no group chat at all may work.",IDC_STATIC_MESSAGE,21,52,256,74
+END
+
+IDD_OPTIONS2 DIALOGEX 0, 0, 306, 239
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Log files",IDC_STATIC,1,2,299,95
+ CONTROL "Enable logging to disk",IDC_LOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,14,277,10
+ LTEXT "Log directory",IDC_STATIC110,17,27,211,8
+ EDITTEXT IDC_LOGDIRECTORY,15,38,211,14,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_FONTCHOOSE,230,39,19,14
+ LTEXT "Maximum size for log files (in kB)",IDC_STATIC112,17,62,159,11
+ EDITTEXT IDC_LIMIT,230,59,38,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_CHAT_SPIN4,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,261,57,11,14
+ GROUPBOX "Group chat log formatting",IDC_STATIC,1,101,299,59
+ LTEXT "Your name",IDC_STATIC,10,111,50,8
+ EDITTEXT IDC_OUTSTAMP,10,121,35,14,ES_AUTOHSCROLL
+ LTEXT "Other name",IDC_STATIC,60,111,57,8
+ EDITTEXT IDC_INSTAMP,60,121,35,14,ES_AUTOHSCROLL
+ LTEXT "Timestamp (window)",IDC_STATIC,118,111,78,8
+ EDITTEXT IDC_TIMESTAMP,118,121,81,14,ES_AUTOHSCROLL
+ LTEXT "Timestamp (logfile)",IDC_STATIC,205,111,81,8
+ EDITTEXT IDC_LOGTIMESTAMP,205,121,81,14,ES_AUTOHSCROLL
+ LTEXT "Maximum number of events in the message window",IDC_STATIC,10,142,225,11
+ EDITTEXT IDC_LOGLIMIT,248,139,38,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_CHAT_SPIN2,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,281,138,11,14
+ LTEXT "Groupchat userlist row height (pixels)",IDC_STATIC_ULIST,10,212,221,8
+ EDITTEXT IDC_NICKROW2,247,209,29,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_CHAT_SPIN3,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,275,215,11,14
+ PUSHBUTTON "Open log file base folder",IDC_MUC_OPENLOGBASEDIR,16,76,155,14
+END
+
+IDD_OPTIONS3 DIALOGEX 0, 0, 306, 239
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Default settings for known event types",IDC_STATIC,7,5,293,153
+ LTEXT "Show when filter is active",IDC_STATIC,12,14,119,13,SS_CENTERIMAGE
+ CTEXT "Log to file",IDC_TEXTO4,234,13,64,13,SS_CENTERIMAGE
+ CTEXT "Show Popup",IDC_TEXTO2,131,13,49,13,SS_CENTERIMAGE
+ CTEXT "Notify in tray",IDC_TEXTO3,183,13,49,13,SS_CENTERIMAGE
+ CONTROL "Actions",IDC_1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,28,110,10
+ CONTROL "Messages",IDC_2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,38,110,10
+ CONTROL "Nick changes",IDC_3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,48,110,10
+ CONTROL "Users joining",IDC_4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,58,110,10
+ CONTROL "Users leaving",IDC_5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,68,110,10
+ CONTROL "Topic changes",IDC_6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,78,110,10
+ CONTROL "Status changes",IDC_7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,88,110,10
+ CONTROL "Information",IDC_8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,98,110,10
+ CONTROL "Disconnects",IDC_9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,108,110,10
+ CONTROL "User kicks",IDC_10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,118,110,10
+ CONTROL "Notices",IDC_11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,32,128,110,10
+ CONTROL "",IDC_P1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,28,21,10
+ CONTROL "",IDC_P2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,38,21,10
+ CONTROL "",IDC_P3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,48,21,10
+ CONTROL "",IDC_P4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,58,21,10
+ CONTROL "",IDC_P5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,68,21,10
+ CONTROL "",IDC_P6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,78,21,10
+ CONTROL "",IDC_P7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,88,21,10
+ CONTROL "",IDC_P8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,98,21,10
+ CONTROL "",IDC_P9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,108,21,10
+ CONTROL "",IDC_P10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,118,21,10
+ CONTROL "",IDC_P11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,128,21,10
+ CONTROL "",IDC_P12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,152,138,21,10
+ CONTROL "",IDC_T1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,28,21,10
+ CONTROL "",IDC_T2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,38,21,10
+ CONTROL "",IDC_T3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,48,21,10
+ CONTROL "",IDC_T4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,58,21,10
+ CONTROL "",IDC_T5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,68,21,10
+ CONTROL "",IDC_T6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,78,21,10
+ CONTROL "",IDC_T7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,88,21,10
+ CONTROL "",IDC_T8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,98,21,10
+ CONTROL "",IDC_T9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,108,21,10
+ CONTROL "",IDC_T10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,118,21,10
+ CONTROL "",IDC_T11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,128,21,10
+ CONTROL "",IDC_T12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,138,21,10
+ CONTROL "",IDC_L1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,28,21,10
+ CONTROL "",IDC_L2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,38,21,10
+ CONTROL "",IDC_L3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,48,21,10
+ CONTROL "",IDC_L4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,58,21,10
+ CONTROL "",IDC_L5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,68,21,10
+ CONTROL "",IDC_L6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,78,21,10
+ CONTROL "",IDC_L7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,88,21,10
+ CONTROL "",IDC_L8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,98,21,10
+ CONTROL "",IDC_L9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,108,21,10
+ CONTROL "",IDC_L10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,118,21,10
+ CONTROL "",IDC_L11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,128,21,10
+ CONTROL "Suppress tray notifications for focused channel windows",IDC_TRAYONLYFORINACTIVE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,164,279,10
+ CONTROL "Do not show popups when the channel window is not open",IDC_NOPOPUPSFORCLOSEDWINDOWS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,176,282,10
+ LTEXT "Highlight event",IDC_STATIC,44,139,68,12
+ COMBOBOX IDC_LOGICONTYPE,12,212,171,38,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Line markers in the message log",IDC_STATIC,14,201,257,10
+END
+
+IDD_OPTIONS4 DIALOGEX 0, 0, 306, 239
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Highlight user names",IDC_STATIC,3,6,300,104
+ CONTROL "Enable highlighting for user names",IDC_HIGHLIGHTNICKENABLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,20,278,11
+ CONTROL "Also look in user ids",IDC_HIGHLIGHTNICKUID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,34,278,11
+ EDITTEXT IDC_HIGHLIGHTNICKPATTERN,11,69,283,35,ES_AUTOHSCROLL
+ LTEXT "Names to highlight, wildcards like * and ? are allowed, separate multiple entries with spaces",IDC_STATIC,10,49,284,19
+ GROUPBOX "Highlight message text",IDC_STATIC,3,113,300,122
+ CONTROL "Enable highlighting for message text",IDC_HIGHLIGHTTEXTENABLE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,125,278,11
+ EDITTEXT IDC_HIGHLIGHTTEXTPATTERN,11,172,283,35,ES_AUTOHSCROLL
+ LTEXT "Words to highlight, wildcards like * and ? are allowed, separate multiple entries with spaces. Leave it empty if you only want to highlight your own nick name.",IDC_STATIC,10,141,284,23
+ CONTROL "Highlight messages containing my own nick name",IDC_HIGHLIGHTME,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,216,278,11
+END
+
+IDD_COLORCHOOSER DIALOGEX 0, 0, 198, 150
+STYLE DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_BORDER
+EXSTYLE WS_EX_TOPMOST
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,172,136,26,14,NOT WS_TABSTOP
+ CTEXT "",IDC_COLORTEXT,0,0,197,12,SS_CENTERIMAGE
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ 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
+ RIGHTMARGIN, 300
+ VERTGUIDE, 10
+ VERTGUIDE, 152
+ 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
+ HORZGUIDE, 107
+ HORZGUIDE, 126
+ HORZGUIDE, 146
+ HORZGUIDE, 150
+ HORZGUIDE, 174
+ HORZGUIDE, 212
+ END
+
+ IDD_OPTIONS3, DIALOG
+ BEGIN
+ END
+
+ IDD_OPTIONS4, DIALOG
+ BEGIN
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Swedish (Sweden) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE)
+LANGUAGE LANG_SWEDISH, SUBLANG_SWEDISH
+#pragma code_page(1252)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "chat_resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "#include ""richedit.h""\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 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
+
+#endif // Swedish (Sweden) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/TabSRMM/chat/chat_resource.h b/plugins/TabSRMM/chat/chat_resource.h
new file mode 100644
index 0000000000..07a9bb8ba4
--- /dev/null
+++ b/plugins/TabSRMM/chat/chat_resource.h
@@ -0,0 +1,161 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by chat.rc
+//
+#define IDR_MENU 151
+#define IDD_CHANNEL 401
+#define IDD_OPTIONS1 402
+#define IDD_OPTIONS2 403
+#define IDD_FILTER 404
+#define IDD_OPTIONSPOPUP 405
+#define IDD_COLORCHOOSER 406
+#define IDD_OPTIONS3 407
+#define IDD_OPTIONS4 408
+#define IDD_ADDHIGHLIGHT 409
+#define IDC_CHAT_LOG 1005
+#define IDC_SPLITTERX 1006
+#define IDC_SMILEY 1007
+#define IDC_SPLITTERY 1008
+#define IDC_CHAT_MESSAGE 1009
+#define IDC_FILTER 1013
+#define IDC_CHANMGR 1014
+#define IDC_SHOWNICKLIST 1015
+#define IDC_BKGCOLOR 1019
+#define IDC_CHECKBOXES 1021
+#define IDC_NICKROW2 1023
+#define IDC_NICKROW 1024
+#define IDC_LOGLIMIT 1024
+#define IDC_CHAT_CLOSE 1025
+#define IDC_CHAT_SPIN1 1028
+#define IDC_CHAT_SPIN2 1029
+#define IDC_CHAT_SPIN3 1030
+#define IDC_CHAT_SPIN4 1031
+#define IDC_PANELNICK 1032
+#define IDC_PANELUIN 1033
+#define IDC_INSTAMP 1041
+#define IDC_OUTSTAMP 1043
+#define IDC_TIMESTAMP 1046
+#define IDC_FONTCHOOSE 1047
+#define IDC_LOGDIRECTORY 1048
+#define IDC_LIMIT 1050
+#define IDC_LOGTIMESTAMP 1051
+#define IDC_GROUP 1057
+#define IDC_CHAT_RADIO1 1061
+#define IDC_RADIO2 1062
+#define IDC_RADIO3 1063
+#define IDC_TEXT 1064
+#define IDC_BKG 1065
+#define IDC_TIMEOUT 1067
+#define IDC_TEXTO 1069
+#define IDC_LOGGING 1069
+#define IDC_COLORTEXT 1070
+#define IDC_TEXTO2 1070
+#define IDC_TEXTO3 1071
+#define IDC_LIST 1072
+#define IDC_TEXTO4 1072
+#define IDC_STATIC_ADD 1077
+#define IDC_STATIC_ULIST 1078
+#define IDC_STATIC_OTHER 1079
+#define IDC_STATIC_MESSAGE 1081
+#define IDC_STATIC110 1082
+#define IDC_STATIC112 1085
+#define IDC_TRAYONLYFORINACTIVE 1086
+#define IDC_NOPOPUPSFORCLOSEDWINDOWS 1087
+#define IDC_LOGICONTYPE 1088
+#define IDC_HIGHLIGHTNICKENABLE 1089
+#define IDC_HIGHLIGHTNICKUID 1090
+#define IDC_HIGHLIGHTNICKPATTERN 1091
+#define IDC_HIGHLIGHTTEXTENABLE 1092
+#define IDC_COMBO1 1092
+#define IDC_ADDHIGHLIGHTNAME 1092
+#define IDC_HIGHLIGHTTEXTPATTERN 1093
+#define IDC_ADDHIGHLIGHTTITLE 1093
+#define IDC_ADDHIGHLIGHTEXPLAIN 1094
+#define IDC_HIGHLIGHTNICKUID2 1094
+#define IDC_HIGHLIGHTME 1094
+#define IDC_ADDHIGHLIGHTEDITLIST 1095
+#define IDC_MUC_OPENLOGBASEDIR 1096
+#define IDC_CHAT_BOLD 1106
+#define IDC_ITALICS 1107
+#define IDC_CHAT_UNDERLINE 1108
+#define IDC_COLOR 1110
+#define IDC_CHAT_HISTORY 1111
+#define IDC_1 1200
+#define IDC_2 1201
+#define IDC_3 1202
+#define IDC_4 1203
+#define IDC_5 1204
+#define IDC_6 1205
+#define IDC_7 1206
+#define IDC_8 1207
+#define IDC_9 1208
+#define IDC_10 1209
+#define IDC_11 1210
+#define IDC_PANELSPLITTER 1216
+#define IDC_CHAT_TOGGLESIDEBAR 1277
+#define IDC_P1 1300
+#define IDC_P2 1301
+#define IDC_P3 1302
+#define IDC_P4 1303
+#define IDC_P5 1304
+#define IDC_P6 1305
+#define IDC_P7 1306
+#define IDC_P8 1307
+#define IDC_P9 1308
+#define IDC_P10 1309
+#define IDC_P11 1310
+#define IDC_P12 1311
+#define IDC_T1 1400
+#define IDC_T2 1401
+#define IDC_T3 1402
+#define IDC_T4 1403
+#define IDC_T5 1404
+#define IDC_T6 1405
+#define IDC_T7 1406
+#define IDC_T8 1407
+#define IDC_T9 1408
+#define IDC_T10 1409
+#define IDC_T11 1410
+#define IDC_T12 1411
+#define IDC_L1 1500
+#define IDC_L2 1501
+#define IDC_L3 1502
+#define IDC_L4 1503
+#define IDC_L5 1504
+#define IDC_L6 1505
+#define IDC_L7 1506
+#define IDC_L8 1507
+#define IDC_L9 1508
+#define IDC_L10 1509
+#define IDC_L11 1510
+#define IDC_WHITERECT 1600
+#define ID_MESS 40001
+#define ID_NEW 40002
+#define ID_CURR 40003
+#define ID_COPY 40004
+#define ID_COPYALL 40006
+#define ID_CLEARLOG 40009
+#define ID_MESSAGE_UNDO 40013
+#define ID_MESSAGE_COPY 40014
+#define ID_MESSAGE_CUT 40015
+#define ID_MESSAGE_CLEAR 40017
+#define ID_MESSAGE_SELECTALL 40018
+#define ID_MESSAGE_REDO 40019
+#define ID_MESSAGE_PASTE 40020
+#define ID_CLOSE 40022
+#define ID_CLOSEOTHER 40023
+#define ID_LOCKPOSITION 40024
+#define ID_SEARCH_GOOGLE 40027
+#define ID_SEARCH_WIKIPEDIA 40028
+#define ID_WIKIPEDIA_ 40029
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 163
+#define _APS_NEXT_COMMAND_VALUE 40030
+#define _APS_NEXT_CONTROL_VALUE 1097
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/TabSRMM/chat/chatprototypes.h b/plugins/TabSRMM/chat/chatprototypes.h
new file mode 100644
index 0000000000..066a25e919
--- /dev/null
+++ b/plugins/TabSRMM/chat/chatprototypes.h
@@ -0,0 +1,174 @@
+/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003-2009 Joergen Persson and others
+
+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.
+
+$Id: chatprototypes.h 13184 2010-12-07 14:16:58Z silvercircle $
+
+*/
+
+void LoadIcons(void);
+void LoadLogIcons(void);
+void FreeIcons(void);
+void UpgradeCheck(void);
+
+//colorchooser.c
+INT_PTR CALLBACK DlgProcColorToolWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//log.c
+void Log_StreamInEvent(HWND hwndDlg, LOGINFO* lin, SESSION_INFO* si, BOOL bRedraw, BOOL bPhaseTwo);
+void LoadMsgLogBitmaps(void);
+void FreeMsgLogBitmaps(void);
+TCHAR* GetChatLogsFilename(SESSION_INFO *si, time_t tTime);
+TCHAR* MakeTimeStamp(TCHAR* pszStamp, time_t time);
+char* Log_CreateRtfHeader(MODULEINFO * mi);
+
+//window.c
+INT_PTR CALLBACK RoomWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+int GetTextPixelSize( TCHAR* pszText, HFONT hFont, BOOL bWidth);
+
+//options.c
+enum { FONTSECTION_AUTO, FONTSECTION_CHAT, FONTSECTION_IM, FONTSECTION_IP };
+int OptionsInit(void);
+int OptionsUnInit(void);
+void LoadMsgDlgFont(int section, int i, LOGFONT * lf, COLORREF * colour, char* szMod );
+void LoadGlobalSettings(void);
+void AddIcons(void);
+HICON LoadIconEx(int iIndex, char * pszIcoLibName, int iX, int iY);
+
+//services.c
+void HookEvents(void);
+void UnhookEvents(void);
+int CreateServiceFunctions(void);
+void DestroyServiceFunctions(void);
+void DestroyHookableEvents(void);
+void CreateHookableEvents(void);
+void TabsInit(void);
+int ModulesLoaded(WPARAM wParam,LPARAM lParam);
+int SmileyOptionsChanged(WPARAM wParam,LPARAM lParam);
+int PreShutdown(WPARAM wParam,LPARAM lParam);
+int IconsChanged(WPARAM wParam,LPARAM lParam);
+void ShowRoom(SESSION_INFO* si, WPARAM wp, BOOL bSetForeground);
+INT_PTR Service_AddEvent(WPARAM wParam, LPARAM lParam);
+int Service_ItemData(WPARAM wParam, LPARAM lParam);
+int Service_SetSBText(WPARAM wParam, LPARAM lParam);
+int Service_SetVisibility(WPARAM wParam, LPARAM lParam);
+INT_PTR Service_GetCount(WPARAM wParam,LPARAM lParam);
+
+HWND CreateNewRoom(TContainerData *pContainer, SESSION_INFO *si, BOOL bActivateTab, BOOL bPopupContainer, BOOL bWantPopup);
+
+//manager.c
+void SetActiveSession(const TCHAR* pszID, const char* pszModule);
+void SetActiveSessionEx(SESSION_INFO* si);
+SESSION_INFO* GetActiveSession(void);
+SESSION_INFO* SM_AddSession(const TCHAR* pszID, const char* pszModule);
+int SM_RemoveSession(const TCHAR* pszID, const char* pszModule);
+SESSION_INFO* SM_FindSession(const TCHAR* pszID, const char* pszModule);
+USERINFO* SM_AddUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus);
+SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const TCHAR* pszOriginal, const TCHAR* pszCurrent);
+BOOL SM_ChangeUID(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNewUID);
+BOOL SM_ChangeNick(const TCHAR* pszID, const char* pszModule, GCEVENT * gce);
+BOOL SM_RemoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID);
+BOOL SM_SetOffline(const TCHAR* pszID, const char* pszModule);
+HICON SM_GetStatusIcon(SESSION_INFO* si, USERINFO* ui, char* szIndicator);
+BOOL SM_SetStatus(const TCHAR* pszID, const char* pszModule, int wStatus);
+BOOL SM_SetStatusEx(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText, int flags );
+BOOL SM_SendUserMessage(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText);
+STATUSINFO* SM_AddStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszStatus);
+BOOL SM_AddEventToAllMatchingUID(GCEVENT * gce, BOOL bisHighLight = FALSE);
+BOOL SM_AddEvent(const TCHAR* pszID, const char* pszModule, GCEVENT * gce, BOOL bIsHighlighted);
+LRESULT SM_SendMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL SM_PostMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL SM_BroadcastMessage(const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAsync);
+BOOL SM_RemoveAll (void);
+BOOL SM_GiveStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus);
+BOOL SM_SetContactStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, WORD pszStatus);
+BOOL SM_TakeStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus);
+BOOL SM_MoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID);
+void SM_AddCommand(const TCHAR* pszID, const char* pszModule, const char* lpNewCommand);
+char* SM_GetPrevCommand(const TCHAR* pszID, const char* pszModule);
+char* SM_GetNextCommand(const TCHAR* pszID, const char* pszModule);
+int SM_GetCount(const char* pszModule);
+SESSION_INFO* SM_FindSessionByHWND(HWND h);
+SESSION_INFO* SM_FindSessionByHCONTACT(HANDLE h);
+SESSION_INFO* SM_FindSessionByIndex(const char* pszModule, int iItem);
+char* SM_GetUsers(SESSION_INFO* si);
+USERINFO* SM_GetUserFromIndex(const TCHAR* pszID, const char* pszModule, int index);
+BOOL SM_ReconfigureFilters();
+BOOL SM_InvalidateLogDirectories();
+MODULEINFO* MM_AddModule(const char* pszModule);
+MODULEINFO* MM_FindModule(const char* pszModule);
+void MM_FixColors();
+void MM_FontsChanged(void);
+void MM_IconsChanged(void);
+BOOL MM_RemoveAll (void);
+BOOL TabM_AddTab(const TCHAR* pszID, const char* pszModule);
+BOOL TabM_RemoveAll (void);
+STATUSINFO* TM_AddStatus(STATUSINFO** ppStatusList, const TCHAR* pszStatus, int* iCount);
+STATUSINFO* TM_FindStatus(STATUSINFO* pStatusList, const TCHAR* pszStatus);
+WORD TM_StringToWord(STATUSINFO* pStatusList, const TCHAR* pszStatus);
+TCHAR* TM_WordToString(STATUSINFO* pStatusList, WORD Status);
+BOOL TM_RemoveAll (STATUSINFO** pStatusList);
+BOOL UM_SetStatusEx(USERINFO* pUserList,const TCHAR* pszText, int onlyMe );
+USERINFO* UM_AddUser(STATUSINFO* pStatusList, USERINFO** pUserList, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus);
+USERINFO* UM_SortUser(USERINFO** ppUserList, const TCHAR* pszUID);
+USERINFO* UM_FindUser(USERINFO* pUserList, const TCHAR* pszUID);
+USERINFO* UM_FindUserFromIndex(USERINFO* pUserList, int index);
+USERINFO* UM_GiveStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status);
+USERINFO* UM_SetContactStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status);
+USERINFO* UM_TakeStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status);
+TCHAR* UM_FindUserAutoComplete(USERINFO* pUserList, const TCHAR* pszOriginal, const TCHAR* pszCurrent);
+BOOL UM_RemoveUser(USERINFO** pUserList, const TCHAR* pszUID);
+BOOL UM_RemoveAll (USERINFO** ppUserList);
+LOGINFO* LM_AddEvent(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd);
+BOOL LM_TrimLog(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd, int iCount);
+BOOL LM_RemoveAll (LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd);
+
+//clist.c
+HANDLE CList_AddRoom(const char* pszModule, const TCHAR* pszRoom, const TCHAR* pszDisplayName, int iType);
+BOOL CList_SetOffline(HANDLE hContact, BOOL bHide);
+BOOL CList_SetAllOffline(BOOL bHide, const char *pszModule);
+int CList_RoomDoubleclicked(WPARAM wParam,LPARAM lParam);
+INT_PTR CList_EventDoubleclicked(WPARAM wParam,LPARAM lParam);
+INT_PTR CList_JoinChat(WPARAM wParam, LPARAM lParam);
+INT_PTR CList_LeaveChat(WPARAM wParam, LPARAM lParam);
+int CList_PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+INT_PTR CList_PrebuildContactMenuSvc(WPARAM wParam, LPARAM lParam);
+void CList_CreateGroup(TCHAR* group);
+BOOL CList_AddEvent(HANDLE hContact, HICON Icon, HANDLE event, int type, const TCHAR* fmt, ... ) ;
+HANDLE CList_FindRoom (const char* pszModule, const TCHAR* pszRoom) ;
+int WCCmp(TCHAR* wild, TCHAR*string);
+
+//tools.c
+TCHAR* RemoveFormatting(const TCHAR* pszText, bool fLower = false, bool fStripCR = false, TCHAR* buf = 0, const size_t len = 0);
+BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix);
+int Chat_GetColorIndex(const char* pszModule, COLORREF cr);
+void CheckColorsInModule(const char* pszModule);
+TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2) ;
+int GetRichTextLength(HWND hwnd);
+BOOL IsHighlighted(SESSION_INFO* si, const TCHAR* pszText);
+UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText);
+void DestroyGCMenu(HMENU *hMenu, int iIndex);
+BOOL DoEventHookAsync(HWND hwnd, const TCHAR* pszID, const char* pszModule, int iType, TCHAR* pszUID, TCHAR* pszText, DWORD dwItem);
+BOOL DoEventHook(const TCHAR* pszID, const char* pszModule, int iType, const TCHAR* pszUID, const TCHAR* pszText, DWORD dwItem);
+BOOL IsEventSupported(int eventType);
+BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce);
+void Chat_SetFilters(SESSION_INFO *si);
+void TSAPI DoFlashAndSoundWorker(FLASH_PARAMS* p);
+// message.c
+char* Chat_Message_GetFromStream(HWND hwndDlg, SESSION_INFO* si);
+TCHAR* Chat_DoRtfToTags( char* pszRtfText, SESSION_INFO* si);
diff --git a/plugins/TabSRMM/chat/clist.cpp b/plugins/TabSRMM/chat/clist.cpp
new file mode 100644
index 0000000000..d321c4d017
--- /dev/null
+++ b/plugins/TabSRMM/chat/clist.cpp
@@ -0,0 +1,326 @@
+/*
+astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ --pad=oper --one-line=keep-blocks --unpad=paren
+
+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.
+
+Group chat module: contact list support functions. Add chat rooms as
+contacts and handle default action for such contacts.
+
+This code was taken in almost unmodified from from the chat.dll
+plugin, originally written by Jörgen Persson
+
+$Id: clist.c 10402 2009-07-24 00:35:21Z silvercircle $
+
+*/
+
+/*
+ * handles interaction of the group chat implementation with the contact list plugin
+ */
+
+#include "../src/commonheaders.h"
+
+char *szChatIconString = "chaticon";
+
+extern HANDLE hJoinMenuItem, hLeaveMenuItem;
+
+static HANDLE Clist_GroupExists(TCHAR *tszGroup)
+{
+ unsigned int i = 0;
+ TCHAR* _t = 0;
+ char str[10];
+ INT_PTR result = 0;
+ DBVARIANT dbv = {0};
+ int match;
+
+ do {
+ _itoa(i, str, 10);
+ result = M->GetTString(0, "CListGroups", str, &dbv);
+ if(!result) {
+ match = (!_tcscmp(tszGroup, &dbv.ptszVal[1]) && (lstrlen(tszGroup) == lstrlen(&dbv.ptszVal[1])));
+ DBFreeVariant(&dbv);
+ if(match)
+ return((HANDLE)(i + 1));
+ }
+ i++;
+ }
+ while(result == 0);
+ return(0);
+}
+
+HANDLE CList_AddRoom(const char* pszModule, const TCHAR* pszRoom, const TCHAR* pszDisplayName, int iType)
+{
+ HANDLE hContact = CList_FindRoom(pszModule, pszRoom);
+ DBVARIANT dbv;
+ TCHAR pszGroup[50];
+
+ *pszGroup = '\0';
+ if (!M->GetTString(NULL, "Chat", "AddToGroup", &dbv)) {
+ if (lstrlen(dbv.ptszVal) > 0)
+ lstrcpyn(pszGroup, dbv.ptszVal, 50);
+ DBFreeVariant(&dbv);
+ } else
+ lstrcpyn(pszGroup, _T("Chat rooms"), 50);
+
+ if (pszGroup[0])
+ CList_CreateGroup(pszGroup);
+
+ if (hContact)
+ return hContact;
+
+ // here we create a new one since no one is to be found
+
+ if ((hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0)) == NULL)
+ return NULL;
+
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) pszModule);
+ if (pszGroup && lstrlen(pszGroup) > 0)
+ CallService(MS_CLIST_CONTACTCHANGEGROUP, (WPARAM)hContact, (LPARAM)g_Settings.hGroup);
+ else
+ DBDeleteContactSetting(hContact, "CList", "Group");
+
+ M->WriteTString(hContact, pszModule, "Nick", pszDisplayName);
+ M->WriteTString(hContact, pszModule, "ChatRoomID", pszRoom);
+ M->WriteByte(hContact, pszModule, "ChatRoom", (BYTE)iType);
+ DBWriteContactSettingWord(hContact, pszModule, "Status", ID_STATUS_OFFLINE);
+ return hContact;
+}
+
+BOOL CList_SetOffline(HANDLE hContact, BOOL bHide)
+{
+ if (hContact) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ int i = M->GetByte(hContact, szProto, "ChatRoom", 0);
+ DBWriteContactSettingWord(hContact, szProto, "ApparentMode", (LPARAM) 0);
+ DBWriteContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CList_SetAllOffline(BOOL bHide, const char *pszModule)
+{
+ HANDLE hContact;
+ char* szProto;
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact) {
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (MM_FindModule(szProto)) {
+ if (!pszModule || (pszModule && !strcmp(pszModule, szProto))) {
+ int i = M->GetByte(hContact, szProto, "ChatRoom", 0);
+ if (i != 0) {
+ DBWriteContactSettingWord(hContact, szProto, "ApparentMode", (LPARAM)(WORD) 0);
+ DBWriteContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ }
+ }
+ }
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ return TRUE;
+}
+
+int CList_RoomDoubleclicked(WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ char *szProto;
+ BOOL bRedrawFlag = FALSE;
+ bool fCreate = false;
+
+ HANDLE hContact = (HANDLE)wParam;
+ if (!hContact)
+ return 0;
+
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (MM_FindModule(szProto)) {
+ if (M->GetByte(hContact, szProto, "ChatRoom", 0) == 0)
+ return 0;
+
+ if (!M->GetTString(hContact, szProto, "ChatRoomID", &dbv)) {
+ SESSION_INFO* si = SM_FindSession(dbv.ptszVal, szProto);
+ if (si) {
+ // is the "toggle visibility option set, so we need to close the window?
+ if (si->hWnd != NULL
+ && M->GetByte("Chat", "ToggleVisibility", 0) == 1
+ && !CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0)
+ && IsWindowVisible(si->hWnd)
+ && !IsIconic(si->pContainer->hwnd)) {
+ PostMessage(si->hWnd, GC_CLOSEWINDOW, 0, 0);
+ DBFreeVariant(&dbv);
+ return 1;
+ }
+ else
+ fCreate = true;
+
+ ShowRoom(si, WINDOW_VISIBLE, TRUE);
+ if(lParam && fCreate) {
+ SendMessage(si->hWnd, DM_ACTIVATEME, 0, 0);
+ if(si->dat)
+ SetForegroundWindow(si->dat->pContainer->hwnd);
+ }
+ }
+ DBFreeVariant(&dbv);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+INT_PTR CList_EventDoubleclicked(WPARAM wParam, LPARAM lParam)
+{
+ return CList_RoomDoubleclicked((WPARAM)((CLISTEVENT*)lParam)->hContact, (LPARAM) 0);
+}
+
+INT_PTR CList_JoinChat(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if ( hContact ) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if ( szProto ) {
+ if ( DBGetContactSettingWord( hContact, szProto, "Status", 0 ) == ID_STATUS_OFFLINE )
+ CallProtoService( szProto, PS_JOINCHAT, wParam, lParam );
+ else
+ CList_RoomDoubleclicked( wParam, 0 );
+ } }
+
+ return 0;
+}
+
+INT_PTR CList_LeaveChat(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if ( hContact ) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if ( szProto )
+ CallProtoService( szProto, PS_LEAVECHAT, wParam, lParam );
+ }
+ return 0;
+}
+
+int CList_PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if ( hContact ) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+
+ CLISTMENUITEM clmi = {0};
+ clmi.cbSize = sizeof( CLISTMENUITEM );
+ clmi.flags = CMIM_FLAGS | CMIF_DEFAULT | CMIF_HIDDEN;
+
+ if ( szProto ) {
+ // display this menu item only for chats
+ if ( M->GetByte(hContact, szProto, "ChatRoom", 0 )) {
+ // still hide it for offline protos
+ if ( CallProtoService( szProto, PS_GETSTATUS, 0, 0 ) != ID_STATUS_OFFLINE ) {
+ clmi.flags &= ~CMIF_HIDDEN;
+ clmi.flags |= CMIM_NAME;
+
+ if ( DBGetContactSettingWord( hContact, szProto, "Status", 0 ) == ID_STATUS_OFFLINE )
+ clmi.pszName = ( char* )LPGEN("Join chat");
+ else
+ clmi.pszName = ( char* )LPGEN("Open chat window");
+ } } }
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hJoinMenuItem, ( LPARAM )&clmi );
+
+ clmi.flags &= ~(CMIM_NAME | CMIF_DEFAULT);
+ clmi.flags |= CMIF_NOTOFFLINE;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hLeaveMenuItem, ( LPARAM )&clmi );
+ }
+ return 0;
+}
+
+INT_PTR CList_PrebuildContactMenuSvc(WPARAM wParam, LPARAM lParam)
+{
+ return CList_PrebuildContactMenu(wParam, lParam);
+}
+
+
+void CList_CreateGroup(TCHAR* group)
+{
+ if (!group)
+ return;
+
+ g_Settings.hGroup = Clist_GroupExists(group);
+
+ if(g_Settings.hGroup == 0) {
+ g_Settings.hGroup = (HANDLE)CallService(MS_CLIST_GROUPCREATE, 0, (LPARAM)group);
+
+ if(g_Settings.hGroup) {
+ CallService(MS_CLUI_GROUPADDED, (WPARAM)g_Settings.hGroup, 0);
+ CallService(MS_CLIST_GROUPSETEXPANDED, (WPARAM)g_Settings.hGroup, 1);
+ }
+ }
+}
+
+BOOL CList_AddEvent(HANDLE hContact, HICON Icon, HANDLE event, int type, const TCHAR* fmt, ...)
+{
+ CLISTEVENT cle;
+ va_list marker;
+ TCHAR* szBuf = (TCHAR*)alloca(4096 * sizeof(TCHAR));
+
+ if (!fmt || lstrlen(fmt) < 1 || lstrlen(fmt) > 2000)
+ return FALSE;
+
+ va_start(marker, fmt);
+ _vstprintf(szBuf, fmt, marker);
+ va_end(marker);
+
+ cle.cbSize = sizeof(cle);
+ cle.hContact = (HANDLE)hContact;
+ cle.hDbEvent = (HANDLE)event;
+ cle.flags = type + CLEF_TCHAR;
+ cle.hIcon = Icon;
+ cle.pszService = "GChat/DblClickEvent" ;
+ cle.ptszTooltip = TranslateTS(szBuf);
+ if (type) {
+ if (!CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, (LPARAM)0))
+ CallService(MS_CLIST_ADDEVENT, (WPARAM) hContact, (LPARAM) &cle);
+ } else {
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)"chaticon");
+ CallService(MS_CLIST_ADDEVENT, (WPARAM) hContact, (LPARAM) &cle);
+ }
+ return TRUE;
+}
+
+HANDLE CList_FindRoom(const char* pszModule, const TCHAR* pszRoom)
+{
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto && !lstrcmpiA(szProto, pszModule)) {
+ if (M->GetByte(hContact, szProto, "ChatRoom", 0) != 0) {
+ DBVARIANT dbv;
+ if (!M->GetTString(hContact, szProto, "ChatRoomID", &dbv)) {
+ if (!lstrcmpi(dbv.ptszVal, pszRoom)) {
+ DBFreeVariant(&dbv);
+ return hContact;
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ return 0;
+}
+
diff --git a/plugins/TabSRMM/chat/colorchooser.cpp b/plugins/TabSRMM/chat/colorchooser.cpp
new file mode 100644
index 0000000000..4879f56d95
--- /dev/null
+++ b/plugins/TabSRMM/chat/colorchooser.cpp
@@ -0,0 +1,281 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * $Id: colorchooser.cpp 10670 2009-09-11 03:28:50Z silvercircle $
+ *
+ * Color chooser for group chats
+ *
+ */
+
+#include "../src/commonheaders.h"
+#include <math.h>
+
+static int CalculateCoordinatesToButton(COLORCHOOSER * pCC, POINT pt)
+{
+ int iSquareRoot = (int)sqrt(static_cast<float>(pCC->pModule->nColorCount));
+ int nCols = iSquareRoot * iSquareRoot < pCC->pModule->nColorCount ? iSquareRoot + 1 : iSquareRoot;
+
+ int col = pt.x / 25;
+ int row = (pt.y - 20) / 20;
+ int pos = nCols * row + col;
+
+ if (pt.y < 20 && pos >= pCC->pModule->nColorCount)
+ pos = -1;
+
+ return pos;
+}
+
+static RECT CalculateButtonToCoordinates(COLORCHOOSER * pCC, int buttonPosition)
+{
+ RECT pt;
+ int iSquareRoot = (int)sqrt(static_cast<float>(pCC->pModule->nColorCount));
+ int nCols = iSquareRoot * iSquareRoot < pCC->pModule->nColorCount ? iSquareRoot + 1 : iSquareRoot;
+
+ int row = buttonPosition / nCols;
+ int col = buttonPosition % nCols;
+
+ pt.left = col * 25 + 1;
+ pt.top = row * 20 + 20;
+ pt.right = pt.left + 25 - 1;
+ pt.bottom = pt.top + 20;
+
+ return pt;
+}
+
+INT_PTR CALLBACK DlgProcColorToolWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static COLORCHOOSER* pCC = NULL;
+ static int iCurrentHotTrack;
+ static BOOL bChoosing;
+ static int iRows;
+ static int iColumns;
+ static HWND hPreviousActiveWindow;
+
+ switch (msg) {
+ case WM_INITDIALOG: {
+ RECT rc;
+ int iSquareRoot;
+ int width ;
+ int height;
+
+ TranslateDialogDefault(hwndDlg);
+ pCC = (COLORCHOOSER*) lParam;
+
+ iCurrentHotTrack = -2;
+ bChoosing = FALSE;
+
+ iSquareRoot = (int)sqrt(static_cast<float>(pCC->pModule->nColorCount));
+
+ iColumns = iSquareRoot * iSquareRoot == pCC->pModule->nColorCount ? iSquareRoot : iSquareRoot + 1;
+ iRows = iSquareRoot;
+
+ rc.top = rc.left = 100;
+ rc.right = 100 + iColumns * 25 + 1;
+ rc.bottom = iRows * 20 + 100 + 20;
+
+ AdjustWindowRectEx(&rc, GetWindowLongPtr(hwndDlg, GWL_STYLE), FALSE, GetWindowLongPtr(hwndDlg, GWL_EXSTYLE));
+
+ width = rc.right - rc.left;
+ height = rc.bottom - rc.top;
+
+ pCC->yPosition -= height;
+
+
+ SetDlgItemText(hwndDlg, IDC_COLORTEXT, pCC->bForeground ? CTranslator::get(CTranslator::GEN_MUC_TEXTCOLOR) :
+ CTranslator::get(CTranslator::GEN_MUC_BGCOLOR));
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_COLORTEXT), NULL, 0, 0, width, 20, 0);
+ SetWindowPos(hwndDlg, NULL, pCC->xPosition, pCC->yPosition, width, height, SWP_SHOWWINDOW);
+ }
+ break;
+
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_COLORTEXT)) {
+ SetTextColor((HDC)wParam, RGB(60, 60, 150));
+ SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
+ return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ if (iCurrentHotTrack >= 0)
+ PostMessage(hwndDlg, WM_LBUTTONUP, 0, 0);
+ break;
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if (iCurrentHotTrack >= 0 && iCurrentHotTrack < pCC->pModule->nColorCount && pCC->hWndTarget != NULL) {
+ HWND hWindow;
+ CHARFORMAT2 cf;
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwMask = 0;
+ cf.dwEffects = 0;
+ hWindow = GetParent(pCC->hWndTarget);
+
+ if (pCC->bForeground) {
+ pCC->si->bFGSet = TRUE;
+ pCC->si->iFG = iCurrentHotTrack;
+ if (IsDlgButtonChecked(hWindow, IDC_COLOR)) {
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = pCC->pModule->crColors[iCurrentHotTrack];
+ SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } else {
+ pCC->si->bBGSet = TRUE;
+ pCC->si->iBG = iCurrentHotTrack;
+ if (IsDlgButtonChecked(hWindow, IDC_BKGCOLOR)) {
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = pCC->pModule->crColors[iCurrentHotTrack];
+ SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ }
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ break;
+
+ case WM_ACTIVATE:
+ if (wParam == WA_INACTIVE)
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ else if ((wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE))
+ hPreviousActiveWindow = (HWND)lParam;
+ break;
+
+ case WM_MOUSEMOVE: {
+ HDC hdc = GetDC(hwndDlg);
+ POINT pt;
+ RECT rect;
+ int but;
+
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+
+ if (iCurrentHotTrack == -2)
+ return 0; // prevent focussing when not drawn yet!
+
+ but = CalculateCoordinatesToButton(pCC, pt);
+
+ // weird stuff
+ if (but != iCurrentHotTrack) {
+ if (iCurrentHotTrack >= 0) {
+ rect = CalculateButtonToCoordinates(pCC, iCurrentHotTrack);
+ DrawFocusRect(hdc, &rect);
+ iCurrentHotTrack = -1;
+ }
+ iCurrentHotTrack = but;
+
+ if (iCurrentHotTrack >= 0) {
+ rect = CalculateButtonToCoordinates(pCC, iCurrentHotTrack);
+ DrawFocusRect(hdc, &rect);
+ }
+ }
+ ReleaseDC(hwndDlg, hdc);
+ }
+ break;
+
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ HDC hdc;
+ RECT rc;
+ int i = 0;
+ int iThisRow = 1;
+ int iThisColumn = 0;
+
+ GetClientRect(hwndDlg, &rc);
+
+ rc.top += 20;
+
+ hdc = BeginPaint(hwndDlg, &ps);
+
+ // fill background
+ FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW));
+
+ for (i; i < pCC->pModule->nColorCount; i++) {
+ HBRUSH hbr;
+
+ // decide place to draw the color block in the window
+ iThisColumn ++;
+ if (iThisColumn > iColumns) {
+ iThisColumn = 1;
+ iThisRow++;
+ }
+
+ if (pCC->bForeground && pCC->si->bFGSet && pCC->si->iFG == i ||
+ !pCC->bForeground && pCC->si->bBGSet && pCC->si->iBG == i) {
+ rc.top = (iThisRow - 1) * 20 + 1 + 20 ;
+ rc.left = (iThisColumn - 1) * 25 + 1 + 1 ;
+ rc.bottom = iThisRow * 20 - 1 + 20 ;
+ rc.right = iThisColumn * 25 - 1 ;
+
+ DrawEdge(hdc, &rc, EDGE_RAISED, BF_TOP | BF_LEFT | BF_RIGHT | BF_BOTTOM);
+ }
+
+ rc.top = (iThisRow - 1) * 20 + 3 + 20 ;
+ rc.left = (iThisColumn - 1) * 25 + 3 + 1 ;
+ rc.bottom = iThisRow * 20 - 3 + 20 ;
+ rc.right = iThisColumn * 25 - 3 ;
+
+ FillRect(hdc, &rc, CSkin::m_BrushBack);
+
+ hbr = CreateSolidBrush(pCC->pModule->crColors[i]);
+
+ rc.top = (iThisRow - 1) * 20 + 4 + 20;
+ rc.left = (iThisColumn - 1) * 25 + 4 + 1;
+ rc.bottom = iThisRow * 20 - 4 + 20;
+ rc.right = iThisColumn * 25 - 4;
+
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ }
+
+ EndPaint(hwndDlg, &ps);
+ iCurrentHotTrack = -1;
+ }
+ break;
+
+ case WM_CLOSE:
+ SetFocus(pCC->hWndTarget);
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ mir_free(pCC);
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/plugins/TabSRMM/chat/log.cpp b/plugins/TabSRMM/chat/log.cpp
new file mode 100644
index 0000000000..7c167441d0
--- /dev/null
+++ b/plugins/TabSRMM/chat/log.cpp
@@ -0,0 +1,1352 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: log.cpp 13614 2011-04-22 13:16:21Z borkra $
+ *
+ * Implements the richedit-based message history display for the group
+ * chat window.
+ *
+ */
+
+#include "../src/commonheaders.h"
+#include <math.h>
+#include <mbstring.h>
+#include <shlwapi.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.
+ */
+
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+extern HICON hIcons[30];
+
+static PBYTE pLogIconBmpBits[14];
+static int logIconBmpSize[ SIZEOF(pLogIconBmpBits)];
+
+static int logPixelSY = 0;
+static int logPixelSX = 0;
+static char *szDivider = "\\strike----------------------------------------------------------------------------\\strike0";
+static char CHAT_rtfFontsGlobal[OPTIONS_FONTCOUNT + 2][RTFCACHELINESIZE];
+static char *CHAT_rtffonts = 0;
+
+/*
+ * ieview MUC support - mostly from scriver
+ */
+
+/*
+static char* u2a( const wchar_t* src, int codepage ) {
+ int cbLen = WideCharToMultiByte( codepage, 0, src, -1, NULL, 0, NULL, NULL );
+ char* result = ( char* )mir_alloc( cbLen+1 );
+ if ( result == NULL )
+ return NULL;
+
+ WideCharToMultiByte( codepage, 0, src, -1, result, cbLen, NULL, NULL );
+ result[ cbLen ] = 0;
+ return result;
+}
+
+static char* t2acp( const TCHAR* src, int codepage ) {
+ #if defined( _UNICODE )
+ return u2a( src, codepage );
+ #else
+ return mir_strdup( src );
+ #endif
+}
+
+static TCHAR *a2tcp(const char *text, int cp) {
+ if ( text != NULL ) {
+ #if defined ( _UNICODE )
+ int cbLen = MultiByteToWideChar( cp, 0, text, -1, NULL, 0 );
+ TCHAR* result = ( TCHAR* )mir_alloc( sizeof(TCHAR)*( cbLen+1 ));
+ if ( result == NULL )
+ return NULL;
+ MultiByteToWideChar(cp, 0, text, -1, result, cbLen);
+ return result;
+ #else
+ return mir_strdup(text);
+ #endif
+ }
+ return NULL;
+}
+
+static int Log_AppendIEView(LOGSTREAMDATA* streamData, BOOL simpleMode, TCHAR **buffer, int *cbBufferEnd, int *cbBufferAlloced, const TCHAR *fmt, ...)
+{
+ va_list va;
+ int lineLen, textCharsCount=0;
+ TCHAR* line = (TCHAR*)alloca( 8001 * sizeof(TCHAR));
+ TCHAR* d;
+ MODULEINFO *mi = MM_FindModule(streamData->si->pszModule);
+
+ va_start(va, fmt);
+ lineLen = _vsntprintf( line, 8000, fmt, va);
+ if (lineLen < 0)
+ return 0;
+ line[lineLen] = 0;
+ va_end(va);
+ lineLen = lineLen*9 + 8;
+ if (*cbBufferEnd + lineLen > *cbBufferAlloced) {
+ cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024);
+ *buffer = (TCHAR *) mir_realloc(*buffer, *cbBufferAlloced * sizeof(TCHAR));
+ }
+
+ d = *buffer + *cbBufferEnd;
+
+ for (; *line; line++, textCharsCount++) {
+ if (*line == '%' && !simpleMode ) {
+ TCHAR szTemp[200];
+
+ szTemp[0] = '\0';
+ switch ( *++line ) {
+ case '\0':
+ case '%':
+ *d++ = '%';
+ break;
+
+ case 'c':
+ case 'f':
+ if (!g_Settings.StripFormat && !streamData->bStripFormat) {
+ if ( line[1] != '\0' && line[2] != '\0') {
+ TCHAR szTemp3[3], c = *line;
+ int col;
+ szTemp3[0] = line[1];
+ szTemp3[1] = line[2];
+ szTemp3[2] = '\0';
+ col = _ttoi(szTemp3);
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%%%c#%02X%02X%02X"), c, GetRValue(mi->crColors[col]), GetGValue(mi->crColors[col]), GetBValue(mi->crColors[col]));
+ }
+ }
+ line += 2;
+ break;
+ case 'C':
+ case 'F':
+ if ( !g_Settings.StripFormat && !streamData->bStripFormat) {
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%%%c"), *line );
+ }
+ break;
+ case 'b':
+ case 'u':
+ case 'i':
+ case 'B':
+ case 'U':
+ case 'I':
+ case 'r':
+ if ( !streamData->bStripFormat ) {
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%%%c"), *line );
+ }
+ break;
+ }
+
+ if ( szTemp[0] ) {
+ size_t iLen = lstrlen(szTemp);
+ memcpy( d, szTemp, iLen * sizeof(TCHAR));
+ d += iLen;
+ }
+ }
+ else if (*line == '%') {
+ *d++ = '%';
+ *d++ = (char) *line;
+ }
+ else {
+ *d++ = (TCHAR) *line;
+ }
+ }
+ *d = '\0';
+ *cbBufferEnd = (int) (d - *buffer);
+ return textCharsCount;
+}
+
+static void AddEventTextToBufferIEView(TCHAR **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData)
+{
+ if (streamData->lin->ptszText)
+ Log_AppendIEView(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+}
+
+static void AddEventToBufferIEView(TCHAR **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData, TCHAR *pszNick)
+{
+
+ if ( streamData && streamData->lin ) {
+ switch ( streamData->lin->iType ) {
+ case GC_EVENT_MESSAGE:
+ if ( streamData->lin->ptszText ) {
+ TCHAR *ptszTemp = NULL;
+ TCHAR *ptszText = streamData->lin->ptszText;
+ #if defined( _UNICODE )
+ if (streamData->dat->codePage != CP_ACP) {
+ char *aText = t2acp(streamData->lin->ptszText, CP_ACP);
+ ptszText = ptszTemp = a2tcp(aText, streamData->dat->codePage);
+ mir_free(aText);
+ }
+ #endif
+ Log_AppendIEView( streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), ptszText );
+ mir_free(ptszTemp);
+ }
+ break;
+ case GC_EVENT_ACTION:
+ if ( pszNick && streamData->lin->ptszText) {
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, _T("%s "), streamData->lin->ptszNick);
+ Log_AppendIEView(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_JOIN:
+ if (pszNick) {
+ if (!streamData->lin->bIsMe)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has joined"), pszNick);
+ else
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("You have joined %s"), streamData->si->ptszName);
+ }
+ break;
+ case GC_EVENT_PART:
+ if (pszNick)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has left"), pszNick);
+ AddEventTextToBufferIEView(buffer, bufferEnd, bufferAlloced, streamData);
+ break;
+ case GC_EVENT_QUIT:
+ if (pszNick)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has disconnected"), pszNick);
+ AddEventTextToBufferIEView(buffer, bufferEnd, bufferAlloced, streamData);
+ break;
+ case GC_EVENT_NICK:
+ if (pszNick && streamData->lin->ptszText) {
+ if (!streamData->lin->bIsMe)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s is now known as %s"), pszNick, streamData->lin->ptszText);
+ else
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("You are now known as %s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_KICK:
+ if (pszNick && streamData->lin->ptszStatus)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s kicked %s"), streamData->lin->ptszStatus, streamData->lin->ptszNick);
+ AddEventTextToBufferIEView(buffer, bufferEnd, bufferAlloced, streamData);
+ break;
+ case GC_EVENT_NOTICE:
+ if (pszNick && streamData->lin->ptszText) {
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("Notice from %s"), pszNick );
+ AddEventTextToBufferIEView(buffer, bufferEnd, bufferAlloced, streamData);
+ }
+ break;
+ case GC_EVENT_TOPIC:
+ if (streamData->lin->ptszText)
+ Log_AppendIEView(streamData, FALSE, buffer, bufferEnd, bufferAlloced, TranslateT("The topic is \'%s%s\'"), streamData->lin->ptszText, _T("%r"));
+ if (pszNick)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ streamData->lin->ptszUserInfo ? TranslateT(" (set by %s on %s)"): TranslateT(" (set by %s)"),
+ pszNick, streamData->lin->ptszUserInfo);
+ break;
+ case GC_EVENT_INFORMATION:
+ if (streamData->lin->ptszText)
+ Log_AppendIEView(streamData, FALSE, buffer, bufferEnd, bufferAlloced, (streamData->lin->bIsMe) ? _T("--> %s") : _T("%s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_ADDSTATUS:
+ if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s enables \'%s\' status for %s"), streamData->lin->ptszText, streamData->lin->ptszStatus, streamData->lin->ptszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s disables \'%s\' status for %s"), streamData->lin->ptszText , streamData->lin->ptszStatus, streamData->lin->ptszNick);
+ break;
+ }
+ }
+}
+
+static void LogEventIEView(LOGSTREAMDATA *streamData, TCHAR *ptszNick)
+{
+ TCHAR *buffer = NULL;
+ int bufferEnd = 0;
+ int bufferAlloced = 0;
+ IEVIEWEVENTDATA ied;
+ IEVIEWEVENT event;
+ ZeroMemory(&event, sizeof(event));
+ event.cbSize = sizeof(event);
+ event.dwFlags = 0;
+ event.hwnd = streamData->dat->hwndIEView ? streamData->dat->hwndIEView : streamData->dat->hwndHPP;
+ event.hContact = streamData->dat->hContact;
+ event.codepage = streamData->dat->codePage;
+ event.pszProto = streamData->si->pszModule;
+ event.iType = IEE_LOG_MEM_EVENTS;
+ event.eventData = &ied;
+ event.count = 1;
+
+ ZeroMemory(&ied, sizeof(ied));
+ AddEventToBufferIEView(&buffer, &bufferEnd, &bufferAlloced, streamData, ptszNick);
+ ied.ptszNick = ptszNick;
+ ied.ptszText = buffer;
+ ied.time = streamData->lin->time;
+ ied.bIsMe = streamData->lin->bIsMe;
+
+ switch ( streamData->lin->iType ) {
+ case GC_EVENT_MESSAGE:
+ ied.iType = IEED_GC_EVENT_MESSAGE;
+ ied.dwData = IEEDD_GC_SHOW_NICK;
+ break;
+ case GC_EVENT_ACTION:
+ ied.iType = IEED_GC_EVENT_ACTION;
+ break;
+ case GC_EVENT_JOIN:
+ ied.iType = IEED_GC_EVENT_JOIN;
+ break;
+ case GC_EVENT_PART:
+ ied.iType = IEED_GC_EVENT_PART;
+ break;
+ case GC_EVENT_QUIT:
+ ied.iType = IEED_GC_EVENT_QUIT;
+ break;
+ case GC_EVENT_NICK:
+ ied.iType = IEED_GC_EVENT_NICK;
+ break;
+ case GC_EVENT_KICK:
+ ied.iType = IEED_GC_EVENT_KICK;
+ break;
+ case GC_EVENT_NOTICE:
+ ied.iType = IEED_GC_EVENT_NOTICE;
+ break;
+ case GC_EVENT_TOPIC:
+ ied.iType = IEED_GC_EVENT_TOPIC;
+ break;
+ case GC_EVENT_INFORMATION:
+ ied.iType = IEED_GC_EVENT_INFORMATION;
+ break;
+ case GC_EVENT_ADDSTATUS:
+ ied.iType = IEED_GC_EVENT_ADDSTATUS;
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ ied.iType = IEED_GC_EVENT_REMOVESTATUS;
+ break;
+ }
+ ied.dwData |= g_Settings.ShowTime ? IEEDD_GC_SHOW_TIME : 0;
+ ied.dwData |= IEEDD_GC_SHOW_ICON;
+#if defined( _UNICODE )
+ ied.dwFlags = IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK | IEEDF_UNICODE_TEXT2;
+#endif
+ ied.next = NULL;
+ CallService(streamData->dat->hwndIEView ? MS_IEVIEW_EVENT : MS_HPP_EG_EVENT, 0, (LPARAM)&event);
+ mir_free(buffer);
+}
+
+*/
+
+static int EventToIndex(LOGINFO * lin)
+{
+ switch (lin->iType) {
+ case GC_EVENT_MESSAGE:
+ if (lin->bIsMe)
+ return 10;
+ else
+ return 9;
+
+ case GC_EVENT_JOIN:
+ return 3;
+ case GC_EVENT_PART:
+ return 4;
+ case GC_EVENT_QUIT:
+ return 5;
+ case GC_EVENT_NICK:
+ return 7;
+ case GC_EVENT_KICK:
+ return 6;
+ case GC_EVENT_NOTICE:
+ return 8;
+ case GC_EVENT_TOPIC:
+ return 11;
+ case GC_EVENT_INFORMATION:
+ return 12;
+ case GC_EVENT_ADDSTATUS:
+ return 13;
+ case GC_EVENT_REMOVESTATUS:
+ return 14;
+ case GC_EVENT_ACTION:
+ return 15;
+ }
+ return 0;
+}
+
+static BYTE EventToSymbol(LOGINFO *lin)
+{
+ switch (lin->iType) {
+ case GC_EVENT_MESSAGE:
+ return (lin->bIsMe) ? 0x37 : 0x38;
+ case GC_EVENT_JOIN:
+ return 0x34;
+ case GC_EVENT_PART:
+ return 0x33;
+ case GC_EVENT_QUIT:
+ return 0x39;
+ case GC_EVENT_NICK:
+ return 0x71;
+ case GC_EVENT_KICK:
+ return 0x72;
+ case GC_EVENT_NOTICE:
+ return 0x28;
+ case GC_EVENT_INFORMATION:
+ return 0x69;
+ case GC_EVENT_ADDSTATUS:
+ return 0x35;
+ case GC_EVENT_REMOVESTATUS:
+ return 0x36;
+ case GC_EVENT_ACTION:
+ return 0x60;
+ }
+ return 0x73;
+}
+
+static int EventToIcon(LOGINFO * lin)
+{
+ switch (lin->iType) {
+ case GC_EVENT_MESSAGE:
+ if (lin->bIsMe)
+ return ICON_MESSAGEOUT;
+ else
+ return ICON_MESSAGE;
+
+ case GC_EVENT_JOIN:
+ return ICON_JOIN;
+ case GC_EVENT_PART:
+ return ICON_PART;
+ case GC_EVENT_QUIT:
+ return ICON_QUIT;
+ case GC_EVENT_NICK:
+ return ICON_NICK;
+ case GC_EVENT_KICK:
+ return ICON_KICK;
+ case GC_EVENT_NOTICE:
+ return ICON_NOTICE;
+ case GC_EVENT_TOPIC:
+ return ICON_TOPIC;
+ case GC_EVENT_INFORMATION:
+ return ICON_INFO;
+ case GC_EVENT_ADDSTATUS:
+ return ICON_ADDSTATUS;
+ case GC_EVENT_REMOVESTATUS:
+ return ICON_REMSTATUS;
+ case GC_EVENT_ACTION:
+ return ICON_ACTION;
+ }
+ return 0;
+}
+
+/* replace pattern `ptrn' with the string `rplc' in string `src' points to */
+static TCHAR * _tcsrplc(TCHAR **src, const TCHAR *ptrn, const TCHAR *rplc)
+{
+ size_t lSrc, lPtrn, lRplc;
+ TCHAR *tszFound, *tszTail;
+
+ lSrc = lstrlen(*src);
+ lPtrn = lstrlen(ptrn);
+ lRplc = lstrlen(rplc);
+ if (lPtrn && lSrc && lSrc >= lPtrn && (tszFound = _tcsstr(*src, ptrn)) != NULL) {
+ if (lRplc > lPtrn)
+ *src = (TCHAR *) realloc((void *) * src,
+ sizeof(TCHAR) * (lSrc + lRplc - lPtrn + 1));
+ if (tszTail = (TCHAR *) malloc(sizeof(TCHAR) *
+ (lSrc - (tszFound - *src) - lPtrn + 1))) {
+ /* save tail */
+ _tcscpy(tszTail, tszFound + lPtrn);
+ /* write replacement string */
+ _tcscpy(tszFound, rplc);
+ /* write tail */
+ _tcscpy(tszFound + lRplc, tszTail);
+ free((void *) tszTail);
+ }
+ }
+ return *src;
+}
+
+/*
+ * replace pattern `ptrn' with the string `rplc' in string `src',
+ * `src' is supposed to be `n' character long (or no checking is done if n < 0).
+ * This function is useful for statically allocated buffers
+ */
+static TCHAR * _tcsnrplc(TCHAR *src, size_t n, const TCHAR *ptrn, const TCHAR *rplc)
+{
+ size_t lSrc, lPtrn, lRplc;
+ TCHAR *tszFound, *tszTail;
+
+ lSrc = lstrlen(src);
+ lPtrn = lstrlen(ptrn);
+ lRplc = lstrlen(rplc);
+ if (lPtrn && lSrc && lSrc >= lPtrn && /* lengths are ok */
+ (tszFound = _tcsstr(src, ptrn)) != NULL && /* pattern was found in string */
+ (n < 0 || lSrc - lPtrn + lRplc < n) && /* there is enough room in the string */
+ (tszTail = (TCHAR *) malloc(sizeof(TCHAR) *
+ (lSrc - (tszFound - src) - lPtrn + 1))) != NULL) {
+ /* save tail */
+ _tcscpy(tszTail, tszFound + lPtrn);
+ /* write replacement string */
+ _tcscpy(tszFound, rplc);
+ /* write tail */
+ _tcscpy(tszFound + lRplc, tszTail);
+ free((void *) tszTail);
+ }
+ return src;
+}
+
+static char *Log_SetStyle(int style, int fontindex)
+{
+ if (style < OPTIONS_FONTCOUNT)
+ return CHAT_rtffonts + (style * RTFCACHELINESIZE);
+
+ return "";
+}
+
+static void Log_Append(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const char *fmt, ...)
+{
+ va_list va;
+ int charsDone = 0;
+
+ va_start(va, fmt);
+ for (;;) {
+ charsDone = mir_vsnprintf(*buffer + *cbBufferEnd, *cbBufferAlloced - *cbBufferEnd, fmt, va);
+ if (charsDone >= 0)
+ break;
+ *cbBufferAlloced += 4096;
+ *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced);
+ }
+ va_end(va);
+ *cbBufferEnd += charsDone;
+}
+
+static int Log_AppendRTF(LOGSTREAMDATA* streamData, BOOL simpleMode, char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const TCHAR *fmt, ...)
+{
+ va_list va;
+ int lineLen, textCharsCount = 0;
+ TCHAR* line = (TCHAR*)alloca(8001 * sizeof(TCHAR));
+ char* d;
+
+ va_start(va, fmt);
+ lineLen = _vsntprintf(line, 8000, fmt, va);
+ if (lineLen < 0) lineLen = 8000;
+ line[lineLen] = 0;
+ va_end(va);
+
+ lineLen = lineLen * 20 + 8;
+ if (*cbBufferEnd + lineLen > *cbBufferAlloced) {
+ cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024);
+ if ((d = (char *) mir_realloc(*buffer, *cbBufferAlloced)) == 0)
+ return 0;
+ *buffer = d;
+ }
+
+ d = *buffer + *cbBufferEnd;
+
+ for (; *line; line++, textCharsCount++) {
+ if (*line == '\r' && line[1] == '\n') {
+ CopyMemory(d, "\\par ", 5);
+ line++;
+ d += 5;
+ } else if (*line == '\n') {
+ CopyMemory(d, "\\line ", 6);
+ d += 6;
+ } else if (*line == '%' && !simpleMode) {
+ char szTemp[200];
+
+ szTemp[0] = '\0';
+ switch (*++line) {
+ case '\0':
+ case '%':
+ *d++ = '%';
+ break;
+
+ case 'c':
+ case 'f':
+ if (g_Settings.StripFormat || streamData->bStripFormat)
+ line += 2;
+
+ else if (line[1] != '\0' && line[2] != '\0') {
+ TCHAR szTemp3[3], c = *line;
+ int col;
+ szTemp3[0] = line[1];
+ szTemp3[1] = line[2];
+ szTemp3[2] = '\0';
+ line += 2;
+
+ col = _ttoi(szTemp3);
+ col += (OPTIONS_FONTCOUNT + 1);
+ mir_snprintf(szTemp, SIZEOF(szTemp), (c == 'c') ? "\\cf%u " : "\\highlight%u ", col);
+ }
+ break;
+ case 'C':
+ case 'F':
+ if (!g_Settings.StripFormat && !streamData->bStripFormat) {
+ int j = streamData->lin->bIsHighlighted ? 16 : EventToIndex(streamData->lin);
+ if (*line == 'C')
+ mir_snprintf(szTemp, SIZEOF(szTemp), "\\cf%u ", j + 1);
+ else
+ mir_snprintf(szTemp, SIZEOF(szTemp), "\\highlight0 ");
+ }
+ break;
+ case 'b':
+ case 'u':
+ case 'i':
+ if (!streamData->bStripFormat)
+ mir_snprintf(szTemp, SIZEOF(szTemp), (*line == 'u') ? "\\%cl " : "\\%c ", *line);
+ break;
+
+ case 'B':
+ case 'U':
+ case 'I':
+ if (!streamData->bStripFormat) {
+ mir_snprintf(szTemp, SIZEOF(szTemp), (*line == 'U') ? "\\%cl0 " : "\\%c0 ", *line);
+ CharLowerA(szTemp);
+ }
+ break;
+
+ case 'r':
+ if (!streamData->bStripFormat) {
+ int index = EventToIndex(streamData->lin);
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s ", Log_SetStyle(index, index));
+ }
+ break;
+ }
+
+ if (szTemp[0]) {
+ int iLen = lstrlenA(szTemp);
+ memcpy(d, szTemp, iLen);
+ d += iLen;
+ }
+ } else if (*line == '\t' && !streamData->bStripFormat) {
+ CopyMemory(d, "\\tab ", 5);
+ d += 5;
+ } else if ((*line == '\\' || *line == '{' || *line == '}') && !streamData->bStripFormat) {
+ *d++ = '\\';
+ *d++ = (char) * line;
+ } else if (*line > 0 && *line < 128) {
+ *d++ = (char) * line;
+ }
+ else d += sprintf(d, "\\u%u ?", (WORD) * line);
+ }
+
+ *cbBufferEnd = (int)(d - *buffer);
+ return textCharsCount;
+}
+
+static void AddEventToBuffer(char **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData)
+{
+ TCHAR szTemp[512], szTemp2[512];
+ TCHAR* pszNick = NULL;
+
+ if (streamData == NULL)
+ return;
+
+ if (streamData->lin == NULL)
+ return;
+
+ if (streamData->lin->ptszNick) {
+ if (g_Settings.LogLimitNames && lstrlen(streamData->lin->ptszNick) > 20) {
+ lstrcpyn(szTemp, streamData->lin->ptszNick, 20);
+ lstrcpyn(szTemp + 20, _T("..."), 4);
+ } else lstrcpyn(szTemp, streamData->lin->ptszNick, 511);
+
+ if (g_Settings.ClickableNicks)
+ mir_sntprintf(szTemp2, SIZEOF(szTemp2), _T("~~++#%s#++~~"), szTemp);
+ else
+ _tcscpy(szTemp2, szTemp);
+
+ if (streamData->lin->ptszUserInfo && streamData->lin->iType != GC_EVENT_TOPIC)
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, streamData->lin->ptszUserInfo);
+ else
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), szTemp2);
+ pszNick = szTemp;
+ }
+
+ switch (streamData->lin->iType) {
+ case GC_EVENT_MESSAGE:
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_ACTION:
+ if (streamData->lin->ptszNick && streamData->lin->ptszText) {
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, _T("%s "), streamData->lin->ptszNick);
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_JOIN:
+ if (pszNick) {
+ if (!streamData->lin->bIsMe)
+ /* replace nick of a newcomer with a link */
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, CTranslator::get(CTranslator::MUC_LOG_JOINED), pszNick);
+ else
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, CTranslator::get(CTranslator::MUC_LOG_ME_JOINED), streamData->si->ptszName);
+ }
+ break;
+ case GC_EVENT_PART:
+ if (pszNick)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, CTranslator::get(CTranslator::MUC_LOG_LEFT), pszNick);
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_QUIT:
+ if (pszNick)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, CTranslator::get(CTranslator::MUC_LOG_DISC), pszNick);
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_NICK:
+ if (pszNick && streamData->lin->ptszText) {
+ if (!streamData->lin->bIsMe)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, CTranslator::get(CTranslator::MUC_LOG_NICKCHANGE), pszNick, streamData->lin->ptszText);
+ else
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, CTranslator::get(CTranslator::MUC_LOG_ME_NICKCHANGE), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_KICK:
+ if (pszNick && streamData->lin->ptszStatus)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ CTranslator::get(CTranslator::MUC_LOG_KICK), streamData->lin->ptszStatus, pszNick);
+
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_NOTICE:
+ if (pszNick && streamData->lin->ptszText) {
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, CTranslator::get(CTranslator::MUC_LOG_NOTICE), pszNick);
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_TOPIC:
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, CTranslator::get(CTranslator::MUC_LOG_TOPICIS), streamData->lin->ptszText, _T("%r"));
+ if (pszNick)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ (streamData->lin->ptszUserInfo) ? CTranslator::get(CTranslator::MUC_LOG_TOPICSETBYON) :
+ CTranslator::get(CTranslator::MUC_LOG_TOPICSETBY),
+ pszNick, streamData->lin->ptszUserInfo);
+ break;
+ case GC_EVENT_INFORMATION:
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, (streamData->lin->bIsMe) ? _T("--> %s") : _T("%s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_ADDSTATUS:
+ if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ CTranslator::get(CTranslator::MUC_LOG_STATUSENABLE),
+ streamData->lin->ptszText, streamData->lin->ptszStatus, pszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) {
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ CTranslator::get(CTranslator::MUC_LOG_STATUSDISABLE),
+ streamData->lin->ptszText , streamData->lin->ptszStatus, pszNick);
+ }
+ break;
+ }
+}
+
+TCHAR* MakeTimeStamp(TCHAR* pszStamp, time_t time)
+{
+ static TCHAR szTime[30];
+ _tcsftime(szTime, 29, pszStamp, localtime(&time));
+ return szTime;
+}
+
+static char* Log_CreateRTF(LOGSTREAMDATA *streamData)
+{
+ char *buffer, *header;
+ int bufferAlloced, bufferEnd, i, me = 0;
+ LOGINFO * lin = streamData->lin;
+ MODULEINFO *mi = MM_FindModule(streamData->si->pszModule);
+
+ // guesstimate amount of memory for the RTF
+ bufferEnd = 0;
+ bufferAlloced = streamData->bRedraw ? 2048 * (streamData->si->iEventCount + 2) : 2048;
+ buffer = (char *) mir_alloc(bufferAlloced);
+ buffer[0] = '\0';
+
+ // ### RTF HEADER
+
+ if(0 == mi->pszHeader)
+ mi->pszHeader = Log_CreateRtfHeader(mi);
+
+ header = mi->pszHeader;
+ streamData->crCount = mi->nColorCount;
+
+ if (header)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, header);
+
+
+ // ### RTF BODY (one iteration per event that should be streamed in)
+ while (lin) {
+ // filter
+ if (streamData->si->iType != GCW_CHATROOM || !streamData->si->bFilterEnabled || (streamData->si->iLogFilterFlags&lin->iType) != 0) {
+ if (lin->next != NULL)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\par ");
+
+ if (streamData->dat->dwFlags & MWF_DIVIDERWANTED || lin->dwFlags & MWF_DIVIDERWANTED) {
+ static char szStyle_div[128] = "\0";
+ if (szStyle_div[0] == 0)
+ mir_snprintf(szStyle_div, 128, "\\f%u\\cf%u\\ul0\\b%d\\i%d\\fs%u", 17, 18, 0, 0, 5);
+
+ lin->dwFlags |= MWF_DIVIDERWANTED;
+ if (lin->prev || !streamData->bRedraw)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\qc\\sl-1\\highlight%d %s ---------------------------------------------------------------------------------------\\par ", 18, szStyle_div);
+ streamData->dat->dwFlags &= ~MWF_DIVIDERWANTED;
+ }
+ // create new line, and set font and color
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\ql\\sl0%s ", Log_SetStyle(0, 0));
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\v~-+%d+-~\\v0 ", lin);
+
+ // Insert icon
+ if (g_Settings.LogSymbols) // use symbols
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s %c", Log_SetStyle(17, 17), EventToSymbol(lin));
+ else if (g_Settings.dwIconFlags) {
+ int iIndex = lin->bIsHighlighted ? ICON_HIGHLIGHT : EventToIcon(lin);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\f0\\fs14");
+ while (bufferAlloced - bufferEnd < (logIconBmpSize[0] + 20))
+ bufferAlloced += 4096;
+ buffer = (char *) mir_realloc(buffer, bufferAlloced);
+ CopyMemory(buffer + bufferEnd, pLogIconBmpBits[iIndex], logIconBmpSize[iIndex]);
+ bufferEnd += logIconBmpSize[iIndex];
+ }
+
+ if (g_Settings.TimeStampEventColour) {
+ // colored timestamps
+ static char szStyle[256];
+ int iii;
+ if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) {
+ iii = lin->bIsHighlighted ? 16 : (lin->bIsMe ? 2 : 1);
+ mir_snprintf(szStyle, SIZEOF(szStyle), "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", iii + 1, aFonts[0].lf.lfWeight >= FW_BOLD ? 1 : 0,aFonts[0].lf.lfItalic,aFonts[0].lf.lfUnderline, 2 * abs(aFonts[0].lf.lfHeight) * 74 / logPixelSY);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", szStyle);
+ } else {
+ iii = lin->bIsHighlighted ? 16 : EventToIndex(lin);
+ mir_snprintf(szStyle, SIZEOF(szStyle), "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", iii + 1, aFonts[0].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[0].lf.lfItalic,aFonts[0].lf.lfUnderline ,2 * abs(aFonts[0].lf.lfHeight) * 74 / logPixelSY);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", szStyle);
+ }
+ } else
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(0, 0));
+ // insert a TAB if necessary to put the timestamp in the right position
+ if (g_Settings.dwIconFlags)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tab ");
+
+ //insert timestamp
+ if (g_Settings.ShowTime) {
+ TCHAR szTimeStamp[30], szOldTimeStamp[30];
+
+ lstrcpyn(szTimeStamp, MakeTimeStamp(g_Settings.pszTimeStamp, lin->time), 30);
+ lstrcpyn(szOldTimeStamp, MakeTimeStamp(g_Settings.pszTimeStamp, streamData->si->LastTime), 30);
+ if (!g_Settings.ShowTimeIfChanged || streamData->si->LastTime == 0 || lstrcmp(szTimeStamp, szOldTimeStamp)) {
+ streamData->si->LastTime = lin->time;
+ Log_AppendRTF(streamData, TRUE, &buffer, &bufferEnd, &bufferAlloced, _T("%s"), szTimeStamp);
+ }
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tab ");
+ }
+
+ // Insert the nick
+ if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) {
+ TCHAR pszTemp[300], *p1;
+ STATUSINFO *ti;
+ char pszIndicator[3] = "\0\0";
+ int crNickIndex = 0;
+ //mad
+ if (g_Settings.LogClassicIndicators/*g_Settings.ClassicIndicators */||g_Settings.ColorizeNicksInLog) {
+ USERINFO *ui = streamData->si->pUsers;
+ while (ui) {
+ if (!lstrcmp(ui->pszNick, lin->ptszNick)) {
+ ti = TM_FindStatus(streamData->si->pStatuses, TM_WordToString(streamData->si->pStatuses, ui->Status));
+ if (ti && (int)ti->hIcon < streamData->si->iStatusCount) {
+ int id = streamData->si->iStatusCount - (int)ti->hIcon - 1;
+ switch (id) {
+ case 1:
+ pszIndicator[0] = '+';
+ crNickIndex = 2;
+ break;
+ case 2:
+ pszIndicator[0] = '%';
+ crNickIndex = 1;
+ break;
+ case 3:
+ pszIndicator[0] = '@';
+ crNickIndex = 0;
+ break;
+ case 4:
+ pszIndicator[0] = '!';
+ crNickIndex = 3;
+ break;
+ case 5:
+ pszIndicator[0] = '*';
+ crNickIndex = 4;
+ break;
+ default:
+ pszIndicator[0] = 0;
+ }
+ }
+ break;
+ }
+ ui = ui->next;
+ }
+ }
+
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(lin->bIsMe ? 2 : 1, lin->bIsMe ? 2 : 1));
+ //MAD
+ if (g_Settings.LogClassicIndicators /*g_Settings.ClassicIndicators*/)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s", pszIndicator);
+
+ lstrcpyn(pszTemp, lin->bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick, 299);
+ p1 = _tcsstr(pszTemp, _T("%n"));
+ if (p1)
+ p1[1] = 's';
+
+ if (!lin->bIsMe) {
+ if (g_Settings.ClickableNicks) {
+ _tcsnrplc(pszTemp, 300, _T("%s"), _T("~~++#%s#++~~"));
+ pszTemp[299] = 0;
+ }
+ //Log_Append(&buffer, &bufferEnd, &bufferAlloced, "~~++#");
+ if (g_Settings.ColorizeNicksInLog && pszIndicator[0])
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\cf%u ", OPTIONS_FONTCOUNT + streamData->crCount + crNickIndex + 1);
+ }
+
+ Log_AppendRTF(streamData, TRUE, &buffer, &bufferEnd, &bufferAlloced, pszTemp, lin->ptszNick);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, " ");
+ }
+
+ // Insert the message
+ {
+ i = lin->bIsHighlighted ? 16 : EventToIndex(lin);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(i, i));
+ streamData->lin = lin;
+ AddEventToBuffer(&buffer, &bufferEnd, &bufferAlloced, streamData);
+ }
+ }
+ lin = lin->prev;
+ }
+
+ // ### RTF END
+ if (streamData->bRedraw)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\par}");
+ else
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}");
+ return buffer;
+}
+
+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 = Log_CreateRTF(lstrdat);
+ lstrdat->bufferLen = lstrlenA(lstrdat->buffer);
+ }
+
+ // give the RTF to the RE control
+ *pcb = min(cb, lstrdat->bufferLen - lstrdat->bufferOffset);
+ CopyMemory(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 bPhaseTwo)
+{
+ EDITSTREAM stream;
+ LOGSTREAMDATA streamData;
+ CHARRANGE oldsel, sel, newsel;
+ POINT point = {0};
+ SCROLLINFO scroll;
+ WPARAM wp;
+ HWND hwndRich;
+ TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ if (hwndDlg == 0 || lin == 0 || si == 0 || dat == 0)
+ return;
+
+ hwndRich = GetDlgItem(hwndDlg, IDC_CHAT_LOG);
+ ZeroMemory(&streamData, sizeof(LOGSTREAMDATA));
+ streamData.hwnd = hwndRich;
+ streamData.si = si;
+ streamData.lin = lin;
+ streamData.bStripFormat = FALSE;
+ streamData.dat = dat;
+
+ // bPhaseTwo = bRedraw && bPhaseTwo;
+
+ if (bRedraw || si->iType != GCW_CHATROOM || !si->bFilterEnabled || (si->iLogFilterFlags&lin->iType) != 0) {
+ BOOL bFlag = FALSE, fDoReplace;
+
+ ZeroMemory(&stream, sizeof(stream));
+ stream.pfnCallback = Log_StreamCallback;
+ stream.dwCookie = (DWORD_PTR) & streamData;
+ scroll.cbSize = sizeof(SCROLLINFO);
+ scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ GetScrollInfo(GetDlgItem(hwndDlg, IDC_CHAT_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;
+ hdc = GetDC(NULL);
+ logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
+ ReleaseDC(NULL, hdc);
+ SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0);
+ bFlag = TRUE;
+ // SetCursor(LoadCursor(NULL, IDC_ARROW));
+ }
+
+ // stream in the event(s)
+ streamData.lin = lin;
+ streamData.bRedraw = bRedraw;
+ SendMessage(hwndRich, EM_STREAMIN, wp, (LPARAM) & stream);
+
+
+ //SendMessage(hwndRich, EM_EXGETSEL, (WPARAM)0, (LPARAM)&newsel);
+ /*
+ * for new added events, only replace in message or action events.
+ * no need to replace smileys or math formulas elsewhere
+ */
+
+ fDoReplace = (bRedraw || (lin->ptszText
+ && (lin->iType == GC_EVENT_MESSAGE || lin->iType == GC_EVENT_ACTION)));
+
+
+ /*
+ * use mathmod to replace formulas
+ */
+ if (g_Settings.MathMod && fDoReplace) {
+ TMathRicheditInfo mathReplaceInfo;
+ CHARRANGE mathNewSel;
+ mathNewSel.cpMin = sel.cpMin;
+
+ if (mathNewSel.cpMin < 0)
+ mathNewSel.cpMin = 0;
+
+ mathNewSel.cpMax = -1;
+
+ mathReplaceInfo.hwndRichEditControl = hwndRich;
+
+ if (!bRedraw)
+ mathReplaceInfo.sel = &mathNewSel;
+ else
+ mathReplaceInfo.sel = 0;
+
+ mathReplaceInfo.disableredraw = TRUE;
+ CallService(MATH_RTF_REPLACE_FORMULAE, 0, (LPARAM)&mathReplaceInfo);
+ bFlag = TRUE;
+ }
+
+ /*
+ * replace marked nicknames with hyperlinks to make the nicks
+ * clickable
+ */
+
+ if (g_Settings.ClickableNicks) {
+ CHARFORMAT2 cf2;
+ FINDTEXTEX fi, fi2;
+
+ ZeroMemory(&cf2, sizeof(CHARFORMAT2));
+ fi2.lpstrText = _T("#++~~");
+ fi.chrg.cpMin = bRedraw ? 0 : sel.cpMin;
+ fi.chrg.cpMax = -1;
+ fi.lpstrText = _T("~~++#");
+ cf2.cbSize = sizeof(cf2);
+
+ while (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) > -1) {
+ fi2.chrg.cpMin = fi.chrgText.cpMin;
+ fi2.chrg.cpMax = -1;
+
+ if (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi2) > -1) {
+
+ SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi.chrgText);
+ SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)_T(""));
+ fi2.chrgText.cpMin -= fi.chrgText.cpMax - fi.chrgText.cpMin;
+ fi2.chrgText.cpMax -= fi.chrgText.cpMax - fi.chrgText.cpMin;
+ SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi2.chrgText);
+ SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)_T(""));
+ fi2.chrgText.cpMax = fi2.chrgText.cpMin;
+
+ fi2.chrgText.cpMin = fi.chrgText.cpMin;
+ SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi2.chrgText);
+ cf2.dwMask = CFM_PROTECTED;
+ cf2.dwEffects = CFE_PROTECTED;
+ SendMessage(hwndRich, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ }
+ fi.chrg.cpMin = fi.chrgText.cpMax;
+ }
+ SendMessage(hwndRich, EM_SETSEL, -1, -1);
+ }
+
+
+ /*
+ * run smileyadd
+ */
+ if (PluginConfig.g_SmileyAddAvail && fDoReplace) {
+ SMADD_RICHEDIT3 sm = {0};
+
+ newsel.cpMax = -1;
+ newsel.cpMin = sel.cpMin;
+ if (newsel.cpMin < 0)
+ newsel.cpMin = 0;
+ ZeroMemory(&sm, 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);
+ }
+
+ /*
+ * trim the message log to the number of most recent events
+ * this uses hidden marks in the rich text to find the events which should be deleted
+ */
+
+
+ if (si->wasTrimmed) {
+ TCHAR szPattern[50];
+ FINDTEXTEX fi;
+
+ mir_sntprintf(szPattern, SIZEOF(szPattern), _T("~-+%d+-~"), si->pLogEnd);
+ fi.lpstrText = szPattern;
+ fi.chrg.cpMin = 0;
+ fi.chrg.cpMax = -1;
+ if (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) != 0) {
+ CHARRANGE sel;
+ sel.cpMin = 0;
+ sel.cpMax = 20;
+ SendMessage(hwndRich, EM_SETSEL, 0, fi.chrgText.cpMax + 1);
+ SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)_T(""));
+ }
+ si->wasTrimmed = FALSE;
+ }
+
+ // 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);
+ }
+ }
+}
+
+char * Log_CreateRtfHeader(MODULEINFO * mi)
+{
+ char *buffer;
+ int bufferAlloced, bufferEnd, i = 0;
+
+ // guesstimate amount of memory for the RTF header
+ bufferEnd = 0;
+ bufferAlloced = 4096;
+ buffer = (char *) mir_realloc(mi->pszHeader, bufferAlloced);
+ buffer[0] = '\0';
+
+
+ //get the number of pixels per logical inch
+ if (logPixelSY == 0) {
+ HDC hdc;
+ hdc = GetDC(NULL);
+ logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
+ ReleaseDC(NULL, hdc);
+ }
+
+ // ### RTF HEADER
+
+ // font table
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl");
+ for (i = 0; i < OPTIONS_FONTCOUNT ; i++)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "{\\f%u\\fnil\\fcharset%u" TCHAR_STR_PARAM ";}", i, aFonts[i].lf.lfCharSet, aFonts[i].lf.lfFaceName);
+
+ // colour table
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl ;");
+
+ for (i = 0; i < OPTIONS_FONTCOUNT; i++)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(aFonts[i].color), GetGValue(aFonts[i].color), GetBValue(aFonts[i].color));
+
+ for (i = 0; i < mi->nColorCount; i++)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(mi->crColors[i]), GetGValue(mi->crColors[i]), GetBValue(mi->crColors[i]));
+
+ for (i = 0; i < 5; i++)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(g_Settings.nickColors[i]), GetGValue(g_Settings.nickColors[i]), GetBValue(g_Settings.nickColors[i]));
+
+ // new paragraph
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}\\pard\\sl%d", 1000);
+
+ // set tabs and indents
+ {
+ int iIndent = 0;
+
+ if (g_Settings.LogSymbols) {
+ TCHAR szString[2];
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ szString[1] = 0;
+ szString[0] = 0x28;
+ LoadMsgDlgFont(FONTSECTION_CHAT, 17, &lf, NULL, CHAT_FONTMODULE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(szString, hFont, TRUE) + 3;
+ DeleteObject(hFont);
+ iIndent += (iText * 1440) / logPixelSX;
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent);
+ } else if (g_Settings.dwIconFlags) {
+ iIndent += ((g_Settings.ScaleIcons ? 14 : 20) * 1440) / logPixelSX;
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent);
+ }
+ if (g_Settings.ShowTime) {
+ int iSize = (g_Settings.LogTextIndent * 1440) / logPixelSX;
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent + iSize);
+ if (g_Settings.LogIndentEnabled)
+ iIndent += iSize;
+ }
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\fi-%u\\li%u", iIndent, iIndent);
+ }
+ return buffer;
+}
+
+#define RTFPICTHEADERMAXSIZE 78
+void LoadMsgLogBitmaps(void)
+{
+ HICON hIcon;
+ HBITMAP hBmp, hoBmp;
+ HDC hdc, hdcMem;
+ BITMAPINFOHEADER bih = { 0 };
+ int widthBytes, i;
+ RECT rc;
+ HBRUSH hBkgBrush;
+ int rtfHeaderSize;
+ PBYTE pBmpBits;
+ int iIconSize;
+ int sizeX = 0, sizeY = 0;
+
+ if (hIcons[0])
+ Utils::getIconSize(hIcons[0], sizeX, sizeY);
+ else
+ sizeX = 16;
+
+ if (sizeX >= 12)
+ iIconSize = g_Settings.ScaleIcons ? 12 : 16;
+ else
+ iIconSize = sizeX;
+
+ hBkgBrush = CreateSolidBrush(M->GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR_MUC, SRMSGDEFSET_BKGCOLOUR));
+ bih.biSize = sizeof(bih);
+ bih.biBitCount = 24;
+ bih.biCompression = BI_RGB;
+ bih.biHeight = iIconSize;
+ bih.biPlanes = 1;
+ bih.biWidth = iIconSize;
+ widthBytes = ((bih.biWidth * bih.biBitCount + 31) >> 5) * 4;
+ rc.top = rc.left = 0;
+ rc.right = iIconSize;
+ rc.bottom = iIconSize;
+ hdc = GetDC(NULL);
+ hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
+ hdcMem = CreateCompatibleDC(hdc);
+ pBmpBits = (PBYTE) mir_alloc(widthBytes * bih.biHeight);
+ for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) {
+ hIcon = hIcons[i];
+ pLogIconBmpBits[i] = (PBYTE) mir_alloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2);
+ rtfHeaderSize = sprintf((char *)pLogIconBmpBits[i], "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, bih.biWidth, bih.biHeight);
+ hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp);
+ FillRect(hdcMem, &rc, hBkgBrush);
+ DrawIconEx(hdcMem, 0, 1, hIcon, iIconSize, iIconSize, 0, NULL, DI_NORMAL);
+
+ SelectObject(hdcMem, hoBmp);
+ GetDIBits(hdc, hBmp, 0, bih.biHeight, pBmpBits, (BITMAPINFO *) & bih, DIB_RGB_COLORS);
+ {
+ int n;
+ for (n = 0; n < sizeof(BITMAPINFOHEADER); n++)
+ sprintf((char *)pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]);
+ for (n = 0; n < widthBytes * bih.biHeight; n += 4)
+ sprintf((char *)pLogIconBmpBits[i] + rtfHeaderSize + (bih.biSize + n) * 2, "%02X%02X%02X%02X", pBmpBits[n], pBmpBits[n + 1], pBmpBits[n + 2], pBmpBits[n + 3]);
+ }
+ logIconBmpSize[i] = rtfHeaderSize + (bih.biSize + widthBytes * bih.biHeight) * 2 + 1;
+ pLogIconBmpBits[i][logIconBmpSize[i] - 1] = '}';
+ }
+ mir_free(pBmpBits);
+ DeleteDC(hdcMem);
+ DeleteObject(hBmp);
+ ReleaseDC(NULL, hdc);
+ DeleteObject(hBkgBrush);
+
+ /* cache RTF font headers */
+
+ //get the number of pixels per logical inch
+ if (logPixelSY == 0) {
+ HDC hdc;
+ hdc = GetDC(NULL);
+ logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
+ ReleaseDC(NULL, hdc);
+ }
+
+ for (i = 0; i < OPTIONS_FONTCOUNT; i++)
+ mir_snprintf(CHAT_rtfFontsGlobal[i], RTFCACHELINESIZE, "\\f%u\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", i, i + 1, aFonts[i].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[i].lf.lfItalic,aFonts[i].lf.lfUnderline ,2 * abs(aFonts[i].lf.lfHeight) * 74 / logPixelSY);
+ CHAT_rtffonts = &(CHAT_rtfFontsGlobal[0][0]);
+}
+
+void FreeMsgLogBitmaps(void)
+{
+ int i;
+ for (i = 0; i < SIZEOF(pLogIconBmpBits); i++)
+ mir_free(pLogIconBmpBits[i]);
+}
diff --git a/plugins/TabSRMM/chat/main.cpp b/plugins/TabSRMM/chat/main.cpp
new file mode 100644
index 0000000000..45b0717f29
--- /dev/null
+++ b/plugins/TabSRMM/chat/main.cpp
@@ -0,0 +1,142 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: main.cpp 13132 2010-11-17 03:47:44Z silvercircle $
+ *
+ * chat module exports and functions to load/unload the plugin.
+ *
+ */
+
+#include "../src/commonheaders.h"
+
+HANDLE g_hWindowList;
+HMENU g_hMenu = NULL;
+
+FONTINFO aFonts[OPTIONS_FONTCOUNT];
+HICON hIcons[30];
+HBRUSH hListBkgBrush = NULL;
+
+TMUCSettings g_Settings;
+
+TCHAR *pszActiveWndID = 0;
+char *pszActiveWndModule = 0;
+
+/*
+ * load the group chat module
+ */
+
+int Chat_Load(PLUGINLINK *link)
+{
+ if(M->GetByte("forceDisableMUC", 0)) {
+ PluginConfig.m_chat_enabled = false;
+ return(0);
+ }
+ g_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU));
+ if(CreateServiceFunctions()) {
+ HookEvents();
+ CreateHookableEvents();
+ OptionsInit();
+ }
+ return 0;
+}
+
+/*
+ * unload the module. final cleanup
+ */
+
+int Chat_Unload(void)
+{
+ if (!PluginConfig.m_chat_enabled)
+ return 0;
+
+ DBWriteContactSettingWord(NULL, "Chat", "SplitterX", (WORD)g_Settings.iSplitterX);
+ DBWriteContactSettingWord(NULL, "Chat", "splitY", (WORD)g_Settings.iSplitterY);
+
+ CList_SetAllOffline(TRUE, NULL);
+
+ mir_free(pszActiveWndID);
+ mir_free(pszActiveWndModule);
+
+ DestroyMenu(g_hMenu);
+ DestroyServiceFunctions();
+ DestroyHookableEvents();
+ FreeIcons();
+ OptionsUnInit();
+ UnhookEvents();
+ return 0;
+}
+
+void LoadLogIcons(void)
+{
+ ZeroMemory(hIcons, sizeof(HICON) * (ICON_STATUS5 - ICON_ACTION));
+ hIcons[ICON_ACTION] = LoadIconEx(IDI_ACTION, "log_action", 16, 16);
+ hIcons[ICON_ADDSTATUS] = LoadIconEx(IDI_ADDSTATUS, "log_addstatus", 16, 16);
+ hIcons[ICON_HIGHLIGHT] = LoadIconEx(IDI_HIGHLIGHT, "log_highlight", 16, 16);
+ hIcons[ICON_INFO] = LoadIconEx(IDI_INFO, "log_info", 16, 16);
+ hIcons[ICON_JOIN] = LoadIconEx(IDI_JOIN, "log_join", 16, 16);
+ hIcons[ICON_KICK] = LoadIconEx(IDI_KICK, "log_kick", 16, 16);
+ hIcons[ICON_MESSAGE] = LoadIconEx(IDI_MESSAGE, "log_message_in", 16, 16);
+ hIcons[ICON_MESSAGEOUT] = LoadIconEx(IDI_MESSAGEOUT, "log_message_out", 16, 16);
+ hIcons[ICON_NICK] = LoadIconEx(IDI_NICK, "log_nick", 16, 16);
+ hIcons[ICON_NOTICE] = LoadIconEx(IDI_NOTICE, "log_notice", 16, 16);
+ hIcons[ICON_PART] = LoadIconEx(IDI_PART, "log_part", 16, 16);
+ hIcons[ICON_QUIT] = LoadIconEx(IDI_QUIT, "log_quit", 16, 16);
+ hIcons[ICON_REMSTATUS] = LoadIconEx(IDI_REMSTATUS, "log_removestatus", 16, 16);
+ hIcons[ICON_TOPIC] = LoadIconEx(IDI_TOPIC, "log_topic", 16, 16);
+ hIcons[ICON_STATUS1] = LoadIconEx(IDI_STATUS1, "status1", 16, 16);
+ hIcons[ICON_STATUS2] = LoadIconEx(IDI_STATUS2, "status2", 16, 16);
+ hIcons[ICON_STATUS3] = LoadIconEx(IDI_STATUS3, "status3", 16, 16);
+ hIcons[ICON_STATUS4] = LoadIconEx(IDI_STATUS4, "status4", 16, 16);
+ hIcons[ICON_STATUS0] = LoadIconEx(IDI_STATUS0, "status0", 16, 16);
+ hIcons[ICON_STATUS5] = LoadIconEx(IDI_STATUS5, "status5", 16, 16);
+
+ return;
+}
+
+void LoadIcons(void)
+{
+ int i;
+
+ for (i = 0; i < 20; i++)
+ hIcons[i] = NULL;
+
+ LoadLogIcons();
+ g_Settings.hIconOverlay = LoadIconEx(IDI_OVERLAY, "overlay", 16, 16);
+ LoadMsgLogBitmaps();
+ return ;
+}
+
+void FreeIcons(void)
+{
+ FreeMsgLogBitmaps();
+ return;
+}
diff --git a/plugins/TabSRMM/chat/manager.cpp b/plugins/TabSRMM/chat/manager.cpp
new file mode 100644
index 0000000000..8a1e404ea5
--- /dev/null
+++ b/plugins/TabSRMM/chat/manager.cpp
@@ -0,0 +1,1541 @@
+/*
+astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ --pad=oper --one-line=keep-blocks --unpad=paren
+
+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.
+
+$Id: manager.cpp 14208 2012-03-26 13:56:42Z silvercircle $
+*/
+
+#include "../src/commonheaders.h"
+
+extern TCHAR *pszActiveWndID ;
+extern char *pszActiveWndModule ;
+extern HICON hIcons[30];
+
+#define WINDOWS_COMMANDS_MAX 30
+#define STATUSICONCOUNT 6
+
+SESSION_INFO *m_WndList = 0;
+MODULEINFO *m_ModList = 0;
+
+extern CRITICAL_SECTION cs;
+
+void SetActiveSession(const TCHAR* pszID, const char* pszModule)
+{
+ SESSION_INFO* si = SM_FindSession(pszID, pszModule);
+ if (si)
+ SetActiveSessionEx(si);
+}
+
+void SetActiveSessionEx(SESSION_INFO* si)
+{
+ if (si) {
+ replaceStr(&pszActiveWndID, si->ptszID);
+ replaceStrA(&pszActiveWndModule, si->pszModule);
+ }
+}
+
+SESSION_INFO* GetActiveSession(void)
+{
+ SESSION_INFO* si = SM_FindSession(pszActiveWndID, pszActiveWndModule);
+ if (si)
+ return si;
+
+ return m_WndList;
+}
+
+//---------------------------------------------------
+// Session Manager functions
+//
+// Keeps track of all sessions and its windows
+//---------------------------------------------------
+
+SESSION_INFO* SM_AddSession(const TCHAR* pszID, const char* pszModule)
+{
+ if (!pszID || !pszModule)
+ return NULL;
+
+ if (!SM_FindSession(pszID, pszModule)) {
+ SESSION_INFO*node = (SESSION_INFO*) mir_alloc(sizeof(SESSION_INFO));
+ ZeroMemory(node, sizeof(SESSION_INFO));
+ node->ptszID = mir_tstrdup(pszID);
+ node->pszModule = mir_strdup(pszModule);
+
+ MODULEINFO *mi = MM_FindModule(pszModule);
+
+ if(mi) {
+ mi->idleTimeStamp = time(0);
+ SM_BroadcastMessage(pszModule, GC_UPDATESTATUSBAR, 0, 1, TRUE);
+ }
+
+ if (m_WndList == NULL) { // list is empty
+ m_WndList = node;
+ node->next = NULL;
+ } else {
+ node->next = m_WndList;
+ m_WndList = node;
+ }
+ node->Highlight = g_Settings.Highlight;
+ return node;
+ }
+ return NULL;
+}
+
+int SM_RemoveSession(const TCHAR* pszID, const char* pszModule)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID && pTemp->iType != GCW_SERVER || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) { // match
+ COMMAND_INFO *pCurComm;
+ DWORD dw = pTemp->dwItemData;
+
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_EVENT_CONTROL + WM_USER + 500, SESSION_TERMINATE, 0);
+
+ DoEventHook(pTemp->ptszID, pTemp->pszModule, GC_SESSION_TERMINATE, NULL, NULL, (DWORD)pTemp->dwItemData);
+
+ if (pLast == NULL)
+ m_WndList = pTemp->next;
+ else
+ pLast->next = pTemp->next;
+
+ UM_RemoveAll(&pTemp->pUsers);
+ TM_RemoveAll(&pTemp->pStatuses);
+ LM_RemoveAll(&pTemp->pLog, &pTemp->pLogEnd);
+ pTemp->iStatusCount = 0;
+ pTemp->nUsersInNicklist = 0;
+
+ if (pTemp->hContact) {
+ CList_SetOffline(pTemp->hContact, pTemp->iType == GCW_CHATROOM ? TRUE : FALSE);
+ //if (pTemp->iType != GCW_SERVER)
+ //DBWriteContactSettingByte(pTemp->hContact, "CList", "Hidden", 1);
+ }
+ DBWriteContactSettingString(pTemp->hContact, pTemp->pszModule , "Topic", "");
+ DBWriteContactSettingString(pTemp->hContact, pTemp->pszModule, "StatusBar", "");
+ DBDeleteContactSetting(pTemp->hContact, "CList", "StatusMsg");
+
+ mir_free(pTemp->pszModule);
+ mir_free(pTemp->ptszID);
+ mir_free(pTemp->ptszName);
+ mir_free(pTemp->ptszStatusbarText);
+ mir_free(pTemp->ptszTopic);
+ mir_free(pTemp->pszID);
+ mir_free(pTemp->pszName);
+
+ // delete commands
+ pCurComm = pTemp->lpCommands;
+ while (pCurComm != NULL) {
+ COMMAND_INFO *pNext = pCurComm->next;
+ mir_free(pCurComm->lpCommand);
+ mir_free(pCurComm);
+ pCurComm = pNext;
+ }
+
+ mir_free(pTemp);
+ if (pszID)
+ return (int)dw;
+ if (pLast)
+ pTemp = pLast->next;
+ else
+ pTemp = m_WndList;
+ } else {
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ }
+ return FALSE;
+}
+
+SESSION_INFO* SM_FindSession(const TCHAR* pszID, const char* pszModule)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule))
+ return pTemp;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return NULL;
+}
+
+BOOL SM_SetOffline(const TCHAR* pszID, const char* pszModule)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ UM_RemoveAll(&pTemp->pUsers);
+ pTemp->nUsersInNicklist = 0;
+ if (pTemp->iType != GCW_SERVER)
+ pTemp->bInitDone = FALSE;
+
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_SetStatusEx(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText, int flags)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ UM_SetStatusEx(pTemp->pUsers, pszText, flags);
+ if (pTemp->hWnd)
+ RedrawWindow(GetDlgItem(pTemp->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE);
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+HICON SM_GetStatusIcon(SESSION_INFO* si, USERINFO* ui, char *szIndicator)
+{
+ STATUSINFO * ti;
+ if (!ui || !si)
+ return NULL;
+
+ *szIndicator = 0;
+
+ ti = TM_FindStatus(si->pStatuses, TM_WordToString(si->pStatuses, ui->Status));
+ if (ti) {
+ if ((INT_PTR)ti->hIcon < STATUSICONCOUNT) {
+ int id = si->iStatusCount - (int)ti->hIcon - 1;
+ if (id == 0) {
+ *szIndicator = 0;
+ return hIcons[ICON_STATUS0];
+ }
+ if (id == 1) {
+ *szIndicator = '+';
+ return hIcons[ICON_STATUS1];
+ }
+ if (id == 2) {
+ *szIndicator = '%';
+ return hIcons[ICON_STATUS2];
+ }
+ if (id == 3) {
+ *szIndicator = '@';
+ return hIcons[ICON_STATUS3];
+ }
+ if (id == 4) {
+ *szIndicator = '!';
+ return hIcons[ICON_STATUS4];
+ }
+ if (id == 5) {
+ *szIndicator = '*';
+ return hIcons[ICON_STATUS5];
+ }
+ } else
+ return ti->hIcon;
+ }
+ return hIcons[ICON_STATUS0];
+}
+
+BOOL SM_AddEventToAllMatchingUID(GCEVENT * gce, BOOL bIsHighLight)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+ int bManyFix = 0;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpiA(pTemp->pszModule, gce->pDest->pszModule)) {
+ if (UM_FindUser(pTemp->pUsers, gce->ptszUID)) {
+ if (pTemp->bInitDone) {
+ if (SM_AddEvent(pTemp->ptszID, pTemp->pszModule, gce, FALSE) && pTemp->hWnd && pTemp->bInitDone) {
+ SendMessage(pTemp->hWnd, GC_ADDLOG, 0, 0);
+ } else if (pTemp->hWnd && pTemp->bInitDone) {
+ SendMessage(pTemp->hWnd, GC_REDRAWLOG2, 0, 0);
+ }
+ DoSoundsFlashPopupTrayStuff(pTemp, gce, bIsHighLight, bManyFix);
+ bManyFix ++;
+ if ((gce->dwFlags & GCEF_ADDTOLOG) && g_Settings.LoggingEnabled)
+ LogToFile(pTemp, gce);
+ }
+ }
+ }
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return 0;
+}
+
+BOOL SM_AddEvent(const TCHAR* pszID, const char* pszModule, GCEVENT * gce, BOOL bIsHighlighted)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return TRUE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ LOGINFO * li = LM_AddEvent(&pTemp->pLog, &pTemp->pLogEnd);
+ pTemp->iEventCount += 1;
+
+ li->iType = gce->pDest->iType;
+ li->ptszNick = mir_tstrdup(gce->ptszNick);
+ li->ptszText = mir_tstrdup(gce->ptszText);
+ li->ptszStatus = mir_tstrdup(gce->ptszStatus);
+ li->ptszUserInfo = mir_tstrdup(gce->ptszUserInfo);
+
+ li->bIsMe = gce->bIsMe;
+ li->time = gce->time;
+ li->bIsHighlighted = bIsHighlighted;
+
+ if (g_Settings.iEventLimit > 0 && pTemp->iEventCount > g_Settings.iEventLimit + g_Settings.iEventLimitThreshold) {
+ LM_TrimLog(&pTemp->pLog, &pTemp->pLogEnd, pTemp->iEventCount - g_Settings.iEventLimit);
+ pTemp->wasTrimmed = TRUE;
+ pTemp->iEventCount = g_Settings.iEventLimit;
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+USERINFO * SM_AddUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO * p = UM_AddUser(pTemp->pStatuses, &pTemp->pUsers, pszUID, pszNick, wStatus);
+ pTemp->nUsersInNicklist++;
+ return p;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return 0;
+}
+
+BOOL SM_MoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID)
+{
+ SESSION_INFO* pTemp = m_WndList;
+
+ if (!pszID || !pszModule || !pszUID)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ UM_SortUser(&pTemp->pUsers, pszUID);
+ return TRUE;
+ }
+ pTemp = pTemp->next;
+ }
+
+ return FALSE;
+}
+
+BOOL SM_RemoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule || !pszUID)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ DWORD dw;
+ USERINFO * ui = UM_FindUser(pTemp->pUsers, pszUID);
+ if (ui) {
+ pTemp->nUsersInNicklist--;
+
+ dw = UM_RemoveUser(&pTemp->pUsers, pszUID);
+
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+
+ if (pszID)
+ return TRUE;
+ }
+ }
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return 0;
+}
+
+USERINFO * SM_GetUserFromIndex(const TCHAR* pszID, const char* pszModule, int index)
+{
+ SESSION_INFO* pTemp = m_WndList;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule))
+ return UM_FindUserFromIndex(pTemp->pUsers, index);
+ pTemp = pTemp->next;
+ }
+
+ return NULL;
+}
+
+
+STATUSINFO * SM_AddStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ STATUSINFO* ti = TM_AddStatus(&pTemp->pStatuses, pszStatus, &pTemp->iStatusCount);
+ if (ti)
+ pTemp->iStatusCount++;
+ return ti;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return 0;
+}
+
+BOOL SM_GiveStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO * ui = UM_GiveStatus(pTemp->pUsers, pszUID, TM_StringToWord(pTemp->pStatuses, pszStatus));
+ if (ui) {
+ SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID);
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return FALSE;
+}
+
+BOOL SM_SetContactStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, WORD wStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO * ui = UM_SetContactStatus(pTemp->pUsers, pszUID, wStatus);
+ if (ui) {
+ SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID);
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return FALSE;
+}
+
+BOOL SM_TakeStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO* ui = UM_TakeStatus(pTemp->pUsers, pszUID, TM_StringToWord(pTemp->pStatuses, pszStatus));
+ if (ui) {
+ SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID);
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return FALSE;
+}
+LRESULT SM_SendMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ while (pTemp && pszModule) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ if (pTemp->hWnd) {
+ LRESULT i = SendMessage(pTemp->hWnd, msg, wParam, lParam);
+ if (pszID)
+ return i;
+ }
+ if (pszID)
+ return 0;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+BOOL SM_PostMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return 0;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ if (pTemp->hWnd)
+ return PostMessage(pTemp->hWnd, msg, wParam, lParam);
+
+ return FALSE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return FALSE;
+}
+
+BOOL SM_BroadcastMessage(const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAsync)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ while (pTemp != NULL) {
+ if (!pszModule || !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ if (pTemp->hWnd) {
+ if (bAsync)
+ PostMessage(pTemp->hWnd, msg, wParam, lParam);
+ else
+ SendMessage(pTemp->hWnd, msg, wParam, lParam);
+ }
+
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_ReconfigureFilters()
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ while (pTemp != NULL) {
+ Chat_SetFilters(pTemp);
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_InvalidateLogDirectories()
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ EnterCriticalSection(&cs);
+
+ while (pTemp != NULL) {
+ pTemp->pszLogFileName[0] = 0;
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ LeaveCriticalSection(&cs);
+ return TRUE;
+}
+
+BOOL SM_SetStatus(const TCHAR* pszID, const char* pszModule, int wStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ pTemp->wStatus = wStatus;
+
+ if (pTemp->hContact) {
+ if (pTemp->iType != GCW_SERVER && wStatus != ID_STATUS_OFFLINE)
+ DBDeleteContactSetting(pTemp->hContact, "CList", "Hidden");
+
+ DBWriteContactSettingWord(pTemp->hContact, pTemp->pszModule, "Status", (WORD)wStatus);
+ }
+
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_SendUserMessage(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule || !pszText)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ if (pTemp->iType == GCW_CHATROOM)
+ DoEventHook(pTemp->ptszID, pTemp->pszModule, GC_USER_MESSAGE, NULL, pszText, (LPARAM)NULL);
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_ChangeUID(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNewUID)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO* ui = UM_FindUser(pTemp->pUsers, pszUID);
+ if (ui)
+ replaceStr(&ui->pszUID, pszNewUID);
+
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_ChangeNick(const TCHAR* pszID, const char* pszModule, GCEVENT * gce)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO* ui = UM_FindUser(pTemp->pUsers, gce->ptszUID);
+ if (ui) {
+ replaceStr(&ui->pszNick, gce->ptszText);
+ SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID);
+ if (pTemp->hWnd) {
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, 0, 0);
+ if(pTemp->dat)
+ GetMyNick(pTemp->dat);
+ SendMessage(pTemp->hWnd, GC_UPDATESTATUSBAR, 0, 0);
+ }
+ }
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+BOOL SM_RemoveAll(void)
+{
+ while (m_WndList) {
+ SESSION_INFO*pLast = m_WndList->next;
+
+ if (m_WndList->hWnd)
+ SendMessage(m_WndList->hWnd, GC_EVENT_CONTROL + WM_USER + 500, SESSION_TERMINATE, 0);
+ DoEventHook(m_WndList->ptszID, m_WndList->pszModule, GC_SESSION_TERMINATE, NULL, NULL, (DWORD)m_WndList->dwItemData);
+ if (m_WndList->hContact)
+ CList_SetOffline(m_WndList->hContact, m_WndList->iType == GCW_CHATROOM ? TRUE : FALSE);
+ DBWriteContactSettingString(m_WndList->hContact, m_WndList->pszModule , "Topic", "");
+ DBDeleteContactSetting(m_WndList->hContact, "CList", "StatusMsg");
+ DBWriteContactSettingString(m_WndList->hContact, m_WndList->pszModule, "StatusBar", "");
+
+ UM_RemoveAll(&m_WndList->pUsers);
+ TM_RemoveAll(&m_WndList->pStatuses);
+ LM_RemoveAll(&m_WndList->pLog, &m_WndList->pLogEnd);
+ m_WndList->iStatusCount = 0;
+ m_WndList->nUsersInNicklist = 0;
+
+ mir_free(m_WndList->pszModule);
+ mir_free(m_WndList->ptszID);
+ mir_free(m_WndList->ptszName);
+ mir_free(m_WndList->ptszStatusbarText);
+ mir_free(m_WndList->ptszTopic);
+
+ while (m_WndList->lpCommands != NULL) {
+ COMMAND_INFO *pNext = m_WndList->lpCommands->next;
+ mir_free(m_WndList->lpCommands->lpCommand);
+ mir_free(m_WndList->lpCommands);
+ m_WndList->lpCommands = pNext;
+ }
+
+ mir_free(m_WndList);
+ m_WndList = pLast;
+ }
+ m_WndList = NULL;
+ return TRUE;
+}
+
+void SM_AddCommand(const TCHAR* pszID, const char* pszModule, const char* lpNewCommand)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->ptszID, pszID) == 0 && lstrcmpiA(pTemp->pszModule, pszModule) == 0) { // match
+ COMMAND_INFO *node = (COMMAND_INFO *)mir_alloc(sizeof(COMMAND_INFO));
+ node->lpCommand = mir_strdup(lpNewCommand);
+ node->last = NULL; // always added at beginning!
+ // new commands are added at start
+ if (pTemp->lpCommands == NULL) {
+ node->next = NULL;
+ pTemp->lpCommands = node;
+ } else {
+ node->next = pTemp->lpCommands;
+ pTemp->lpCommands->last = node; // hmm, weird
+ pTemp->lpCommands = node;
+ }
+ pTemp->lpCurrentCommand = NULL; // current command
+ pTemp->wCommandsNum++;
+
+ if (pTemp->wCommandsNum > WINDOWS_COMMANDS_MAX) {
+ COMMAND_INFO *pCurComm = pTemp->lpCommands;
+ COMMAND_INFO *pLast;
+ while (pCurComm->next != NULL) {
+ pCurComm = pCurComm->next;
+ }
+ pLast = pCurComm->last;
+ mir_free(pCurComm->lpCommand);
+ mir_free(pCurComm);
+ pLast->next = NULL;
+ // done
+ pTemp->wCommandsNum--;
+ }
+ }
+ pTemp = pTemp->next;
+ }
+}
+
+char* SM_GetPrevCommand(const TCHAR* pszID, const char* pszModule) // get previous command. returns NULL if previous command does not exist. current command remains as it was.
+{
+ SESSION_INFO* pTemp = m_WndList;
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->ptszID, pszID) == 0 && lstrcmpiA(pTemp->pszModule, pszModule) == 0) { // match
+ COMMAND_INFO *pPrevCmd = NULL;
+ if (pTemp->lpCurrentCommand != NULL) {
+ if (pTemp->lpCurrentCommand->next != NULL) // not NULL
+ pPrevCmd = pTemp->lpCurrentCommand->next; // next command (newest at beginning)
+ else
+ pPrevCmd = pTemp->lpCurrentCommand;
+ } else pPrevCmd = pTemp->lpCommands;
+
+ pTemp->lpCurrentCommand = pPrevCmd; // make it the new command
+ return(((pPrevCmd) ? (pPrevCmd->lpCommand) : (NULL)));
+ }
+ pTemp = pTemp->next;
+ }
+ return(NULL);
+}
+
+char* SM_GetNextCommand(const TCHAR* pszID, const char* pszModule) // get next command. returns NULL if next command does not exist. current command becomes NULL (a prev command after this one will get you the last command)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->ptszID, pszID) == 0 && lstrcmpiA(pTemp->pszModule, pszModule) == 0) { // match
+ COMMAND_INFO *pNextCmd = NULL;
+ if (pTemp->lpCurrentCommand != NULL)
+ pNextCmd = pTemp->lpCurrentCommand->last; // last command (newest at beginning)
+
+ pTemp->lpCurrentCommand = pNextCmd; // make it the new command
+ return(((pNextCmd) ? (pNextCmd->lpCommand) : (NULL)));
+ }
+ pTemp = pTemp->next;
+ }
+ return(NULL);
+}
+
+int SM_GetCount(const char* pszModule)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ int count = 0;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpiA(pszModule, pTemp->pszModule))
+ count++;
+
+ pTemp = pTemp->next;
+ }
+ return count;
+}
+
+SESSION_INFO* SM_FindSessionByHWND(HWND hWnd)
+{
+ SESSION_INFO *pTemp = m_WndList;
+
+ while (pTemp) {
+ if (pTemp->hWnd == hWnd)
+ return pTemp;
+ pTemp = pTemp->next;
+ }
+ return NULL;
+}
+
+SESSION_INFO * SM_FindSessionByHCONTACT(HANDLE h)
+{
+ SESSION_INFO *pTemp = m_WndList;
+
+ while (pTemp) {
+ if (pTemp->hContact == h)
+ return pTemp;
+ pTemp = pTemp->next;
+ }
+ return NULL;
+}
+
+SESSION_INFO* SM_FindSessionByIndex(const char* pszModule, int iItem)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ int count = 0;
+ while (pTemp != NULL) {
+ if (!lstrcmpiA(pszModule, pTemp->pszModule)) {
+ if (iItem == count)
+ return pTemp;
+ else
+ count++;
+ }
+
+ pTemp = pTemp->next;
+ }
+ return NULL;
+
+}
+
+SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const TCHAR* pszOriginal, const TCHAR* pszCurrent)
+{
+ SESSION_INFO* pResult = NULL;
+ if (prevSession == NULL && my_strstri(currSession->ptszName, pszOriginal) == currSession->ptszName) {
+ pResult = currSession;
+ } else {
+ TCHAR* pszName = NULL;
+ SESSION_INFO* pTemp = m_WndList;
+ if (currSession == prevSession) {
+ pszCurrent = pszOriginal;
+ }
+ while (pTemp != NULL) {
+ if (pTemp != currSession && !lstrcmpiA(pszModule, pTemp->pszModule)) {
+ if (my_strstri(pTemp->ptszName, pszOriginal) == pTemp->ptszName) {
+ if (prevSession != pTemp && lstrcmpi(pTemp->ptszName, pszCurrent) > 0 && (!pszName || lstrcmpi(pTemp->ptszName, pszName) < 0)) {
+ pResult = pTemp;
+ pszName = pTemp->ptszName;
+ }
+ }
+ }
+ pTemp = pTemp->next;
+ }
+ }
+ return pResult;
+
+}
+
+char* SM_GetUsers(SESSION_INFO* si)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ USERINFO* utemp;
+ int count = 0;
+ char* p = NULL;
+ int alloced = 0;
+
+ if (si == NULL)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (si == pTemp) {
+ if ((utemp = pTemp->pUsers) == NULL)
+ return NULL;
+
+ break;
+ }
+ pTemp = pTemp->next;
+ }
+
+ do {
+ int pLen = lstrlenA(p), nameLen = lstrlen(utemp->pszUID);
+ if (pLen + nameLen + 2 > alloced)
+ p = (char *)mir_realloc(p, alloced += 4096);
+ WideCharToMultiByte(CP_ACP, 0, utemp->pszUID, -1, p + pLen, nameLen + 1, 0, 0);
+ lstrcpyA(p + pLen + nameLen, " ");
+ utemp = utemp->next;
+ } while (utemp != NULL);
+ return p;
+}
+
+
+
+
+
+
+//---------------------------------------------------
+// Module Manager functions
+//
+// Necessary to keep track of all modules
+// that has registered with the plugin
+//---------------------------------------------------
+
+MODULEINFO* MM_AddModule(const char* pszModule)
+{
+ if (!pszModule)
+ return NULL;
+ if (!MM_FindModule(pszModule)) {
+ MODULEINFO *node = (MODULEINFO*) mir_alloc(sizeof(MODULEINFO));
+ ZeroMemory(node, sizeof(MODULEINFO));
+
+ node->pszModule = (char*)mir_alloc(lstrlenA(pszModule) + 1);
+ lstrcpyA(node->pszModule, pszModule);
+ node->idleTimeStamp = time(0);
+ if (m_ModList == NULL) { // list is empty
+ m_ModList = node;
+ node->next = NULL;
+ } else {
+ node->next = m_ModList;
+ m_ModList = node;
+ }
+ return node;
+ }
+ return FALSE;
+}
+
+/*
+void MM_IconsChanged(void)
+{
+ MODULEINFO *pTemp = m_ModList, *pLast = NULL;
+ while (pTemp != NULL) {
+ if (pTemp->hOfflineIcon)
+ DestroyIcon(pTemp->hOfflineIcon);
+ if (pTemp->hOnlineIcon)
+ DestroyIcon(pTemp->hOnlineIcon);
+ if (pTemp->hOnlineTalkIcon)
+ DestroyIcon(pTemp->hOnlineTalkIcon);
+ if (pTemp->hOfflineTalkIcon)
+ DestroyIcon(pTemp->hOfflineTalkIcon);
+
+ pTemp->hOfflineIcon = ImageList_GetIcon(hIconsList, pTemp->OfflineIconIndex, ILD_TRANSPARENT);
+ pTemp->hOnlineIcon = ImageList_GetIcon(hIconsList, pTemp->OnlineIconIndex, ILD_TRANSPARENT);
+
+ pTemp->hOnlineTalkIcon = ImageList_GetIcon(hIconsList, pTemp->OnlineIconIndex, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1));
+ ImageList_ReplaceIcon(hIconsList, pTemp->OnlineIconIndex+1, pTemp->hOnlineTalkIcon);
+
+ pTemp->hOfflineTalkIcon = ImageList_GetIcon(hIconsList, pTemp->OfflineIconIndex, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1));
+ ImageList_ReplaceIcon(hIconsList, pTemp->OfflineIconIndex+1, pTemp->hOfflineTalkIcon);
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return;
+}
+*/
+
+void MM_FontsChanged(void)
+{
+ MODULEINFO *pTemp = m_ModList;
+ while (pTemp != NULL) {
+ pTemp->pszHeader = Log_CreateRtfHeader(pTemp);
+ pTemp = pTemp->next;
+ }
+ return;
+}
+MODULEINFO* MM_FindModule(const char* pszModule)
+{
+ MODULEINFO *pTemp = m_ModList, *pLast = NULL;
+
+ if (!pszModule)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (lstrcmpiA(pTemp->pszModule, pszModule) == 0)
+ return pTemp;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+// stupid thing..
+void MM_FixColors()
+{
+ MODULEINFO *pTemp = m_ModList;
+
+ while (pTemp != NULL) {
+ CheckColorsInModule(pTemp->pszModule);
+ pTemp = pTemp->next;
+ }
+ return;
+}
+
+BOOL MM_RemoveAll(void)
+{
+ while (m_ModList != NULL) {
+ MODULEINFO *pLast = m_ModList->next;
+ mir_free(m_ModList->pszModule);
+ mir_free(m_ModList->ptszModDispName);
+ if(m_ModList->pszHeader)
+ mir_free(m_ModList->pszHeader);
+ mir_free(m_ModList->crColors);
+
+ mir_free(m_ModList);
+ m_ModList = pLast;
+ }
+ m_ModList = NULL;
+ return TRUE;
+}
+
+//---------------------------------------------------
+// Status manager functions
+//
+// Necessary to keep track of what user statuses
+// per window nicklist that is available
+//---------------------------------------------------
+
+STATUSINFO * TM_AddStatus(STATUSINFO** ppStatusList, const TCHAR* pszStatus, int* iCount)
+{
+ if (!ppStatusList || !pszStatus)
+ return NULL;
+
+ if (!TM_FindStatus(*ppStatusList, pszStatus)) {
+ STATUSINFO *node = (STATUSINFO*) mir_alloc(sizeof(STATUSINFO));
+ ZeroMemory(node, sizeof(STATUSINFO));
+ replaceStr(&node->pszGroup, pszStatus);
+ node->hIcon = (HICON)(*iCount);
+ while ((int)node->hIcon > STATUSICONCOUNT - 1)
+ node->hIcon--;
+
+ if (*ppStatusList == NULL) { // list is empty
+ node->Status = 1;
+ *ppStatusList = node;
+ node->next = NULL;
+ } else {
+ node->Status = ppStatusList[0]->Status * 2;
+ node->next = *ppStatusList;
+ *ppStatusList = node;
+ }
+ return node;
+
+ }
+ return FALSE;
+}
+
+STATUSINFO * TM_FindStatus(STATUSINFO* pStatusList, const TCHAR* pszStatus)
+{
+ STATUSINFO *pTemp = pStatusList, *pLast = NULL;
+
+ if (!pStatusList || !pszStatus)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->pszGroup, pszStatus) == 0)
+ return pTemp;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+WORD TM_StringToWord(STATUSINFO* pStatusList, const TCHAR* pszStatus)
+{
+ STATUSINFO *pTemp = pStatusList, *pLast = NULL;
+
+ if (!pStatusList || !pszStatus)
+ return 0;
+
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->pszGroup, pszStatus) == 0)
+ return pTemp->Status;
+
+ if (pTemp->next == NULL)
+ return pStatusList->Status;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+TCHAR* TM_WordToString(STATUSINFO* pStatusList, WORD Status)
+{
+ STATUSINFO *pTemp = pStatusList, *pLast = NULL;
+
+ if (!pStatusList)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (pTemp->Status&Status) {
+ Status -= pTemp->Status;
+ if (Status == 0)
+ return pTemp->pszGroup;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+BOOL TM_RemoveAll(STATUSINFO** ppStatusList)
+{
+
+ if (!ppStatusList)
+ return FALSE;
+
+ while (*ppStatusList != NULL) {
+ STATUSINFO *pLast = ppStatusList[0]->next;
+ mir_free(ppStatusList[0]->pszGroup);
+ if ((int)ppStatusList[0]->hIcon > 10)
+ DestroyIcon(ppStatusList[0]->hIcon);
+ mir_free(*ppStatusList);
+ *ppStatusList = pLast;
+ }
+ *ppStatusList = NULL;
+ return TRUE;
+}
+
+//---------------------------------------------------
+// User manager functions
+//
+// Necessary to keep track of the users
+// in a window nicklist
+//---------------------------------------------------
+
+//MAD: alternative sorting by Nullbie
+static int sttCompareNicknames(const TCHAR *s1, const TCHAR *s2)
+{
+ // skip rubbish
+ while (*s1 && !_istalpha(*s1)) ++s1;
+ while (*s2 && !_istalpha(*s2)) ++s2;
+
+ // are there ~0veRy^kEwL_n1kz?
+ if (!*s1 && !*s2) return 0;
+ if (!*s1 && *s2) return +1;
+ if (*s1 && !*s2) return -1;
+
+ // compare tails
+ return lstrcmpi(s1, s2);
+}
+//
+
+static int UM_CompareItem(USERINFO * u1, const TCHAR* pszNick, WORD wStatus)
+{
+ int i;
+
+ WORD dw1 = u1->Status;
+ WORD dw2 = wStatus;
+
+ for (i = 0; i < 8; i++) {
+ if ((dw1 & 1) && !(dw2 & 1))
+ return -1;
+ if ((dw2 & 1) && !(dw1 & 1))
+ return 1;
+ if ((dw1 & 1) && (dw2 & 1))
+ //
+ {
+ if (g_Settings.AlternativeSorting)
+ return sttCompareNicknames(u1->pszNick, pszNick);
+ else
+ return lstrcmp(u1->pszNick, pszNick);
+ }//
+ dw1 = dw1 >> 1;
+ dw2 = dw2 >> 1;
+ }
+ if (g_Settings.AlternativeSorting)
+ //
+ return sttCompareNicknames(u1->pszNick, pszNick);
+ else
+ return lstrcmp(u1->pszNick, pszNick);
+ //
+}
+
+USERINFO * UM_SortUser(USERINFO** ppUserList, const TCHAR* pszUID)
+{
+ USERINFO * pTemp = *ppUserList, *pLast = NULL;
+ USERINFO * node = NULL;
+
+ if (!pTemp || !pszUID)
+ return NULL;
+
+ while (pTemp && lstrcmpi(pTemp->pszUID, pszUID)) {
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ if (pTemp) {
+ node = pTemp;
+ if (pLast)
+ pLast->next = pTemp->next;
+ else
+ *ppUserList = pTemp->next;
+ pTemp = *ppUserList;
+
+ pLast = NULL;
+
+ while (pTemp && UM_CompareItem(pTemp, node->pszNick, node->Status) <= 0) {
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ if (*ppUserList == NULL) { // list is empty
+ *ppUserList = node;
+ node->next = NULL;
+ } else {
+ if (pLast) {
+ node->next = pTemp;
+ pLast->next = node;
+ } else {
+ node->next = *ppUserList;
+ *ppUserList = node;
+ }
+ }
+
+ return node;
+ }
+ return NULL;
+}
+
+USERINFO* UM_AddUser(STATUSINFO* pStatusList, USERINFO** ppUserList, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus)
+{
+ USERINFO * pTemp = *ppUserList, *pLast = NULL;
+
+ if (!pStatusList || !ppUserList || !ppUserList)
+ return NULL;
+
+ while (pTemp && UM_CompareItem(pTemp, pszNick, wStatus) <= 0) {
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ // if (!UM_FindUser(*ppUserList, pszUI, wStatus)
+ {
+ USERINFO *node = (USERINFO*) mir_alloc(sizeof(USERINFO));
+ ZeroMemory(node, sizeof(USERINFO));
+ replaceStr(&node->pszUID, pszUID);
+
+ if (*ppUserList == NULL) { // list is empty
+ *ppUserList = node;
+ node->next = NULL;
+ } else {
+ if (pLast) {
+ node->next = pTemp;
+ pLast->next = node;
+ } else {
+ node->next = *ppUserList;
+ *ppUserList = node;
+ }
+ }
+
+ return node;
+ }
+ return NULL;
+}
+
+USERINFO* UM_FindUser(USERINFO* pUserList, const TCHAR* pszUID)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+
+ if (!pUserList || !pszUID)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID))
+ return pTemp;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+USERINFO* UM_FindUserFromIndex(USERINFO* pUserList, int index)
+{
+ int i = 0;
+ USERINFO *pTemp = pUserList;
+
+ if (!pUserList)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (i == index) {
+ return pTemp;
+ }
+ pTemp = pTemp->next;
+ i++;
+ }
+ return NULL;
+}
+
+USERINFO* UM_GiveStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+
+ if (!pUserList || !pszUID)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID)) {
+ pTemp->Status |= status;
+ return pTemp;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+USERINFO* UM_SetContactStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+
+ if (!pUserList || !pszUID)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID)) {
+ pTemp->ContactStatus = status;
+ return pTemp;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+BOOL UM_SetStatusEx(USERINFO* pUserList, const TCHAR* pszText, int flags)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+ int bOnlyMe = (flags & GC_SSE_ONLYLISTED) != 0, bSetStatus = (flags & GC_SSE_ONLINE) != 0;
+ char cDelimiter = (flags & GC_SSE_TABDELIMITED) ? '\t' : ' ';
+
+ while (pTemp != NULL) {
+ if (!bOnlyMe)
+ pTemp->iStatusEx = 0;
+
+ if (pszText != NULL) {
+ TCHAR* s = (TCHAR *)_tcsstr(pszText, pTemp->pszUID);
+ if (s) {
+ pTemp->iStatusEx = 0;
+ if (s == pszText || s[-1] == cDelimiter) {
+ int len = lstrlen(pTemp->pszUID);
+ if (s[len] == cDelimiter || s[len] == '\0')
+ pTemp->iStatusEx = (!bOnlyMe || bSetStatus) ? 1 : 0;
+ }
+ }
+ }
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+USERINFO* UM_TakeStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+
+ if (!pUserList || !pszUID)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID)) {
+ pTemp->Status &= ~status;
+ return pTemp;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+TCHAR* UM_FindUserAutoComplete(USERINFO* pUserList, const TCHAR* pszOriginal, const TCHAR* pszCurrent)
+{
+ TCHAR* pszName = NULL;
+ USERINFO *pTemp = pUserList;
+
+ if (!pUserList || !pszOriginal || !pszCurrent)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (my_strstri(pTemp->pszNick, pszOriginal) == pTemp->pszNick)
+ if (lstrcmpi(pTemp->pszNick, pszCurrent) > 0 && (!pszName || lstrcmpi(pTemp->pszNick, pszName) < 0))
+ pszName = pTemp->pszNick;
+
+ pTemp = pTemp->next;
+ }
+ return pszName;
+}
+
+BOOL UM_RemoveUser(USERINFO** ppUserList, const TCHAR* pszUID)
+{
+ USERINFO *pTemp = *ppUserList, *pLast = NULL;
+
+ if (!ppUserList || !pszUID)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID)) {
+ if (pLast == NULL)
+ *ppUserList = pTemp->next;
+ else
+ pLast->next = pTemp->next;
+ mir_free(pTemp->pszNick);
+ mir_free(pTemp->pszUID);
+ mir_free(pTemp);
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return FALSE;
+}
+
+BOOL UM_RemoveAll(USERINFO** ppUserList)
+{
+ if (!ppUserList)
+ return FALSE;
+
+ while (*ppUserList != NULL) {
+ USERINFO *pLast = ppUserList[0]->next;
+ mir_free(ppUserList[0]->pszUID);
+ mir_free(ppUserList[0]->pszNick);
+ mir_free(*ppUserList);
+ *ppUserList = pLast;
+ }
+ *ppUserList = NULL;
+ return TRUE;
+}
+
+//---------------------------------------------------
+// Log manager functions
+//
+// Necessary to keep track of events
+// in a window log
+//---------------------------------------------------
+
+LOGINFO * LM_AddEvent(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd)
+{
+
+ LOGINFO *node = NULL;
+
+ if (!ppLogListStart || !ppLogListEnd)
+ return NULL;
+
+ node = (LOGINFO*) mir_alloc(sizeof(LOGINFO));
+ ZeroMemory(node, sizeof(LOGINFO));
+
+
+ if (*ppLogListStart == NULL) { // list is empty
+ *ppLogListStart = node;
+ *ppLogListEnd = node;
+ node->next = NULL;
+ node->prev = NULL;
+ } else {
+ ppLogListStart[0]->prev = node;
+ node->next = *ppLogListStart;
+ *ppLogListStart = node;
+ ppLogListStart[0]->prev = NULL;
+ }
+
+ return node;
+}
+
+BOOL LM_TrimLog(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd, int iCount)
+{
+ LOGINFO *pTemp = *ppLogListEnd;
+ while (pTemp != NULL && iCount > 0) {
+ *ppLogListEnd = pTemp->prev;
+ if (*ppLogListEnd == NULL)
+ *ppLogListStart = NULL;
+
+ mir_free(pTemp->ptszNick);
+ mir_free(pTemp->ptszUserInfo);
+ mir_free(pTemp->ptszText);
+ mir_free(pTemp->ptszStatus);
+ mir_free(pTemp);
+ pTemp = *ppLogListEnd;
+ iCount--;
+ }
+ ppLogListEnd[0]->next = NULL;
+
+ return TRUE;
+}
+
+BOOL LM_RemoveAll(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd)
+{
+ while (*ppLogListStart != NULL) {
+ LOGINFO *pLast = ppLogListStart[0]->next;
+ mir_free(ppLogListStart[0]->ptszText);
+ mir_free(ppLogListStart[0]->ptszNick);
+ mir_free(ppLogListStart[0]->ptszStatus);
+ mir_free(ppLogListStart[0]->ptszUserInfo);
+ mir_free(*ppLogListStart);
+ *ppLogListStart = pLast;
+ }
+ *ppLogListStart = NULL;
+ *ppLogListEnd = NULL;
+ return TRUE;
+}
diff --git a/plugins/TabSRMM/chat/message.cpp b/plugins/TabSRMM/chat/message.cpp
new file mode 100644
index 0000000000..0a7f56b594
--- /dev/null
+++ b/plugins/TabSRMM/chat/message.cpp
@@ -0,0 +1,341 @@
+/*
+astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ --pad=oper --one-line=keep-blocks --unpad=paren
+
+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.
+
+$Id: message.c 10402 2009-07-24 00:35:21Z silvercircle $
+*/
+
+#include "../src/commonheaders.h"
+#include <math.h>
+
+static int RTFColorToIndex(int *pIndex, int iCol, SESSION_INFO* si)
+{
+ int i;
+ MODULEINFO * pMod = MM_FindModule(si->pszModule);
+
+ for (i = 0; i < pMod->nColorCount ; i++)
+ if (pIndex[i] == iCol)
+ return i;
+
+ return -1;
+}
+
+static void CreateColorMap(char* Text, int *pIndex, SESSION_INFO* si)
+{
+ char *p1, *p2, *pEnd;
+ int iIndex = 1;
+
+ static const char* lpszFmt = "\\red%[^ \x5b\\]\\green%[^ \x5b\\]\\blue%[^ \x5b;];";
+ char szRed[10], szGreen[10], szBlue[10];
+
+ p1 = strstr(Text, "\\colortbl");
+ if (!p1)
+ return;
+
+ pEnd = strchr(p1, '}');
+ p2 = strstr(p1, "\\red");
+
+ while (p2 && p2 < pEnd) {
+ if (sscanf(p2, lpszFmt, &szRed, &szGreen, &szBlue) > 0) {
+ int i;
+ MODULEINFO * pMod = MM_FindModule(si->pszModule);
+ for (i = 0; i < pMod->nColorCount ; i ++)
+ if (pMod->crColors[i] == RGB(atoi(szRed), atoi(szGreen), atoi(szBlue)))
+ pIndex[i] = iIndex;
+ }
+ iIndex++;
+ p1 = p2;
+ p1 ++;
+ p2 = strstr(p1, "\\red");
+ }
+}
+
+static int ReadInteger(const char* p, int* result)
+{
+ char temp[10];
+ int i = 0;
+ while (isdigit(*p) && i < 9)
+ temp[i++] = *p++;
+ temp[i] = 0;
+
+ if (result != NULL)
+ *result = atoi(temp);
+
+ return i;
+}
+
+TCHAR* Chat_DoRtfToTags(char* pszText, SESSION_INFO* si)
+{
+ char *p1;
+ int* pIndex;
+ int i, iRemoveChars, cp = CP_ACP;
+ char InsertThis[50];
+ BOOL bJustRemovedRTF = TRUE;
+ BOOL bTextHasStarted = FALSE;
+ TCHAR *ptszResult; //, *d;
+ int iUcMode = 0;
+
+ if (!pszText)
+ return FALSE;
+
+ // create an index of colors in the module and map them to
+ // corresponding colors in the RTF color table
+ pIndex = (int *)mir_alloc(sizeof(int) * MM_FindModule(si->pszModule)->nColorCount);
+ for (i = 0; i < MM_FindModule(si->pszModule)->nColorCount ; i++)
+ pIndex[i] = -1;
+
+ CreateColorMap(pszText, pIndex, si);
+
+ // scan the file for rtf commands and remove or parse them
+ p1 = strstr(pszText, "\\pard");
+ if (p1 == NULL) {
+ mir_free(pIndex);
+ return FALSE;
+ }
+
+ p1 += 5;
+
+ MoveMemory(pszText, p1, lstrlenA(p1) + 1);
+ p1 = pszText;
+
+ // iterate through all characters, if rtf control character found then take action
+ while (*p1 != '\0') {
+ InsertThis[0] = 0;
+ iRemoveChars = 0;
+
+ switch (*p1) {
+ case '\\':
+ if (!memcmp(p1, "\\cf", 3)) { // foreground color
+ int iCol, iInd;
+ iRemoveChars = 3 + ReadInteger(p1 + 3, &iCol);
+ iInd = RTFColorToIndex(pIndex, iCol, si);
+ bJustRemovedRTF = TRUE;
+
+ if (bTextHasStarted || iInd >= 0)
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), (iInd >= 0) ? "%%c%02u" : "%%C", iInd);
+ } else if (!memcmp(p1, "\\highlight", 10)) { //background color
+ int iCol, iInd;
+ iRemoveChars = 10 + ReadInteger(p1 + 10, &iCol);
+ iInd = RTFColorToIndex(pIndex, iCol, si);
+ bJustRemovedRTF = TRUE;
+
+ if (bTextHasStarted || iInd >= 0)
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), (iInd >= 0) ? "%%f%02u" : "%%F", iInd);
+ } else if (!memcmp(p1, "\\lang", 5)) { // language id
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 5 + ReadInteger(p1 + 5, NULL);
+ } else if (!memcmp(p1, "\\par", 4)) { // newline
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 4;
+ strcpy(InsertThis, "\n");
+ } else if (!memcmp(p1, "\\endash", 7)) {
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\x93");
+ } else if (!memcmp(p1, "\\emdash", 7)) {
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\x94");
+ } else if (!memcmp(p1, "\\bullet", 7)) {
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\xA2");
+ } else if (!memcmp(p1, "\\line", 5)) { // newline
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 5;
+ strcpy(InsertThis, "\n");
+ } else if (!memcmp(p1, "\\b", 2)) { //bold
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = (p1[2] != '0') ? 2 : 3;
+ strcpy(InsertThis, (p1[2] != '0') ? "%b" : "%B");
+ } else if (!memcmp(p1, "\\i", 2)) { // italics
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = (p1[2] != '0') ? 2 : 3;
+ strcpy(InsertThis, (p1[2] != '0') ? "%i" : "%I");
+ } else if (!memcmp(p1, "\\uc", 3)) { // number of Unicode chars
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iUcMode = p1[3] - '0';
+ iRemoveChars = 4;
+ } else if (!memcmp(p1, "\\ul", 3)) { // underlined
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ if (p1[3] == 'n')
+ iRemoveChars = 7;
+ else if (p1[3] == '0')
+ iRemoveChars = 4;
+ else
+ iRemoveChars = 3;
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), (p1[3] != '0' && p1[3] != 'n') ? "%%u" : "%%U");
+ } else if (p1[1] == 'f' && isdigit(p1[2])) { // unicode char
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 2 + ReadInteger(p1 + 2, NULL);
+ } else if (p1[1] == '\\' || p1[1] == '{' || p1[1] == '}') { // escaped characters
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ iRemoveChars = 2;
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), "%c", p1[1]);
+ } else if (p1[1] == '~') { // non-breaking space
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ iRemoveChars = 2;
+ strcpy(InsertThis, "\xC2\xA0");
+ }
+
+
+ else if (!memcmp(p1, "\\tab",4)) { // tab
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 4;
+ strcpy(InsertThis, "\x09");
+ }
+ else if (!memcmp(p1, "\\ldblquote",10)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 10;
+ strcpy(InsertThis, "\xe2\x80\x9c");
+ }
+ else if (!memcmp(p1, "\\rdblquote",10)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 10;
+ strcpy(InsertThis, "\xe2\x80\x9d");
+ }
+ else if (!memcmp(p1, "\\lquote",7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\x98");
+ }
+ else if (!memcmp(p1, "\\rquote",7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\x99");
+ }
+
+ else if (p1[1] == '\'') { // special character
+ char tmp[4], *p3 = tmp;
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ if (p1[2] != ' ' && p1[2] != '\\') {
+ *p3++ = p1[2];
+ iRemoveChars = 3;
+ if (p1[3] != ' ' && p1[3] != '\\') {
+ *p3++ = p1[3];
+ iRemoveChars++;
+ }
+ *p3 = 0;
+ sscanf(tmp, "%x", InsertThis);
+
+ InsertThis[1] = 0;
+ } else iRemoveChars = 2;
+ } else if (bJustRemovedRTF) { // remove unknown RTF command
+ int j = 1;
+ bJustRemovedRTF = TRUE;
+ while (p1[j] != ' ' && p1[j] != '\\' && p1[j] != '\0')
+ j++;
+ iRemoveChars = j;
+ }
+ break;
+
+ case '{': // other RTF control characters
+ case '}':
+ iRemoveChars = 1;
+ break;
+
+ case '\r': case '\n':
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ iRemoveChars = 1;
+ break;
+
+ case '%': // escape chat -> protocol control character
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ iRemoveChars = 1;
+ strcpy(InsertThis, "%%");
+ break;
+ case ' ': // remove spaces following a RTF command
+ if (bJustRemovedRTF)
+ iRemoveChars = 1;
+ bJustRemovedRTF = FALSE;
+ bTextHasStarted = TRUE;
+ break;
+
+ default: // other text that should not be touched
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ break;
+ }
+
+ // move the memory and paste in new commands instead of the old RTF
+ if (InsertThis[0] || iRemoveChars) {
+ MoveMemory(p1 + lstrlenA(InsertThis) , p1 + iRemoveChars, lstrlenA(p1) - iRemoveChars + 1);
+ CopyMemory(p1, InsertThis, lstrlenA(InsertThis));
+ p1 += lstrlenA(InsertThis);
+ } else p1++;
+ }
+
+ mir_free(pIndex);
+ ptszResult = M->utf8_decodeW(pszText);
+ return ptszResult;
+}
+
+static DWORD CALLBACK Chat_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* Chat_Message_GetFromStream(HWND hwndDlg, SESSION_INFO* si)
+{
+ EDITSTREAM stream;
+ char* pszText = NULL;
+ DWORD dwFlags;
+
+ if (hwndDlg == 0 || si == 0)
+ return NULL;
+
+ ZeroMemory(&stream, sizeof(stream));
+ stream.pfnCallback = Chat_Message_StreamCallback;
+ stream.dwCookie = (DWORD_PTR) & pszText; // pass pointer to pointer
+
+ dwFlags = SF_RTFNOOBJS | SFF_PLAINRTF | SF_USECODEPAGE | (CP_UTF8 << 16);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_STREAMOUT, dwFlags, (LPARAM) & stream);
+ return pszText; // pszText contains the text
+}
diff --git a/plugins/TabSRMM/chat/muchighlight.cpp b/plugins/TabSRMM/chat/muchighlight.cpp
new file mode 100644
index 0000000000..d790cc1d2b
--- /dev/null
+++ b/plugins/TabSRMM/chat/muchighlight.cpp
@@ -0,0 +1,427 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: muchighlight.cpp 13184 2010-12-07 14:16:58Z silvercircle $
+ *
+ * highlighter class for multi user chats
+ *
+ */
+
+#include "../src/commonheaders.h"
+
+//#define __HLT_PERFSTATS 0
+
+void CMUCHighlight::cleanup()
+{
+ if(m_NickPatternString)
+ mir_free(m_NickPatternString);
+ if(m_TextPatternString)
+ mir_free(m_TextPatternString);
+
+ m_TextPatternString = m_NickPatternString = 0;
+
+ if(m_NickPatterns)
+ mir_free(m_NickPatterns);
+ if(m_TextPatterns)
+ mir_free(m_TextPatterns);
+
+ m_iNickPatterns = m_iTextPatterns = 0;
+ m_NickPatterns = m_TextPatterns = 0;
+}
+
+void CMUCHighlight::init()
+{
+ DBVARIANT dbv = {0};
+
+ if(m_fInitialized)
+ cleanup(); // clean up first, if we were already initialized
+
+ m_fInitialized = true;
+
+ if(0 == M->GetTString(0, "Chat", "HighlightWords", &dbv)) {
+ m_TextPatternString = dbv.ptszVal;
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(m_TextPatternString);
+ }
+
+ if(0 == M->GetTString(0, "Chat", "HighlightNames", &dbv))
+ m_NickPatternString = dbv.ptszVal;
+
+ m_dwFlags = M->GetByte("Chat", "HighlightEnabled", MATCH_TEXT);
+ m_fHighlightMe = (M->GetByte("Chat", "HighlightMe", 1) ? true : false);
+
+ __try {
+ tokenize(m_TextPatternString, m_TextPatterns, m_iTextPatterns);
+ tokenize(m_NickPatternString, m_NickPatterns, m_iNickPatterns);
+ }
+ __except(CGlobals::Ex_ShowDialog(GetExceptionInformation(), __FILE__, __LINE__, L"MUC_HLT_TOKENIZER", false)) {
+ m_Valid = false;
+ }
+}
+
+void CMUCHighlight::tokenize(TCHAR *tszString, TCHAR**& patterns, UINT& nr)
+{
+ if(tszString == 0)
+ return;
+
+ TCHAR *p = tszString;
+
+ if(*p == 0)
+ return;
+
+ nr = 0;
+
+ if(*p != ' ')
+ nr++;
+
+ while(*p) {
+ if(*p == ' ') {
+ p++;
+ while(*p && _istspace(*p))
+ p++;
+ if(*p)
+ nr++;
+ }
+ p++;
+ }
+ patterns = (TCHAR **)mir_alloc(nr * sizeof(TCHAR *));
+
+ p = tszString;
+ nr = 0;
+
+ if(*p != ' ')
+ patterns[nr++] = p;
+
+ while(*p) {
+ if(*p == ' ') {
+ *p++ = 0;
+ while(*p && _istspace(*p))
+ p++;
+ if(*p)
+ patterns[nr++] = p;
+ }
+ p++;
+ }
+}
+
+int CMUCHighlight::match(const GCEVENT *pgce, const SESSION_INFO *psi, DWORD dwFlags)
+{
+ int result = 0, nResult = 0;
+
+ if(pgce == 0 || m_Valid == false)
+ return(0);
+
+ __try {
+ if((m_dwFlags & MATCH_TEXT) && (dwFlags & MATCH_TEXT) && (m_fHighlightMe || m_iTextPatterns > 0) && psi != 0) {
+ #ifdef __HLT_PERFSTATS
+ int words = 0;
+ M->startTimer();
+ #endif
+ TCHAR *tszCleaned = ::RemoveFormatting(pgce->ptszText, true, true);
+ TCHAR *p = tszCleaned;
+ TCHAR *p1;
+ UINT i = 0;
+
+ TCHAR *tszMe = ((psi && psi->pMe) ? mir_tstrdup(psi->pMe->pszNick) : 0);
+ if(tszMe) {
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(tszMe);
+ }
+
+ if(m_fHighlightMe && tszMe) {
+ result = wcsstr(p, tszMe) ? MATCH_TEXT : 0;
+ if(0 == m_iTextPatterns)
+ goto skip_textpatterns;
+ }
+ while(p && !result) {
+ while(*p && (*p == ' ' || *p == ',' || *p == '.' || *p == ':' || *p == ';' || *p == '?' || *p == '!'))
+ p++;
+
+ if(*p) {
+ p1 = p;
+ while(*p1 && *p1 != ' ' && *p1 != ',' && *p1 != '.' && *p1 != ':' && *p1 != ';' && *p1 != '?' && *p1 != '!')
+ p1++;
+
+ if(*p1)
+ *p1 = 0;
+ else
+ p1 = 0;
+
+ for(i = 0; i < m_iTextPatterns && !result; i++)
+ result = wildmatch(m_TextPatterns[i], p) ? MATCH_TEXT : 0;
+
+ if(p1) {
+ *p1 = ' ';
+ p = p1 + 1;
+ }
+ else
+ p = 0;
+ #ifdef __HLT_PERFSTATS
+ words++;
+ #endif
+ }
+ else
+ break;
+ }
+skip_textpatterns:
+
+ #ifdef __HLT_PERFSTATS
+ M->stopTimer(0);
+ if(psi && psi->dat) {
+ mir_sntprintf(psi->dat->szStatusBar, 100, _T("PERF text match: %d ticks = %f msec (%d words, %d patterns)"), (int)M->getTicks(), M->getMsec(), words, m_iTextPatterns);
+ if(psi->dat->pContainer->hwndStatus)
+ ::SendMessage(psi->dat->pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)psi->dat->szStatusBar);
+ }
+ #endif
+ if(tszMe)
+ mir_free(tszMe);
+ }
+
+ /*
+ * optinally, match the nickname against the list of nicks to highlight
+ */
+ if((m_dwFlags & MATCH_NICKNAME) && (dwFlags & MATCH_NICKNAME) && pgce->ptszNick && m_iNickPatterns > 0) {
+ for(UINT i = 0; i < m_iNickPatterns && !nResult; i++) {
+ if(pgce->ptszNick)
+ nResult = wildmatch(m_NickPatterns[i], pgce->ptszNick) ? MATCH_NICKNAME : 0;
+ if((m_dwFlags & MATCH_UIN) && pgce->ptszUserInfo)
+ nResult = wildmatch(m_NickPatterns[i], pgce->ptszUserInfo) ? MATCH_NICKNAME : 0;
+ }
+ }
+
+ return(result | nResult);
+ }
+ __except(CGlobals::Ex_ShowDialog(GetExceptionInformation(), __FILE__, __LINE__, L"MUC_HIGHLIGHT_EXCEPTION", false)) {
+ m_Valid = false;
+ return(0);
+ }
+ return(0);
+}
+
+int CMUCHighlight::wildmatch(const TCHAR *pattern, const TCHAR *tszString) {
+
+ const TCHAR *cp = 0, *mp = 0;
+
+ while ((*tszString) && (*pattern != '*')) {
+ if ((*pattern != *tszString) && (*pattern != '?')) {
+ return 0;
+ }
+ pattern++;
+ tszString++;
+ }
+
+ while (*tszString) {
+ if (*pattern == '*') {
+ if (!*++pattern)
+ return 1;
+ mp = pattern;
+ cp = tszString + 1;
+ }
+ else if ((*pattern == *tszString) || (*pattern == '?')) {
+ pattern++;
+ tszString++;
+ }
+ else {
+ pattern = mp;
+ tszString = cp++;
+ }
+ }
+
+ while (*pattern == '*')
+ pattern++;
+
+ return(!*pattern);
+}
+
+/**
+ * Dialog procedure to handle global highlight settings
+ *
+ * @param Standard Windows dialog procedure parameters
+ */
+
+INT_PTR CALLBACK CMUCHighlight::dlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG: {
+ DBVARIANT dbv = {0};
+
+ TranslateDialogDefault(hwndDlg);
+
+ if(0 == M->GetTString(0, "Chat", "HighlightWords", &dbv)) {
+ ::SetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, dbv.ptszVal);
+ ::DBFreeVariant(&dbv);
+ }
+
+ if(0 == M->GetTString(0, "Chat", "HighlightNames", &dbv)) {
+ ::SetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, dbv.ptszVal);
+ ::DBFreeVariant(&dbv);
+ }
+
+ DWORD dwFlags = M->GetByte("Chat", "HighlightEnabled", MATCH_TEXT);
+
+ ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTNICKENABLE, dwFlags & MATCH_NICKNAME ? BST_CHECKED : BST_UNCHECKED);
+ ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTNICKUID, dwFlags & MATCH_UIN ? BST_CHECKED : BST_UNCHECKED);
+ ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTTEXTENABLE, dwFlags & MATCH_TEXT ? BST_CHECKED : BST_UNCHECKED);
+ ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTME, M->GetByte("Chat", "HighlightMe", 1) ? BST_CHECKED : BST_UNCHECKED);
+
+ ::SendMessageW(hwndDlg, WM_USER + 100, 0, 0);
+ return(TRUE);
+ }
+
+ case WM_USER + 100:
+ Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN,
+ ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? TRUE : FALSE);
+
+ Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTNICKPATTERN,
+ ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? TRUE : FALSE);
+
+ Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTNICKUID,
+ ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? TRUE : FALSE);
+
+ Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTME,
+ ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? TRUE : FALSE);
+ return(FALSE);
+
+ case WM_COMMAND:
+ if ((LOWORD(wParam) == IDC_HIGHLIGHTNICKPATTERN
+ || LOWORD(wParam) == IDC_HIGHLIGHTTEXTPATTERN)
+ && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != ::GetFocus()))
+ return 0;
+
+ ::SendMessage(hwndDlg, WM_USER + 100, 0, 0);
+ if (lParam != (LPARAM)NULL)
+ ::SendMessage(::GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY: {
+ wchar_t* szBuf = 0;
+ int iLen = ::GetWindowTextLengthW(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTNICKPATTERN));
+
+ if(iLen) {
+ szBuf = reinterpret_cast<wchar_t *>(mir_alloc((iLen + 2) * sizeof(wchar_t)));
+ ::GetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, szBuf, iLen + 1);
+ M->WriteTString(0, "Chat", "HighlightNames",szBuf);
+ }
+
+ iLen = ::GetWindowTextLengthW(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN));
+ if(iLen) {
+ szBuf = reinterpret_cast<TCHAR *>(mir_realloc(szBuf, sizeof(wchar_t) * (iLen + 2)));
+ ::GetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, szBuf, iLen + 1);
+ M->WriteTString(0, "Chat", "HighlightWords", szBuf);
+ }
+ else
+ M->WriteTString(0, "Chat", "HighlightWords", L"");
+
+ mir_free(szBuf);
+ BYTE dwFlags = (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? MATCH_NICKNAME : 0) |
+ (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? MATCH_TEXT : 0);
+
+ if(dwFlags & MATCH_NICKNAME)
+ dwFlags |= (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKUID) ? MATCH_UIN : 0);
+
+ M->WriteByte("Chat", "HighlightEnabled", dwFlags);
+ M->WriteByte("Chat", "HighlightMe", ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTME) ? 1 : 0);
+ g_Settings.Highlight->init();
+ }
+ return TRUE;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+/**
+ * dialog procedure for the small "add user to highlight list" dialog box
+ * TODO: finish it
+ */
+INT_PTR CALLBACK CMUCHighlight::dlgProcAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ UINT uCmd = ::GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_INITDIALOG: {
+ HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0);
+ LOGFONTW lf = {0};
+
+ THighLightEdit *the = reinterpret_cast<THighLightEdit *>(lParam);
+ ::SetWindowLongPtr(hwndDlg, GWLP_USERDATA, the->uCmd);
+
+ ::GetObject(hFont, sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ lf.lfHeight = (int)(lf.lfHeight * 1.2);
+ hFont = ::CreateFontIndirectW(&lf);
+
+ ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_SETFONT, (WPARAM)hFont, FALSE);
+ if(the->uCmd == THighLightEdit::CMD_ADD) {
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEDITLIST, SW_HIDE);
+ ::SetDlgItemTextW(hwndDlg, IDC_ADDHIGHLIGHTTITLE, CTranslator::get(CTranslator::GEN_MUC_HIGHLIGHT_ADD));
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszNick);
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszUID);
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_SETCURSEL, 1, 0);
+ } else {
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTNAME, SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEXPLAIN, SW_HIDE);
+ ::SetDlgItemTextW(hwndDlg, IDC_ADDHIGHLIGHTTITLE, CTranslator::get(CTranslator::GEN_MUC_HIGHLIGHT_EDIT));
+ }
+ break;
+ }
+
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ HWND hwndChild = (HWND)lParam;
+ UINT id = ::GetDlgCtrlID(hwndChild);
+
+ if(hwndChild == ::GetDlgItem(hwndDlg, IDC_ADDHIGHLIGHTTITLE))
+ ::SetTextColor((HDC)wParam, RGB(60, 60, 150));
+ ::SetBkColor((HDC)wParam, ::GetSysColor(COLOR_WINDOW));
+ return (INT_PTR)::GetSysColorBrush(COLOR_WINDOW);
+ }
+
+ case WM_COMMAND: {
+ if(LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ ::DestroyWindow(hwndDlg);
+ break;
+ }
+
+ case WM_DESTROY: {
+ HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0);
+ ::DeleteObject(hFont);
+ break;
+ }
+ }
+ return(FALSE);
+}
+
diff --git a/plugins/TabSRMM/chat/muchighlight.h b/plugins/TabSRMM/chat/muchighlight.h
new file mode 100644
index 0000000000..cffac2ad39
--- /dev/null
+++ b/plugins/TabSRMM/chat/muchighlight.h
@@ -0,0 +1,94 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: muchighlight.h 12299 2010-08-10 02:39:36Z silvercircle $
+ *
+ * highlighter class for multi user chats
+ *
+ */
+
+class CMUCHighlight {
+
+public:
+
+ enum {
+ MATCH_TEXT = 1,
+ MATCH_NICKNAME = 2,
+ MATCH_UIN = 4,
+ };
+
+ CMUCHighlight()
+ {
+ m_fInitialized = false;
+ m_TextPatternString = m_NickPatternString = 0;
+ m_NickPatterns = m_TextPatterns = 0;
+ m_iNickPatterns = m_iTextPatterns = 0;
+ m_dwFlags = 0;
+ m_Valid = true;
+ init();
+ }
+
+ ~CMUCHighlight()
+ {
+ cleanup();
+ }
+
+ void init ();
+ void cleanup ();
+ int match (const GCEVENT *pgce, const SESSION_INFO *psi,
+ DWORD dwFlags = MATCH_NICKNAME);
+
+ static INT_PTR CALLBACK dlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); // option page dlg proc
+ static INT_PTR CALLBACK dlgProcAdd (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); // for the "add to" dialog
+private:
+ void tokenize(TCHAR *tszString, TCHAR**& patterns, UINT& nr);
+ int wildmatch (const TCHAR *pattern, const TCHAR *tszString);
+ DWORD m_dwFlags;
+ bool m_fInitialized;
+ TCHAR** m_NickPatterns;
+ TCHAR** m_TextPatterns;
+ UINT m_iNickPatterns;
+ UINT m_iTextPatterns;
+ TCHAR* m_NickPatternString;
+ TCHAR* m_TextPatternString;
+ bool m_Valid;
+ bool m_fHighlightMe;
+};
+
+struct THighLightEdit
+{
+ enum {
+ CMD_ADD = 1,
+ CMD_EDIT = 2
+ };
+
+ UINT uCmd;
+ SESSION_INFO *si;
+ USERINFO *ui;
+};
+
diff --git a/plugins/TabSRMM/chat/options.cpp b/plugins/TabSRMM/chat/options.cpp
new file mode 100644
index 0000000000..e3e40db2ac
--- /dev/null
+++ b/plugins/TabSRMM/chat/options.cpp
@@ -0,0 +1,1496 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: options.cpp 13412 2011-03-08 19:13:11Z george.hazan $
+ *
+ * group chat options and generic font handling
+ *
+ */
+
+#include "../src/commonheaders.h"
+#undef Translate
+
+#define TranslateA(s) ((char*)CallService(MS_LANGPACK_TRANSLATESTRING,0,(LPARAM)(s)))
+#include <shlobj.h>
+#include <shlwapi.h>
+
+extern HBRUSH hListBkgBrush;
+extern HICON hIcons[30];
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+extern HMODULE g_hIconDLL;
+
+extern HIMAGELIST CreateStateImageList();
+
+HANDLE g_hOptions = NULL;
+
+
+#define FONTF_BOLD 1
+#define FONTF_ITALIC 2
+
+struct FontOptionsList {
+ TCHAR* szDescr;
+ COLORREF defColour;
+ TCHAR* szDefFace;
+ BYTE defCharset, defStyle;
+ char defSize;
+ COLORREF colour;
+ TCHAR szFace[LF_FACESIZE];
+ BYTE charset, style;
+ char size;
+};
+
+struct ColorOptionsList {
+ int order;
+ TCHAR* tszGroup;
+ TCHAR* tszName;
+ char* szSetting;
+ COLORREF def;
+};
+
+/*
+ * note: bits 24-31 in default color indicates that color is a system color index
+ * (GetSysColor(default_color & 0x00ffffff)), not a rgb value.
+ */
+static ColorOptionsList _clrs[] = {
+ 0, LPGENT("TabSRMM/Group Chats"), LPGENT("Group chat log background"), SRMSGSET_BKGCOLOUR_MUC, SRMSGDEFSET_BKGCOLOUR,
+ 1, LPGENT("TabSRMM"), LPGENT("Input area background"), "inputbg", SRMSGDEFSET_BKGCOLOUR,
+ 2, LPGENT("TabSRMM"), LPGENT("Log background"), SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR,
+ 0, LPGENT("TabSRMM/Single Messaging"), LPGENT("Outgoing background"), "outbg", SRMSGDEFSET_BKGOUTCOLOUR,
+ 1, LPGENT("TabSRMM/Single Messaging"), LPGENT("Incoming background"), "inbg", SRMSGDEFSET_BKGINCOLOUR,
+ 2, LPGENT("TabSRMM/Single Messaging"), LPGENT("Status background"), "statbg", SRMSGDEFSET_BKGCOLOUR,
+ 3, LPGENT("TabSRMM/Single Messaging"), LPGENT("Incoming background(old)"), "oldinbg", SRMSGDEFSET_BKGINCOLOUR,
+ 4, LPGENT("TabSRMM/Single Messaging"), LPGENT("Outgoing background(old)"), "oldoutbg", SRMSGDEFSET_BKGOUTCOLOUR,
+ 5, LPGENT("TabSRMM/Single Messaging"), LPGENT("Horizontal Grid Lines"), "hgrid", RGB(224, 224, 224),
+ 0, LPGENT("TabSRMM/Info Panel"), LPGENT("Panel background low"), "ipfieldsbg", 0x62caff,
+ 1, LPGENT("TabSRMM/Info Panel"), LPGENT("Panel background high"), "ipfieldsbgHigh", 0xf0f0f0,
+ 0, LPGENT("TabSRMM/Common colors"), LPGENT("Toolbar background high"), "tbBgHigh", 0,
+ 1, LPGENT("TabSRMM/Common colors"), LPGENT("Toolbar background low"), "tbBgLow", 0,
+ 2, LPGENT("TabSRMM/Common colors"), LPGENT("Window fill color"), "fillColor", 0,
+ 3, LPGENT("TabSRMM/Common colors"), LPGENT("Text area borders"), "cRichBorders", 0,
+ 4, LPGENT("TabSRMM/Common colors"), LPGENT("Aero glow effect"), "aeroGlow", RGB(40, 40, 255),
+ 4, LPGENT("TabSRMM/Common colors"), LPGENT("Generic text color (only when fill color is set)"), "genericTxtClr", 0xff000000 | COLOR_BTNTEXT,
+};
+
+static ColorOptionsList _tabclrs[] = {
+ 0, LPGENT("TabSRMM/Tabs"), LPGENT("Normal text"), "tab_txt_normal", 0xff000000 | COLOR_BTNTEXT,
+ 1, LPGENT("TabSRMM/Tabs"), LPGENT("Active text"), "tab_txt_active", 0xff000000 | COLOR_BTNTEXT,
+ 2, LPGENT("TabSRMM/Tabs"), LPGENT("Hovered text"), "tab_txt_hottrack", 0xff000000 | COLOR_HOTLIGHT,
+ 3, LPGENT("TabSRMM/Tabs"), LPGENT("Unread text"), "tab_txt_unread", 0xff000000 | COLOR_HOTLIGHT,
+
+ 4, LPGENT("TabSRMM/Tabs"), LPGENT("Normal background"), "tab_bg_normal", 0xff000000 | COLOR_3DFACE,
+ 5, LPGENT("TabSRMM/Tabs"), LPGENT("Active background"), "tab_bg_active", 0xff000000 | COLOR_3DFACE,
+ 6, LPGENT("TabSRMM/Tabs"), LPGENT("Hovered background"), "tab_bg_hottrack", 0xff000000 | COLOR_3DFACE,
+ 7, LPGENT("TabSRMM/Tabs"), LPGENT("Unread background"), "tab_bg_unread", 0xff000000 | COLOR_3DFACE
+};
+
+extern LOGFONT lfDefault;
+
+//remember to put these in the Translate( ) template file too
+static FontOptionsList CHAT_fontOptionsList[] = {
+ {LPGENT("Timestamp"), RGB(50, 50, 240), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Others nicknames"), RGB(0, 0, 192), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("Your nickname"), RGB(0, 0, 192), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("User has joined"), RGB(90, 160, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User has left"), RGB(160, 160, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User has disconnected"), RGB(160, 90, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User kicked ..."), RGB(100, 100, 100), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User is now known as ..."), RGB(90, 90, 160), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Notice from user"), RGB(160, 130, 60), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Incoming message"), RGB(90, 90, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Outgoing message"), RGB(90, 90, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("The topic is ..."), RGB(70, 70, 160), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Information messages"), RGB(130, 130, 195), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User enables status for ..."), RGB(70, 150, 70), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User disables status for ..."), RGB(150, 70, 70), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Action message"), RGB(160, 90, 160), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Highlighted message"), RGB(180, 150, 80), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Chat log symbols (Webdings)"), RGB(170, 170, 170), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User list members (Online)"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User list members (away)"), RGB(170, 170, 170), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+};
+
+const int msgDlgFontCount = SIZEOF(CHAT_fontOptionsList);
+
+static FontOptionsList IM_fontOptionsList[] = {
+ {LPGENT(">> Outgoing messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT(">> Outgoing misc events"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("<< Incoming messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("<< Incoming misc events"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT(">> Outgoing name"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT(">> Outgoing timestamp"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("<< Incoming name"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("<< Incoming timestamp"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT(">> Outgoing messages (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT(">> Outgoing misc events (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("<< Incoming messages (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("<< Incoming misc events (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT(">> Outgoing name (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT(">> Outgoing timestamp (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("<< Incoming name (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("<< Incoming timestamp (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("* Message Input Area"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("* Status changes"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("* Dividers"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("* Error and warning Messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("* Symbols (incoming)"), RGB(50, 50, 50), _T("Webdings"), SYMBOL_CHARSET, 0, -12},
+ {LPGENT("* Symbols (outgoing)"), RGB(50, 50, 50), _T("Webdings"), SYMBOL_CHARSET, 0, -12},
+};
+
+static FontOptionsList IP_fontOptionsList[] = {
+ {LPGENT("Nickname"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("UIN"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Status"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Protocol"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Contacts local time"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Window caption (skinned mode)"), RGB(255, 255, 255), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+};
+
+static FontOptionsList *fontOptionsList = IM_fontOptionsList;
+static int fontCount = MSGDLGFONTCOUNT;
+
+struct branch_t {
+ TCHAR* szDescr;
+ char* szDBName;
+ int iMode;
+ BYTE bDefault;
+ HTREEITEM hItem;
+};
+static struct branch_t branch1[] = {
+ {LPGENT("Open new chat rooms in the default container"), "DefaultContainer", 0, 1, NULL},
+ {LPGENT("Flash window when someone speaks"), "FlashWindow", 0, 0, NULL},
+ {LPGENT("Flash window when a word is highlighted"), "FlashWindowHighlight", 0, 1, NULL},
+//TODO Fix for 3.0 !!!
+
+#if !defined(__DELAYED_FOR_3_1)
+ {LPGENT("Create tabs or windows for highlight events"), "CreateWindowOnHighlight", 0,0, NULL},
+ {LPGENT("Activate chat window on highlight"), "AnnoyingHighlight", 0,0, NULL},
+#endif
+
+ {LPGENT("Show list of users in the chat room"), "ShowNicklist", 0, 1, NULL},
+ {LPGENT("Colorize nicknames in member list"), "ColorizeNicks", 0, 1, NULL},
+ {LPGENT("Show button menus when right clicking the buttons"), "RightClickFilter", 0, 0, NULL},
+ {LPGENT("Show topic as status message on the contact list"), "TopicOnClist", 0, 1, NULL},
+ {LPGENT("Do not pop up the window when joining a chat room"), "PopupOnJoin", 0, 0, NULL},
+ {LPGENT("Hide or show the window by double click in the contact list"), "ToggleVisibility", 0, 0, NULL},
+ {LPGENT("Sync splitter position with standard IM sessions"), "SyncSplitter", 0, 0, NULL},
+ {LPGENT("Show contact's status modes if supported by the protocol"), "ShowContactStatus", 0, 1, NULL},
+ {LPGENT("Display contact's status icon before user role icon"), "ContactStatusFirst", 0, 0, NULL},
+ //MAD: simple customization improvement
+ {LPGENT("Use IRC style status indicators in the user list"), "ClassicIndicators", 0, 0, NULL},
+ {LPGENT("Use alternative sorting method in member list"), "AlternativeSorting", 0, 1, NULL},
+
+};
+static struct branch_t branch2[] = {
+ {LPGENT("Prefix all events with a timestamp"), "ShowTimeStamp", 0, 1, NULL},
+ {LPGENT("Timestamp only when event time differs"), "ShowTimeStampIfChanged", 0, 0, NULL},
+ {LPGENT("Timestamp has same color as the event"), "TimeStampEventColour", 0, 0, NULL},
+ {LPGENT("Indent the second line of a message"), "LogIndentEnabled", 0, 1, NULL},
+ {LPGENT("Limit user names in the message log to 20 characters"), "LogLimitNames", 0, 1, NULL},
+ {LPGENT("Add a colon (:) to auto-completed user names"), "AddColonToAutoComplete", 0, 1, NULL},
+ {LPGENT("Start private conversation on doubleclick in nick list (insert nick if unchecked)"), "DoubleClick4Privat", 0, 0, NULL},
+ {LPGENT("Strip colors from messages in the log"), "StripFormatting", 0, 0, NULL},
+ {LPGENT("Enable the \'event filter\' for new rooms"), "FilterEnabled", 0, 0, NULL},
+//MAD: simple customization improvement
+ {LPGENT("Use IRC style status indicators in the log"), "LogClassicIndicators", 0,0, NULL},
+//
+ {LPGENT("Allow clickable user names in the message log"), "ClickableNicks", 0, 1, NULL},
+ {LPGENT("Colorize user names in message log"), "ColorizeNicksInLog", 0, 1, NULL},
+ {LPGENT("Scale down icons to 10x10 pixels in the chat log"), "ScaleIcons", 0, 1, NULL},
+ {LPGENT("Place a separator in the log after a window lost its foreground status"), "UseDividers", 0, 1, NULL},
+ {LPGENT("Only place a separator when an incoming event is announced with a popup"), "DividersUsePopupConfig", 0, 1, NULL},
+ {LPGENT("Support the math module plugin"), "MathModSupport", 0, 0, NULL}
+};
+
+static HWND hPathTip = 0;
+
+void LoadMsgDlgFont(int section, int i, LOGFONT *lf, COLORREF* colour, char *szMod)
+{
+ char str[32];
+ int style;
+ DBVARIANT dbv;
+ int j = (i >= 100 ? i - 100 : i);
+
+ struct FontOptionsList *fol = fontOptionsList;
+ switch (section)
+ {
+ case FONTSECTION_CHAT: fol = CHAT_fontOptionsList; break;
+ case FONTSECTION_IM: fol = IM_fontOptionsList; break;
+ case FONTSECTION_IP: fol = IP_fontOptionsList; break;
+ }
+
+ if (colour) {
+ wsprintfA(str, "Font%dCol", i);
+ *colour = M->GetDword(szMod, str, fol[j].defColour);
+ }
+ if (lf) {
+ wsprintfA(str, "Font%dSize", i);
+ lf->lfHeight = (char) M->GetByte(szMod, str, fol[j].defSize);
+ lf->lfWidth = 0;
+ lf->lfEscapement = 0;
+ lf->lfOrientation = 0;
+ wsprintfA(str, "Font%dSty", i);
+ style = M->GetByte(szMod, str, fol[j].defStyle);
+ if(i == MSGFONTID_MESSAGEAREA && section == FONTSECTION_IM && M->GetByte(0, SRMSGMOD_T, "inputFontFix", 1) == 1) {
+ lf->lfWeight = FW_NORMAL;
+ lf->lfItalic = 0;
+ lf->lfUnderline = 0;
+ lf->lfStrikeOut = 0;
+ }
+ else {
+ lf->lfWeight = style & FONTF_BOLD ? FW_BOLD : FW_NORMAL;
+ lf->lfItalic = style & FONTF_ITALIC ? 1 : 0;
+ lf->lfUnderline = style & FONTF_UNDERLINE ? 1 : 0;
+ lf->lfStrikeOut = style & FONTF_STRIKEOUT ? 1 : 0;
+ }
+ wsprintfA(str, "Font%dSet", i);
+ lf->lfCharSet = M->GetByte(szMod, str, fol[j].defCharset);
+ lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf->lfQuality = DEFAULT_QUALITY;
+ lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ wsprintfA(str, "Font%d", i);
+ if ((i == 17 && !strcmp(szMod, CHAT_FONTMODULE)) || ((i == 20 || i == 21) && !strcmp(szMod, FONTMODULE))) {
+ lf->lfCharSet = SYMBOL_CHARSET;
+ lstrcpyn(lf->lfFaceName, _T("Webdings"), SIZEOF(lf->lfFaceName));
+ } else {
+ if (M->GetTString(NULL, szMod, str, &dbv)) {
+ lstrcpy(lf->lfFaceName, fol[j].szDefFace);
+ } else {
+ lstrcpyn(lf->lfFaceName, dbv.ptszVal, SIZEOF(lf->lfFaceName));
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+}
+
+static HTREEITEM InsertBranch(HWND hwndTree, TCHAR* pszDescr, BOOL bExpanded)
+{
+ TVINSERTSTRUCT tvis;
+
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_STATE;
+ tvis.item.pszText = TranslateTS(pszDescr);
+ tvis.item.stateMask = (bExpanded ? TVIS_STATEIMAGEMASK | TVIS_EXPANDED : TVIS_STATEIMAGEMASK) | TVIS_BOLD;
+ tvis.item.state = (bExpanded ? INDEXTOSTATEIMAGEMASK(0) | TVIS_EXPANDED : INDEXTOSTATEIMAGEMASK(0)) | TVIS_BOLD;
+ return TreeView_InsertItem(hwndTree, &tvis);
+}
+
+static void FillBranch(HWND hwndTree, HTREEITEM hParent, struct branch_t *branch, int nValues, DWORD defaultval)
+{
+ TVINSERTSTRUCT tvis;
+ int i;
+ int iState;
+
+ if (hParent == 0)
+ return;
+
+ tvis.hParent = hParent;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_STATE;
+ for (i = 0;i < nValues;i++) {
+ tvis.item.pszText = TranslateTS(branch[i].szDescr);
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ if (branch[i].iMode)
+ iState = ((M->GetDword("Chat", branch[i].szDBName, defaultval) & branch[i].iMode) & branch[i].iMode) != 0 ? 3 : 2;
+ else
+ iState = M->GetByte("Chat", branch[i].szDBName, branch[i].bDefault) != 0 ? 3 : 2;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK(iState);
+ branch[i].hItem = TreeView_InsertItem(hwndTree, &tvis);
+ }
+}
+
+static void SaveBranch(HWND hwndTree, struct branch_t *branch, int nValues)
+{
+ TVITEM tvi;
+ BYTE bChecked;
+ int i;
+ int iState = 0;
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ for (i = 0;i < nValues;i++) {
+ tvi.hItem = branch[i].hItem;
+ TreeView_GetItem(hwndTree, &tvi);
+ bChecked = ((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2) ? 0 : 1;
+ if (branch[i].iMode) {
+ if (bChecked)
+ iState |= branch[i].iMode;
+ if (iState & GC_EVENT_ADDSTATUS)
+ iState |= GC_EVENT_REMOVESTATUS;
+ M->WriteDword("Chat", branch[i].szDBName, (DWORD)iState);
+ } else M->WriteByte("Chat", branch[i].szDBName, bChecked);
+ }
+}
+
+static void CheckHeading(HWND hwndTree, HTREEITEM hHeading)
+{
+ BOOL bChecked = TRUE;
+ TVITEM tvi;
+
+ if (hHeading == 0)
+ return;
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.hItem = TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD);
+ while (tvi.hItem && bChecked) {
+ if (tvi.hItem != branch1[0].hItem && tvi.hItem != branch1[1].hItem) {
+ TreeView_GetItem(hwndTree, &tvi);
+ if (((tvi.state&TVIS_STATEIMAGEMASK) >> 12 == 2))
+ bChecked = FALSE;
+ }
+ tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem);
+ }
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ tvi.state = INDEXTOSTATEIMAGEMASK(1); //bChecked ? 3 : 2);
+ tvi.hItem = hHeading;
+ TreeView_SetItem(hwndTree, &tvi);
+}
+
+static void CheckBranches(HWND hwndTree, HTREEITEM hHeading)
+{
+ BOOL bChecked = TRUE;
+ TVITEM tvi;
+
+ if (hHeading == 0)
+ return;
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.hItem = hHeading;
+ TreeView_GetItem(hwndTree, &tvi);
+ if (((tvi.state&TVIS_STATEIMAGEMASK) >> 12 == 3)||((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 1))
+ bChecked = FALSE;
+
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ tvi.state = INDEXTOSTATEIMAGEMASK(bChecked ? 2 : 1);
+ TreeView_SetItem(hwndTree, &tvi);
+ tvi.hItem = TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD);
+ while (tvi.hItem) {
+ tvi.state = INDEXTOSTATEIMAGEMASK(bChecked ? 3:2);
+ if (tvi.hItem != branch1[0].hItem && tvi.hItem != branch1[1].hItem)
+ TreeView_SetItem(hwndTree, &tvi);
+ tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem);
+ }
+}
+
+static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
+{
+ char szDir[MAX_PATH];
+ switch (uMsg) {
+ case BFFM_INITIALIZED: {
+ const TCHAR *szData = M->getUserDir();
+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szData);
+ break;
+ }
+ case BFFM_SELCHANGED:
+ if (SHGetPathFromIDListA((LPITEMIDLIST) lp , szDir))
+ SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir);
+ break;
+ }
+ return 0;
+}
+
+static void LoadLogFonts(void)
+{
+ int i;
+
+ for (i = 0; i < OPTIONS_FONTCOUNT; i++)
+ LoadMsgDlgFont(FONTSECTION_CHAT, i, &aFonts[i].lf, &aFonts[i].color, CHAT_FONTMODULE);
+}
+
+static struct _tagicons { char *szDesc; char *szName; int id; UINT size;} _icons[] = {
+ LPGEN("Window Icon"), "chat_window", IDI_CHANMGR, 16,
+ LPGEN("Icon overlay"), "chat_overlay", IDI_OVERLAY, 16,
+
+ LPGEN("Status 1 (10x10)"), "chat_status0", IDI_STATUS0, 16,
+ LPGEN("Status 2 (10x10)"), "chat_status1", IDI_STATUS1, 16,
+ LPGEN("Status 3 (10x10)"), "chat_status2", IDI_STATUS2, 16,
+ LPGEN("Status 4 (10x10)"), "chat_status3", IDI_STATUS3, 16,
+ LPGEN("Status 5 (10x10)"), "chat_status4", IDI_STATUS4, 16,
+ LPGEN("Status 6 (10x10)"), "chat_status5", IDI_STATUS5, 16,
+ NULL, NULL, -1, 0
+};
+
+static struct _tag1icons { char *szDesc; char *szName; int id; UINT size;} _logicons[] = {
+ LPGEN("Message in (10x10)"), "chat_log_message_in", IDI_MESSAGE, 16,
+ LPGEN("Message out (10x10)"), "chat_log_message_out", IDI_MESSAGEOUT, 16,
+ LPGEN("Action (10x10)"), "chat_log_action", IDI_ACTION, 16,
+ LPGEN("Add Status (10x10)"), "chat_log_addstatus", IDI_ADDSTATUS, 16,
+ LPGEN("Remove Status (10x10)"), "chat_log_removestatus", IDI_REMSTATUS, 16,
+ LPGEN("Join (10x10)"), "chat_log_join", IDI_JOIN, 16,
+ LPGEN("Leave (10x10)"), "chat_log_part", IDI_PART, 16,
+ LPGEN("Quit (10x10)"), "chat_log_quit", IDI_QUIT, 16,
+ LPGEN("Kick (10x10)"), "chat_log_kick", IDI_KICK, 16,
+ LPGEN("Notice (10x10)"), "chat_log_notice", IDI_NOTICE, 16,
+ LPGEN("Nickchange (10x10)"), "chat_log_nick", IDI_NICK, 16,
+ LPGEN("Topic (10x10)"), "chat_log_topic", IDI_TOPIC, 16,
+ LPGEN("Highlight (10x10)"), "chat_log_highlight", IDI_HIGHLIGHT, 16,
+ LPGEN("Information (10x10)"), "chat_log_info", IDI_INFO, 16,
+ NULL, NULL, 0, 0
+};
+
+// add icons to the skinning module
+void Chat_AddIcons(void)
+{
+ if (ServiceExists(MS_SKIN2_ADDICON)) {
+ SKINICONDESC sid = {0};
+ char szFile[MAX_PATH];
+ int i = 0;
+
+ // 16x16 icons
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.pszSection = TranslateA("TabSRMM/Group chat windows");
+ GetModuleFileNameA(g_hIconDLL, szFile, MAX_PATH);
+ sid.pszDefaultFile = szFile;
+
+ while (_icons[i].szDesc != NULL) {
+ sid.cx = sid.cy = _icons[i].size;
+ sid.pszDescription = _icons[i].szDesc;
+ sid.pszName = _icons[i].szName;
+ sid.iDefaultIndex = -_icons[i].id;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ i++;
+ }
+ i = 0;
+ sid.pszSection = TranslateA("TabSRMM/Group chat log");
+ while (_logicons[i].szDesc != NULL) {
+ sid.cx = sid.cy = _logicons[i].size;
+ sid.pszDescription = _logicons[i].szDesc;
+ sid.pszName = _logicons[i].szName;
+ sid.iDefaultIndex = -_logicons[i].id;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ i++;
+ }
+ }
+ return;
+}
+
+/*
+ * get icon by name from the core icon library service
+ */
+
+HICON LoadIconEx(int iIndex, char * pszIcoLibName, int iX, int iY)
+{
+ char szTemp[256];
+ mir_snprintf(szTemp, sizeof(szTemp), "chat_%s", pszIcoLibName);
+ return (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM)szTemp);
+}
+
+static void InitSetting(TCHAR** ppPointer, char* pszSetting, TCHAR* pszDefault)
+{
+ DBVARIANT dbv;
+ if (!M->GetTString(NULL, "Chat", pszSetting, &dbv)) {
+ replaceStr(ppPointer, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else
+ replaceStr(ppPointer, pszDefault);
+}
+
+#define OPT_FIXHEADINGS (WM_USER+1)
+
+static UINT _o1controls[] = {IDC_CHECKBOXES, IDC_GROUP, IDC_STATIC_ADD, 0};
+
+HWND CreateToolTip(HWND hwndParent, LPTSTR ptszText, LPTSTR ptszTitle)
+{
+ TOOLINFO ti = { 0 };
+ HWND hwndTT;
+ hwndTT = CreateWindowEx(WS_EX_TOPMOST,
+ TOOLTIPS_CLASS, NULL,
+ WS_POPUP | TTS_NOPREFIX,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ hwndParent, NULL, g_hInst, NULL);
+
+ SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+
+ ti.cbSize = sizeof(TOOLINFO);
+ ti.uFlags = TTF_SUBCLASS | TTF_CENTERTIP;
+ ti.hwnd = hwndParent;
+ ti.hinst = g_hInst;
+ ti.lpszText = ptszText;
+ GetClientRect (hwndParent, &ti.rect);
+ ti.rect.left =- 85;
+
+ SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
+ SendMessage(hwndTT, TTM_SETTITLE, 1, (LPARAM)ptszTitle);
+ return hwndTT;
+}
+
+INT_PTR CALLBACK DlgProcOptions1(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static HTREEITEM hListHeading1 = 0;
+ static HTREEITEM hListHeading2 = 0;
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ if (PluginConfig.m_chat_enabled) {
+ HIMAGELIST himlOptions;
+
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES);
+
+ himlOptions = (HIMAGELIST)SendDlgItemMessage(hwndDlg, IDC_CHECKBOXES, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)CreateStateImageList());
+ ImageList_Destroy(himlOptions);
+
+ hListHeading1 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), const_cast<TCHAR *>(CTranslator::getOpt(CTranslator::OPT_MUC_OPTHEADER1)), TRUE);
+ hListHeading2 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), const_cast<TCHAR *>(CTranslator::getOpt(CTranslator::OPT_MUC_OPTHEADER2)), TRUE);
+
+ FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, branch1, SIZEOF(branch1), 0x0000);
+ FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, branch2, SIZEOF(branch2), 0x0000);
+
+ {
+ TCHAR* pszGroup = NULL;
+ InitSetting(&pszGroup, "AddToGroup", _T("Chat rooms"));
+ SetWindowText(GetDlgItem(hwndDlg, IDC_GROUP), pszGroup);
+ mir_free(pszGroup);
+ Utils::showDlgControl(hwndDlg, IDC_STATIC_MESSAGE, SW_HIDE);
+ }
+ } else {
+ int i = 0;
+
+ while (_o1controls[i])
+ Utils::showDlgControl(hwndDlg, _o1controls[i++], SW_HIDE);
+ }
+ break;
+
+ case WM_COMMAND:
+ if ((LOWORD(wParam) == IDC_GROUP)
+ && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+
+ if (lParam != (LPARAM)NULL)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY: {
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case IDC_CHECKBOXES:
+ if (((LPNMHDR)lParam)->code == NM_CLICK || (((LPNMHDR)lParam)->code == TVN_KEYDOWN && ((LPNMTVKEYDOWN)lParam)->wVKey == VK_SPACE)) {
+ 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) || ((LPNMHDR)lParam)->code == TVN_KEYDOWN) {
+ if (((LPNMHDR)lParam)->code == TVN_KEYDOWN)
+ hti.flags |= TVHT_ONITEMSTATEICON;
+ if (hti.flags&TVHT_ONITEMSTATEICON) {
+ TVITEM tvi = {0};
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.stateMask = TVIS_STATEIMAGEMASK | TVIS_BOLD;
+
+ if (((LPNMHDR)lParam)->code == TVN_KEYDOWN)
+ tvi.hItem = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
+ else
+ tvi.hItem = (HTREEITEM)hti.hItem;
+
+ TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &tvi);
+
+ if (tvi.state & TVIS_BOLD && hti.flags & TVHT_ONITEMSTATEICON) {
+ tvi.state = INDEXTOSTATEIMAGEMASK(0) | TVIS_BOLD;
+ SendDlgItemMessageA(hwndDlg, IDC_CHECKBOXES, TVM_SETITEMA, 0, (LPARAM)&tvi);
+ } else if (hti.flags&TVHT_ONITEMSTATEICON) {
+ if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12) == 3) {
+ tvi.state = INDEXTOSTATEIMAGEMASK(1);
+ SendDlgItemMessageA(hwndDlg, IDC_CHECKBOXES, TVM_SETITEMA, 0, (LPARAM)&tvi);
+ }
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ }
+
+ break;
+
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY: {
+ if (PluginConfig.m_chat_enabled) {
+ int iLen;
+ TCHAR *pszText = NULL;
+ BYTE b;
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_GROUP));
+ if (iLen > 0) {
+ pszText = (TCHAR *)realloc(pszText, (iLen + 2) * sizeof(TCHAR));
+ GetDlgItemText(hwndDlg, IDC_GROUP, pszText, iLen + 1);
+ M->WriteTString(NULL, "Chat", "AddToGroup", pszText);
+ } else
+ M->WriteTString(NULL, "Chat", "AddToGroup", _T(""));
+
+ g_Settings.hGroup = 0;
+
+ if (pszText)
+ free(pszText);
+
+ b = M->GetByte("Chat", "Tabs", 1);
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch1, sizeof(branch1) / sizeof(branch1[0]));
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch2, sizeof(branch2) / sizeof(branch2[0]));
+
+ LoadGlobalSettings();
+ MM_FontsChanged();
+ FreeMsgLogBitmaps();
+ LoadMsgLogBitmaps();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ SM_ReconfigureFilters();
+ }
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+ case WM_DESTROY: {
+ BYTE b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, TVIS_EXPANDED) & TVIS_EXPANDED ? 1 : 0;
+ M->WriteByte("Chat", "Branch1Exp", b);
+ b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, TVIS_EXPANDED) & TVIS_EXPANDED ? 1 : 0;
+ M->WriteByte("Chat", "Branch2Exp", b);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static TCHAR* chatcolorsnames[] ={
+// LPGENT("Your nickname"),
+ LPGENT("Channel operators"),
+ LPGENT("Half operators"),
+ LPGENT("Voiced"),
+// LPGENT("Others nicknames"),
+ LPGENT("Extended mode 1"),
+ LPGENT("Extended mode 2"),
+ LPGENT("Selection background"),
+ LPGENT("Selected text"),
+ LPGENT("Incremental search highlight")
+ };
+
+void RegisterFontServiceFonts() {
+ int i;
+ char szTemp[100];
+ LOGFONT lf;
+ FontIDT fid = {0};
+ ColourIDT cid = {0};
+
+ fid.cbSize = sizeof(FontIDT);
+ cid.cbSize = sizeof(ColourIDT);
+
+ strncpy(fid.dbSettingsGroup, FONTMODULE, SIZEOF(fid.dbSettingsGroup));
+
+ for (i = 0; i < SIZEOF(IM_fontOptionsList); i++) {
+ fid.flags = FIDF_DEFAULTVALID|FIDF_ALLOWEFFECTS;
+ LoadMsgDlgFont(FONTSECTION_IM, i , &lf, &fontOptionsList[i].colour, FONTMODULE);
+ mir_snprintf(szTemp, SIZEOF(szTemp), "Font%d", i);
+ strncpy(fid.prefix, szTemp, SIZEOF(fid.prefix));
+ fid.order = i;
+ _tcsncpy(fid.name, fontOptionsList[i].szDescr, SIZEOF(fid.name));
+ fid.deffontsettings.colour = fontOptionsList[i].colour;
+ fid.deffontsettings.size = (char) lf.lfHeight;
+ fid.deffontsettings.style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0);
+ fid.deffontsettings.charset = lf.lfCharSet;
+ fid.flags = fid.flags & ~FIDF_CLASSMASK | (fid.deffontsettings.style&FONTF_BOLD ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL);
+ _tcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE);
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM/Single Messaging"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.group, _T("TabSRMM/Single Messaging"), SIZEOF(fid.group));
+ switch (i) {
+ case MSGFONTID_MYMSG:
+ case 1:
+ case MSGFONTID_MYNAME:
+ case MSGFONTID_MYTIME:
+ case 21:
+ _tcsncpy(fid.backgroundName, _T("Outgoing background"), SIZEOF(fid.backgroundName));
+ break;
+ case 8:
+ case 9:
+ case 12:
+ case 13:
+ _tcsncpy(fid.backgroundName, _T("Outgoing background(old)"), SIZEOF(fid.backgroundName));
+ break;
+ case 10:
+ case 11:
+ case 14:
+ case 15:
+ _tcsncpy(fid.backgroundName, _T("Incoming background(old)"), SIZEOF(fid.backgroundName));
+ break;
+ case MSGFONTID_MESSAGEAREA:
+ _tcsncpy(fid.group, _T("TabSRMM"), SIZEOF(fid.group));
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T("Input area background"), SIZEOF(fid.backgroundName));
+ fid.flags |= FIDF_DISABLESTYLES;
+ fid.flags &= ~FIDF_ALLOWEFFECTS;
+ break;
+ case 17:
+ _tcsncpy(fid.backgroundName, _T("Status background"), SIZEOF(fid.backgroundName));
+ break;
+ case 18:
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T("Log background"), SIZEOF(fid.backgroundName));
+ break;
+ case 19:
+ _tcsncpy(fid.backgroundName, _T(""), SIZEOF(fid.backgroundName));
+ break;
+ default:
+ _tcsncpy(fid.backgroundName, _T("Incoming background"), SIZEOF(fid.backgroundName));
+ break;
+ }
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fid, 0);
+ }
+
+ fontOptionsList = IP_fontOptionsList;
+ fid.flags = FIDF_DEFAULTVALID|FIDF_ALLOWEFFECTS;
+ //fid.flags|=FIDF_SAVEPOINTSIZE;
+ _tcsncpy(fid.group, _T("TabSRMM/Info Panel"), SIZEOF(fid.group));
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM/Info Panel"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T("Fields background"), SIZEOF(fid.backgroundName));
+ for (i =0; i < IPFONTCOUNT; i++) {
+ LoadMsgDlgFont(FONTSECTION_IP, i + 100 , &lf, &fontOptionsList[i].colour, FONTMODULE);
+ mir_snprintf(szTemp, SIZEOF(szTemp), "Font%d", i + 100);
+ strncpy(fid.prefix, szTemp, SIZEOF(fid.prefix));
+ fid.order = i + 100 ;
+ _tcsncpy(fid.name, fontOptionsList[i].szDescr, SIZEOF(fid.name));
+ fid.deffontsettings.colour = fontOptionsList[i].colour;
+ fid.deffontsettings.size = (char) lf.lfHeight;
+ fid.deffontsettings.style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0);
+ fid.deffontsettings.charset = lf.lfCharSet;
+ fid.flags = fid.flags & ~FIDF_CLASSMASK | (fid.deffontsettings.style&FONTF_BOLD ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL);
+ fid.deffontsettings.charset = lf.lfCharSet;
+ _tcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE);
+ if(i==IPFONTCOUNT-1){
+ _tcsncpy(fid.backgroundGroup, _T(""), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T(""), SIZEOF(fid.backgroundName));
+ _tcsncpy(fid.group, _T("TabSRMM"), SIZEOF(fid.group));
+ }
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fid, 0);
+ }
+
+ fontOptionsList = CHAT_fontOptionsList;
+ fid.flags = FIDF_DEFAULTVALID|FIDF_ALLOWEFFECTS;
+ fid.flags&=~FIDF_SAVEPOINTSIZE;
+ _tcsncpy(fid.group, _T("TabSRMM/Group Chats"), SIZEOF(fid.group));
+ strncpy(fid.dbSettingsGroup, CHAT_FONTMODULE, SIZEOF(fid.dbSettingsGroup));
+ for (i = 0; i < msgDlgFontCount; i++) {
+ LoadMsgDlgFont(FONTSECTION_CHAT, i , &lf, &fontOptionsList[i].colour, CHAT_FONTMODULE);
+ mir_snprintf(szTemp, SIZEOF(szTemp), "Font%d", i);
+ strncpy(fid.prefix, szTemp, SIZEOF(fid.prefix));
+ fid.order = i;
+ _tcsncpy(fid.name, fontOptionsList[i].szDescr, SIZEOF(fid.name));
+ fid.deffontsettings.colour = fontOptionsList[i].colour;
+ fid.deffontsettings.size = (char) lf.lfHeight;
+ fid.deffontsettings.style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0);
+ fid.flags = fid.flags & ~FIDF_CLASSMASK | (fid.deffontsettings.style&FONTF_BOLD ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL);
+ fid.deffontsettings.charset = lf.lfCharSet;
+ _tcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE);
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM/Group Chats"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T("Group chat log background"), SIZEOF(fid.backgroundName));
+ if(i == 18 || i == 19)
+ _tcsncpy(fid.backgroundName, _T("Userlist background"), SIZEOF(fid.backgroundName));
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fid, 0);
+ }
+
+ _tcsncpy(cid.group, _T("TabSRMM/Group Chats"), SIZEOF(cid.group));
+ strncpy(cid.dbSettingsGroup, "Chat", SIZEOF(cid.dbSettingsGroup));
+ for (i = 0; i <= 7; i++) {
+ mir_snprintf(szTemp, SIZEOF(szTemp), "NickColor%d", i);
+ _tcsncpy(cid.name, chatcolorsnames[i], SIZEOF(cid.name));
+ cid.order=i+1;
+ strncpy(cid.setting, szTemp, SIZEOF(cid.setting));
+ switch (i) {
+ case 5:
+ cid.defcolour = GetSysColor(COLOR_HIGHLIGHT);
+ break;
+ case 6:
+ cid.defcolour = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ break;
+ default:
+ cid.defcolour =RGB(0, 0, 0);
+ break;
+ }
+ CallService(MS_COLOUR_REGISTERT, (WPARAM)&cid, 0);
+ }
+ cid.order=8;
+ _tcsncpy(cid.name, _T("Userlist background"), SIZEOF(cid.name));
+ strncpy(cid.setting, "ColorNicklistBG", SIZEOF(cid.setting));
+ cid.defcolour = SRMSGDEFSET_BKGCOLOUR;
+ CallService(MS_COLOUR_REGISTERT, (WPARAM)&cid, 0);
+
+ /*
+ * static colors (info panel, tool bar background etc...)
+ */
+ strncpy(fid.dbSettingsGroup, FONTMODULE, SIZEOF(fid.dbSettingsGroup));
+ strncpy(cid.dbSettingsGroup, FONTMODULE, SIZEOF(fid.dbSettingsGroup));
+
+ for(i = 0; i < (sizeof(_clrs) / sizeof(_clrs[0])); i++) {
+ cid.order = _clrs[i].order;
+ _tcsncpy(cid.group, _clrs[i].tszGroup, SIZEOF(fid.group));
+ _tcsncpy(cid.name, _clrs[i].tszName, SIZEOF(cid.name));
+ strncpy(cid.setting, _clrs[i].szSetting, SIZEOF(cid.setting));
+ if(_clrs[i].def & 0xff000000)
+ cid.defcolour = GetSysColor(_clrs[i].def & 0x000000ff);
+ else
+ cid.defcolour = _clrs[i].def;
+ CallService(MS_COLOUR_REGISTERT, (WPARAM)&cid, 0);
+ }
+
+ strncpy(cid.dbSettingsGroup, SRMSGMOD_T, SIZEOF(fid.dbSettingsGroup));
+
+ /*
+ * text and background colors for tabs
+ */
+ for(i = 0; i < (sizeof(_tabclrs) / sizeof(_tabclrs[0])); i++) {
+ cid.order = _tabclrs[i].order;
+ _tcsncpy(cid.group, _tabclrs[i].tszGroup, SIZEOF(fid.group));
+ _tcsncpy(cid.name, _tabclrs[i].tszName, SIZEOF(cid.name));
+ strncpy(cid.setting, _tabclrs[i].szSetting, SIZEOF(cid.setting));
+ if(_tabclrs[i].def & 0xff000000)
+ cid.defcolour = GetSysColor(_tabclrs[i].def & 0x000000ff);
+ else
+ cid.defcolour = _tabclrs[i].def;
+
+ CallService(MS_COLOUR_REGISTERT, (WPARAM)&cid, 0);
+ }
+}
+
+int FontServiceFontsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (PluginConfig.m_chat_enabled) {
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ LoadLogFonts();
+ FreeMsgLogBitmaps();
+ LoadMsgLogBitmaps();
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 0, &lf, NULL, CHAT_FONTMODULE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)), hFont, TRUE);
+ DeleteObject(hFont);
+ g_Settings.LogTextIndent = iText;
+ g_Settings.LogTextIndent = g_Settings.LogTextIndent * 12 / 10;
+ g_Settings.LogIndentEnabled = (M->GetByte("Chat", "LogIndentEnabled", 1) != 0) ? TRUE : FALSE;
+
+ LoadGlobalSettings();
+ MM_FontsChanged();
+ MM_FixColors();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ }
+
+ PluginConfig.reloadSettings();
+ CSkin::initAeroEffect();
+ CacheMsgLogIcons();
+ CacheLogFonts();
+ FreeTabConfig();
+ ReloadTabConfig();
+ Skin->setupAeroSkins();
+ M->BroadcastMessage(DM_OPTIONSAPPLIED, 1, 0);
+ return 0;
+}
+
+
+static UINT _o2chatcontrols[] = { IDC_CHAT_SPIN2, IDC_LIMIT, IDC_CHAT_SPIN4, IDC_LOGTIMESTAMP, IDC_TIMESTAMP,
+ IDC_OUTSTAMP, IDC_FONTCHOOSE, IDC_LOGGING, IDC_LOGDIRECTORY, IDC_INSTAMP, IDC_CHAT_SPIN2, IDC_CHAT_SPIN3, IDC_NICKROW2, IDC_LOGLIMIT,
+ IDC_STATIC110, IDC_STATIC112, 0};
+
+static UINT _o3chatcontrols[] = {0};
+
+INT_PTR CALLBACK DlgProcOptions2(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_INITDIALOG: {
+
+ TranslateDialogDefault(hwndDlg);
+
+ if (PluginConfig.m_chat_enabled) {
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_SETRANGE, 0, MAKELONG(5000, 0));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_SETPOS, 0, MAKELONG(DBGetContactSettingWord(NULL, "Chat", "LogLimit", 100), 0));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_SETRANGE, 0, MAKELONG(255, 10));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_SETPOS, 0, MAKELONG(M->GetByte("Chat", "NicklistRowDist", 12), 0));
+ 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_LOGGING, g_Settings.LoggingEnabled);
+ SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, g_Settings.pszLogDir);
+ Utils::enableDlgControl(hwndDlg, IDC_LOGDIRECTORY, g_Settings.LoggingEnabled ? TRUE : FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_FONTCHOOSE, g_Settings.LoggingEnabled ? TRUE : FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_SETRANGE, 0, MAKELONG(10000, 0));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_SETPOS, 0, MAKELONG(DBGetContactSettingWord(NULL, "Chat", "LoggingLimit", 100), 0));
+ Utils::enableDlgControl(hwndDlg, IDC_LIMIT, g_Settings.LoggingEnabled ? TRUE : FALSE);
+
+ if (ServiceExists(MS_UTILS_REPLACEVARS)) {
+ TCHAR tszTooltipText[2048];
+
+ mir_sntprintf(tszTooltipText, SIZEOF(tszTooltipText),
+ _T("%s - %s\n%s - %s\n%s - %s\n\n")
+ _T("%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n\n")
+ _T("%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s"),
+ // contact vars
+ _T("%nick%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP1),
+ _T("%proto%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP2),
+ _T("%userid%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP3),
+ // global vars
+ _T("%miranda_path%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP4),
+ _T("%miranda_profile%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP5),
+ _T("%miranda_profilename%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP6),
+ _T("%miranda_userdata%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP7),
+ _T("%appdata%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP8),
+ _T("%username%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP9),
+ _T("%mydocuments%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP10),
+ _T("%desktop%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP11),
+ _T("%xxxxxxx%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP12),
+ // date/time vars
+ _T("%d%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP13),
+ _T("%dd%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP14),
+ _T("%m%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP15),
+ _T("%mm%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP16),
+ _T("%mon%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP17),
+ _T("%month%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP18),
+ _T("%yy%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP19),
+ _T("%yyyy%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP20),
+ _T("%wday%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP21),
+ _T("%weekday%"), CTranslator::getOpt(CTranslator::OPT_MUC_LOGTIP22));
+ hPathTip = CreateToolTip(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), tszTooltipText, const_cast<TCHAR *>(CTranslator::getOpt(CTranslator::OPT_MUC_VARIABLES)));
+ }
+
+ } else {
+ int i = 0;
+
+ while (_o2chatcontrols[i])
+ Utils::enableDlgControl(hwndDlg, _o2chatcontrols[i++], FALSE);
+ }
+ if (hPathTip)
+ SetTimer(hwndDlg, 0, 3000, NULL);
+ break;
+ }
+ case WM_COMMAND:
+ if ((LOWORD(wParam) == IDC_INSTAMP
+ || LOWORD(wParam) == IDC_OUTSTAMP
+ || LOWORD(wParam) == IDC_TIMESTAMP
+ || LOWORD(wParam) == IDC_LOGLIMIT
+ || LOWORD(wParam) == IDC_NICKROW2
+ || LOWORD(wParam) == IDC_LOGDIRECTORY
+ || LOWORD(wParam) == IDC_LIMIT
+ || LOWORD(wParam) == IDC_LOGTIMESTAMP)
+ && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+
+ switch (LOWORD(wParam)) {
+ /*
+ * open the base directory for MUC logs, using a standard file selector
+ * dialog. Simply allows the user to view what log files are there
+ * and possibly delete archived logs.
+ */
+ case IDC_MUC_OPENLOGBASEDIR: {
+ OPENFILENAME ofn = {0};
+ SESSION_INFO si = {0};
+ TCHAR tszReturnName[MAX_PATH];
+ TCHAR tszInitialDir[_MAX_DRIVE + _MAX_PATH + 10];
+ TCHAR tszTemp[MAX_PATH + 20], *p = 0, *p1 = 0;
+
+ mir_sntprintf(tszTemp, MAX_PATH + 20, _T("%s"), g_Settings.pszLogDir);
+
+ p = tszTemp;
+ while(*p && (*p == '\\' || *p == '.'))
+ p++;
+
+ if(*p) {
+ if((p1 = _tcschr(p, '\\')))
+ *p1 = 0;
+ }
+
+ mir_sntprintf(tszInitialDir, MAX_PATH, _T("%s%s"), M->getChatLogPath(), p);
+ if(PathFileExists(tszInitialDir))
+ ofn.lpstrInitialDir = tszInitialDir;
+ else {
+ mir_sntprintf(tszInitialDir, MAX_PATH, _T("%s"), M->getChatLogPath());
+ ofn.lpstrInitialDir = tszInitialDir;
+ }
+
+ tszReturnName[0] = 0;
+ mir_sntprintf(tszTemp, SIZEOF(tszTemp), _T("%s%c*.*%c%c"), TranslateT("All Files"), 0, 0, 0);
+
+ ofn.lpstrFilter = tszTemp;
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = 0;
+ ofn.lpstrFile = tszReturnName;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.Flags = OFN_HIDEREADONLY | OFN_DONTADDTORECENT;
+ ofn.lpstrDefExt = _T("log");
+ GetOpenFileName(&ofn);
+ break;
+ }
+
+ case IDC_FONTCHOOSE: {
+ TCHAR tszDirectory[MAX_PATH];
+ LPITEMIDLIST idList;
+ LPMALLOC psMalloc;
+ BROWSEINFO bi = {0};
+
+ if (SUCCEEDED(CoGetMalloc(1, &psMalloc))) {
+ TCHAR tszTemp[MAX_PATH];
+ bi.hwndOwner = hwndDlg;
+ bi.pszDisplayName = tszDirectory;
+ bi.lpszTitle = const_cast<TCHAR *>(CTranslator::getOpt(CTranslator::OPT_MUC_SELECTFOLDER));
+ bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_RETURNONLYFSDIRS;
+ bi.lpfn = BrowseCallbackProc;
+ bi.lParam = (LPARAM)tszDirectory;
+
+
+ idList = SHBrowseForFolder(&bi);
+ if (idList) {
+ const TCHAR *szUserDir = M->getUserDir();
+ SHGetPathFromIDList(idList, tszDirectory);
+ lstrcat(tszDirectory, _T("\\"));
+ M->pathToRelative(tszDirectory, tszTemp, const_cast<TCHAR *>(szUserDir));
+ SetWindowText(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), lstrlen(tszTemp) > 1 ? tszTemp : DEFLOGFILENAME);
+ }
+ psMalloc->Free(idList);
+ psMalloc->Release();
+ }
+ break;
+ }
+
+ case IDC_LOGGING:
+ if (PluginConfig.m_chat_enabled) {
+ Utils::enableDlgControl(hwndDlg, IDC_LOGDIRECTORY, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_FONTCHOOSE, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_LIMIT, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE);
+ }
+ break;
+ }
+
+ if (lParam != (LPARAM)NULL)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) {
+ int iLen;
+ TCHAR *p2 = NULL;
+ char *pszText = NULL;
+ TCHAR *ptszPath = NULL;
+
+ if (PluginConfig.m_chat_enabled) {
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY));
+ if (iLen > 0) {
+ TCHAR *pszText1 = (TCHAR *)malloc(iLen*sizeof(TCHAR) + 2);
+ GetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, pszText1, iLen + 1);
+ M->WriteTString(NULL, "Chat", "LogDirectory", pszText1);
+ free(pszText1);
+ g_Settings.LoggingEnabled = IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE;
+ M->WriteByte("Chat", "LoggingEnabled", (BYTE)g_Settings.LoggingEnabled);
+ } else {
+ DBDeleteContactSetting(NULL, "Chat", "LogDirectory");
+ M->WriteByte("Chat", "LoggingEnabled", 0);
+ }
+ SM_InvalidateLogDirectories();
+
+ iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_GETPOS, 0, 0);
+ DBWriteContactSettingWord(NULL, "Chat", "LoggingLimit", (WORD)iLen);
+
+ iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_GETPOS, 0, 0);
+ if (iLen > 0)
+ M->WriteByte("Chat", "NicklistRowDist", (BYTE)iLen);
+ else
+ DBDeleteContactSetting(NULL, "Chat", "NicklistRowDist");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGTIMESTAMP));
+ if (iLen > 0) {
+ pszText = (char *)realloc(pszText, iLen + 1);
+ GetDlgItemTextA(hwndDlg, IDC_LOGTIMESTAMP, pszText, iLen + 1);
+ DBWriteContactSettingString(NULL, "Chat", "LogTimestamp", pszText);
+ } else DBDeleteContactSetting(NULL, "Chat", "LogTimestamp");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_TIMESTAMP));
+ if (iLen > 0) {
+ pszText = (char *)realloc(pszText, iLen + 1);
+ GetDlgItemTextA(hwndDlg, IDC_TIMESTAMP, pszText, iLen + 1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderTime", pszText);
+ } else DBDeleteContactSetting(NULL, "Chat", "HeaderTime");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_INSTAMP));
+ if (iLen > 0) {
+ pszText = (char *)realloc(pszText, iLen + 1);
+ GetDlgItemTextA(hwndDlg, IDC_INSTAMP, pszText, iLen + 1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderIncoming", pszText);
+ } else DBDeleteContactSetting(NULL, "Chat", "HeaderIncoming");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_OUTSTAMP));
+ if (iLen > 0) {
+ pszText = (char *)realloc(pszText, iLen + 1);
+ GetDlgItemTextA(hwndDlg, IDC_OUTSTAMP, pszText, iLen + 1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderOutgoing", pszText);
+ } else DBDeleteContactSetting(NULL, "Chat", "HeaderOutgoing");
+
+ iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_GETPOS, 0, 0);
+ DBWriteContactSettingWord(NULL, "Chat", "LogLimit", (WORD)iLen);
+ }
+
+
+ if (pszText != NULL)
+ free(pszText);
+ if (hListBkgBrush)
+ DeleteObject(hListBkgBrush);
+ hListBkgBrush = CreateSolidBrush(M->GetDword("Chat", "ColorNicklistBG", SRMSGDEFSET_BKGCOLOUR));
+
+
+ if (PluginConfig.m_chat_enabled) {
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ LoadLogFonts();
+ FreeMsgLogBitmaps();
+ LoadMsgLogBitmaps();
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 0, &lf, NULL, CHAT_FONTMODULE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)), hFont, TRUE);
+ DeleteObject(hFont);
+ g_Settings.LogTextIndent = iText;
+ g_Settings.LogTextIndent = g_Settings.LogTextIndent * 12 / 10;
+ g_Settings.LogIndentEnabled = (M->GetByte("Chat", "LogIndentEnabled", 1) != 0) ? TRUE : FALSE;
+
+ LoadGlobalSettings();
+ MM_FontsChanged();
+ MM_FixColors();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ }
+
+ PluginConfig.reloadSettings();
+ CacheMsgLogIcons();
+ CacheLogFonts();
+ return TRUE;
+ }
+ break;
+ case WM_TIMER:
+ if(IsWindow(hPathTip))
+ KillTimer(hPathTip, 4); // It will prevent tooltip autoclosing
+ break;
+ case WM_DESTROY:
+ if (hPathTip)
+ {
+ KillTimer(hwndDlg, 0);
+ DestroyWindow(hPathTip);
+ hPathTip = 0;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+#define NR_GC_EVENTS 12
+
+static UINT _eventorder[] = { GC_EVENT_ACTION,
+ GC_EVENT_MESSAGE,
+ GC_EVENT_NICK,
+ GC_EVENT_JOIN,
+ GC_EVENT_PART,
+ GC_EVENT_TOPIC,
+ GC_EVENT_ADDSTATUS,
+ GC_EVENT_INFORMATION,
+ GC_EVENT_QUIT,
+ GC_EVENT_KICK,
+ GC_EVENT_NOTICE,
+ GC_EVENT_HIGHLIGHT,
+ 0
+};
+
+#define GC_EVENT_ALL (GC_EVENT_ACTION | GC_EVENT_MESSAGE | GC_EVENT_NICK | GC_EVENT_JOIN | \
+ GC_EVENT_PART | GC_EVENT_TOPIC | GC_EVENT_ADDSTATUS | GC_EVENT_INFORMATION | GC_EVENT_QUIT | \
+ GC_EVENT_KICK | GC_EVENT_NOTICE)
+
+/**
+ * Dialog procedure for group chat options tab #3 (event filter configuration)
+ *
+ * @return
+ */
+INT_PTR CALLBACK DlgProcOptions3(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_INITDIALOG: {
+
+ TranslateDialogDefault(hwndDlg);
+
+ if (PluginConfig.m_chat_enabled) {
+ DWORD dwFilterFlags = M->GetDword("Chat", "FilterFlags", GC_EVENT_ALL);
+ DWORD dwTrayFlags = M->GetDword("Chat", "TrayIconFlags", GC_EVENT_ALL);
+ DWORD dwPopupFlags = M->GetDword("Chat", "PopupFlags", GC_EVENT_ALL);
+ DWORD dwLogFlags = M->GetDword("Chat", "DiskLogFlags", GC_EVENT_ALL);
+
+ for(int i = 0; _eventorder[i]; i++) {
+ if(_eventorder[i] != GC_EVENT_HIGHLIGHT) {
+ CheckDlgButton(hwndDlg, IDC_1 + i, dwFilterFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_L1 + i, dwLogFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED);
+ }
+ CheckDlgButton(hwndDlg, IDC_P1 + i, dwPopupFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_T1 + i, dwTrayFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)CTranslator::getOpt(CTranslator::OPT_MUC_NOMARKERS));
+ SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)CTranslator::getOpt(CTranslator::OPT_MUC_ASICONS));
+ SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)CTranslator::getOpt(CTranslator::OPT_MUC_ASSYMBOLS));
+
+ SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_SETCURSEL, (g_Settings.LogSymbols ? 2 : (g_Settings.dwIconFlags ? 1 : 0)), 0);
+
+ CheckDlgButton(hwndDlg, IDC_NOPOPUPSFORCLOSEDWINDOWS, M->GetByte("Chat", "SkipWhenNoWindow", 0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_TRAYONLYFORINACTIVE, M->GetByte("Chat", "TrayIconInactiveOnly", 0) ? BST_CHECKED : BST_UNCHECKED);
+ }
+ break;
+ }
+ case WM_COMMAND:
+ if (lParam != (LPARAM)NULL)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY: {
+ DWORD dwFilterFlags = 0, dwTrayFlags = 0,
+ dwPopupFlags = 0, dwLogFlags = 0;
+
+ for(int i = 0; _eventorder[i]; i++) {
+ if(_eventorder[i] != GC_EVENT_HIGHLIGHT) {
+ dwFilterFlags |= (IsDlgButtonChecked(hwndDlg, IDC_1 + i) ? _eventorder[i] : 0);
+ dwLogFlags |= (IsDlgButtonChecked(hwndDlg, IDC_L1 + i) ? _eventorder[i] : 0);
+ }
+ dwPopupFlags |= (IsDlgButtonChecked(hwndDlg, IDC_P1 + i) ? _eventorder[i] : 0);
+ dwTrayFlags |= (IsDlgButtonChecked(hwndDlg, IDC_T1 + i) ? _eventorder[i] : 0);
+ }
+ M->WriteDword("Chat", "FilterFlags", dwFilterFlags);
+ M->WriteDword("Chat", "PopupFlags", dwPopupFlags);
+ M->WriteDword("Chat", "TrayIconFlags", dwTrayFlags);
+ M->WriteDword("Chat", "DiskLogFlags", dwLogFlags);
+
+ LRESULT lr = SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_GETCURSEL, 0, 0);
+
+ M->WriteDword("Chat", "IconFlags", lr == 1 ? 1 : 0);
+ M->WriteByte("Chat", "LogSymbols", lr == 2 ? 1 : 0);
+
+ M->WriteByte("Chat", "SkipWhenNoWindow", IsDlgButtonChecked(hwndDlg, IDC_NOPOPUPSFORCLOSEDWINDOWS) ? 1 : 0);
+ M->WriteByte("Chat", "TrayIconInactiveOnly", IsDlgButtonChecked(hwndDlg, IDC_TRAYONLYFORINACTIVE) ? 1 : 0);
+ LoadGlobalSettings();
+ MM_FontsChanged();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ SM_ReconfigureFilters();
+ break;
+ }
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ break;
+
+ }
+ return FALSE;
+}
+
+void LoadGlobalSettings(void)
+{
+ LOGFONT lf;
+ int i;
+ char szBuf[40];
+
+ g_Settings.LogLimitNames = M->GetByte("Chat", "LogLimitNames", 1);
+ g_Settings.ShowTime = M->GetByte("Chat", "ShowTimeStamp", 1);
+ g_Settings.ShowTimeIfChanged = (BOOL)M->GetByte("Chat", "ShowTimeStampIfChanged", 0);
+ g_Settings.TimeStampEventColour = (BOOL)M->GetByte("Chat", "TimeStampEventColour", 0);
+ g_Settings.iEventLimit = DBGetContactSettingWord(NULL, "Chat", "LogLimit", 100);
+ g_Settings.iEventLimitThreshold = DBGetContactSettingWord(NULL, "Chat", "LogLimitThreshold", 20);
+ g_Settings.dwIconFlags = M->GetDword("Chat", "IconFlags", 0x0000);
+ g_Settings.LoggingLimit = (size_t)DBGetContactSettingWord(NULL, "Chat", "LoggingLimit", 100);
+ g_Settings.LoggingEnabled = (BOOL)M->GetByte("Chat", "LoggingEnabled", 0);
+ g_Settings.OpenInDefault = (BOOL)M->GetByte("Chat", "DefaultContainer", 1);
+ g_Settings.FlashWindow = (BOOL)M->GetByte("Chat", "FlashWindow", 0);
+ g_Settings.FlashWindowHightlight = (BOOL)M->GetByte("Chat", "FlashWindowHighlight", 0);
+ g_Settings.HighlightEnabled = (BOOL)M->GetByte("Chat", "HighlightEnabled", 1);
+ g_Settings.crUserListColor = (BOOL)M->GetDword(CHAT_FONTMODULE, "Font18Col", RGB(0, 0, 0));
+ g_Settings.crUserListBGColor = (BOOL)M->GetDword("Chat", "ColorNicklistBG", SRMSGDEFSET_BKGCOLOUR);
+ g_Settings.crUserListHeadingsColor = (BOOL)M->GetDword(CHAT_FONTMODULE, "Font19Col", RGB(170, 170, 170));
+ g_Settings.StripFormat = (BOOL)M->GetByte("Chat", "StripFormatting", 0);
+ g_Settings.TrayIconInactiveOnly = (BOOL)M->GetByte("Chat", "TrayIconInactiveOnly", 1);
+ g_Settings.BBCodeInPopups = (BOOL)M->GetByte("Chat", "BBCodeInPopups", 0);
+ g_Settings.AddColonToAutoComplete = (BOOL)M->GetByte("Chat", "AddColonToAutoComplete", 1);
+ g_Settings.iPopupStyle = M->GetByte("Chat", "PopupStyle", 1);
+ g_Settings.iPopupTimeout = DBGetContactSettingWord(NULL, "Chat", "PopupTimeout", 3);
+ g_Settings.crPUBkgColour = M->GetDword("Chat", "PopupColorBG", GetSysColor(COLOR_WINDOW));
+ g_Settings.crPUTextColour = M->GetDword("Chat", "PopupColorText", 0);
+ g_Settings.ClassicIndicators = M->GetByte("Chat", "ClassicIndicators", 0);
+ //MAD
+ g_Settings.LogClassicIndicators = M->GetByte("Chat", "LogClassicIndicators", 0);
+ g_Settings.AlternativeSorting = M->GetByte("Chat", "AlternativeSorting", 1);
+ g_Settings.AnnoyingHighlight = M->GetByte("Chat", "AnnoyingHighlight", 0);
+ g_Settings.CreateWindowOnHighlight = M->GetByte("Chat", "CreateWindowOnHighlight", 1);
+ //MAD_
+ g_Settings.LogSymbols = M->GetByte("Chat", "LogSymbols", 1);
+ g_Settings.ClickableNicks = M->GetByte("Chat", "ClickableNicks", 1);
+ g_Settings.ColorizeNicks = M->GetByte("Chat", "ColorizeNicks", 1);
+ g_Settings.ColorizeNicksInLog = M->GetByte("Chat", "ColorizeNicksInLog", 1);
+ g_Settings.ScaleIcons = M->GetByte("Chat", "ScaleIcons", 1);
+ g_Settings.UseDividers = M->GetByte("Chat", "UseDividers", 1);
+ g_Settings.DividersUsePopupConfig = M->GetByte("Chat", "DividersUsePopupConfig", 1);
+ g_Settings.MathMod = ServiceExists(MATH_RTF_REPLACE_FORMULAE) && M->GetByte("Chat", "MathModSupport", 0);
+
+ g_Settings.DoubleClick4Privat = (BOOL)M->GetByte("Chat", "DoubleClick4Privat", 0);
+ g_Settings.ShowContactStatus = M->GetByte("Chat", "ShowContactStatus", 1);
+ g_Settings.ContactStatusFirst = M->GetByte("Chat", "ContactStatusFirst", 0);
+
+
+ if (hListBkgBrush)
+ DeleteObject(hListBkgBrush);
+ hListBkgBrush = CreateSolidBrush(M->GetDword("Chat", "ColorNicklistBG", SRMSGDEFSET_BKGCOLOUR));
+
+ InitSetting(&g_Settings.pszTimeStamp, "HeaderTime", _T("[%H:%M]"));
+ InitSetting(&g_Settings.pszTimeStampLog, "LogTimestamp", _T("[%d %b %y %H:%M]"));
+ InitSetting(&g_Settings.pszIncomingNick, "HeaderIncoming", _T("%n:"));
+ InitSetting(&g_Settings.pszOutgoingNick, "HeaderOutgoing", _T("%n:"));
+
+ DBVARIANT dbv;
+
+ if (!M->GetTString(NULL, "Chat", "LogDirectory", &dbv)) {
+ lstrcpyn(g_Settings.pszLogDir, dbv.ptszVal, MAX_PATH);
+ DBFreeVariant(&dbv);
+ } else
+ lstrcpyn(g_Settings.pszLogDir, DEFLOGFILENAME, MAX_PATH);
+
+ g_Settings.pszLogDir[MAX_PATH - 1] = 0;
+
+ g_Settings.LogIndentEnabled = (M->GetByte("Chat", "LogIndentEnabled", 1) != 0) ? TRUE : FALSE;
+
+
+ // nicklist
+
+ if(g_Settings.UserListFont) {
+ DeleteObject(g_Settings.UserListFont);
+ DeleteObject(g_Settings.UserListHeadingsFont);
+ }
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 18, &lf, NULL, CHAT_FONTMODULE);
+ g_Settings.UserListFont = CreateFontIndirect(&lf);
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 19, &lf, NULL, CHAT_FONTMODULE);
+ g_Settings.UserListHeadingsFont = CreateFontIndirect(&lf);
+
+ int ih;
+ int ih2;
+
+ ih = GetTextPixelSize(_T("AQGglo"), g_Settings.UserListFont, FALSE);
+ ih2 = GetTextPixelSize(_T("AQGglo"), g_Settings.UserListHeadingsFont, FALSE);
+ g_Settings.iNickListFontHeight = max(M->GetByte("Chat", "NicklistRowDist", 12), (ih > ih2 ? ih : ih2));
+
+ for (i = 0; i < 7; i++) {
+ mir_snprintf(szBuf, 20, "NickColor%d", i);
+ g_Settings.nickColors[i] = M->GetDword("Chat", szBuf, g_Settings.crUserListColor);
+ }
+ g_Settings.nickColors[5] = M->GetDword("Chat", "NickColor5", GetSysColor(COLOR_HIGHLIGHT));
+ g_Settings.nickColors[6] = M->GetDword("Chat", "NickColor6", GetSysColor(COLOR_HIGHLIGHTTEXT));
+ if (g_Settings.SelectionBGBrush)
+ DeleteObject(g_Settings.SelectionBGBrush);
+ g_Settings.SelectionBGBrush = CreateSolidBrush(g_Settings.nickColors[5]);
+}
+
+static void FreeGlobalSettings(void)
+{
+ mir_free(g_Settings.pszTimeStamp);
+ mir_free(g_Settings.pszTimeStampLog);
+ mir_free(g_Settings.pszIncomingNick);
+ mir_free(g_Settings.pszOutgoingNick);
+ if(g_Settings.UserListFont) {
+ DeleteObject(g_Settings.UserListFont);
+ DeleteObject(g_Settings.UserListHeadingsFont);
+ }
+ if (g_Settings.SelectionBGBrush)
+ DeleteObject(g_Settings.SelectionBGBrush);
+
+ delete g_Settings.Highlight;
+}
+
+int OptionsInit(void)
+{
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ LoadLogFonts();
+ LoadMsgDlgFont(FONTSECTION_CHAT, 17, &lf, NULL, CHAT_FONTMODULE);
+ lstrcpy(lf.lfFaceName, _T("MS Shell Dlg"));
+ lf.lfUnderline = lf.lfItalic = lf.lfStrikeOut = 0;
+ lf.lfHeight = -17;
+ lf.lfWeight = FW_BOLD;
+ ZeroMemory(&g_Settings, sizeof(TMUCSettings));
+ g_Settings.NameFont = CreateFontIndirect(&lf);
+ g_Settings.iSplitterX = DBGetContactSettingWord(NULL, "Chat", "SplitterX", 105);
+ if(g_Settings.iSplitterX <= 50)
+ g_Settings.iSplitterX = 105;
+ g_Settings.iSplitterY = DBGetContactSettingWord(NULL, "Chat", "splitY", 50);
+ if(g_Settings.iSplitterY <= 20)
+ g_Settings.iSplitterY = 50;
+ g_Settings.hGroup = 0;
+ LoadGlobalSettings();
+ g_Settings.Highlight = new CMUCHighlight();
+ SkinAddNewSoundEx("ChatMessage", "Group chats", "Incoming message");
+ SkinAddNewSoundEx("ChatSent", "Group chats", "Outgoing message");
+ SkinAddNewSoundEx("ChatHighlight", "Group chats", "Message is highlighted");
+ SkinAddNewSoundEx("ChatAction", "Group chats", "User has performed an action");
+ SkinAddNewSoundEx("ChatJoin", "Group chats", "User has joined");
+ SkinAddNewSoundEx("ChatPart", "Group chats", "User has left");
+ SkinAddNewSoundEx("ChatKick", "Group chats", "User has kicked some other user");
+ SkinAddNewSoundEx("ChatMode", "Group chats", "User's status was changed");
+ SkinAddNewSoundEx("ChatNick", "Group chats", "User has changed name");
+ SkinAddNewSoundEx("ChatNotice", "Group chats", "User has sent a notice");
+ SkinAddNewSoundEx("ChatQuit", "Group chats", "User has disconnected");
+ SkinAddNewSoundEx("ChatTopic", "Group chats", "The topic has been changed");
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 0, &lf, NULL, CHAT_FONTMODULE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)), hFont, TRUE);
+ DeleteObject(hFont);
+ g_Settings.LogTextIndent = iText;
+ g_Settings.LogTextIndent = g_Settings.LogTextIndent * 12 / 10;
+ return 0;
+}
+
+
+int OptionsUnInit(void)
+{
+ FreeGlobalSettings();
+ UnhookEvent(g_hOptions);
+ DeleteObject(hListBkgBrush);
+ DeleteObject(g_Settings.NameFont);
+ return 0;
+}
diff --git a/plugins/TabSRMM/chat/services.cpp b/plugins/TabSRMM/chat/services.cpp
new file mode 100644
index 0000000000..e165763861
--- /dev/null
+++ b/plugins/TabSRMM/chat/services.cpp
@@ -0,0 +1,909 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: services.cpp 13046 2010-10-28 10:02:50Z silvercircle $
+ *
+ * This implements the services that form the group chat API
+ *
+ */
+
+#include "../src/commonheaders.h"
+
+// defs
+extern HICON hIcons[30];
+
+HANDLE hSendEvent;
+HANDLE hBuildMenuEvent;
+HANDLE hJoinMenuItem, hLeaveMenuItem;
+HANDLE g_hHookPrebuildMenu;
+CRITICAL_SECTION cs;
+
+static HANDLE hServiceRegister = NULL,
+ hServiceNewChat = NULL,
+ hServiceAddEvent = NULL,
+ hServiceGetAddEventPtr = NULL,
+ hServiceGetInfo = NULL,
+ hServiceGetCount = NULL,
+ hEventPrebuildMenu = NULL,
+ hEventDoubleclicked = NULL,
+ hEventJoinChat = NULL,
+ hEventLeaveChat = NULL;
+
+#ifdef _WIN64
+
+#define SIZEOF_STRUCT_GCREGISTER_V1 40
+#define SIZEOF_STRUCT_GCWINDOW_V1 48
+#define SIZEOF_STRUCT_GCEVENT_V1 76
+#define SIZEOF_STRUCT_GCEVENT_V2 80
+
+#else
+
+#define SIZEOF_STRUCT_GCREGISTER_V1 28
+#define SIZEOF_STRUCT_GCWINDOW_V1 32
+#define SIZEOF_STRUCT_GCEVENT_V1 44
+#define SIZEOF_STRUCT_GCEVENT_V2 48
+
+#endif
+
+int Chat_ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ if (!PluginConfig.m_chat_enabled)
+ return 0;
+
+ char * mods[3] = {"Chat", CHAT_FONTMODULE};
+ CallService("DBEditorpp/RegisterModule", (WPARAM)mods, (LPARAM)2);
+
+ LoadIcons();
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.position = -2000090001;
+ mi.flags = CMIF_DEFAULT | CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle( SKINICON_CHAT_JOIN );
+ mi.pszName = LPGEN("&Join");
+ mi.pszService = "GChat/JoinChat";
+ hJoinMenuItem = ( HANDLE )CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
+
+ mi.position = -2000090000;
+ mi.flags = CMIF_NOTOFFLINE | CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle( SKINICON_CHAT_LEAVE );
+ mi.pszName = LPGEN("&Leave");
+ mi.pszService = "GChat/LeaveChat";
+ hLeaveMenuItem = ( HANDLE )CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
+
+ CList_SetAllOffline(TRUE, NULL);
+
+ g_Settings.MathMod = ServiceExists(MATH_RTF_REPLACE_FORMULAE) && M->GetByte("Chat", "MathModSupport", 0);
+ return 0;
+}
+
+int Chat_PreShutdown()
+{
+ SM_RemoveAll();
+ MM_RemoveAll();
+ return 0;
+}
+
+int Chat_IconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ FreeMsgLogBitmaps();
+
+ LoadLogIcons();
+ LoadMsgLogBitmaps();
+ //MM_IconsChanged();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, FALSE);
+ return 0;
+}
+
+INT_PTR Service_GetCount(WPARAM wParam, LPARAM lParam)
+{
+ int i;
+
+ if (!lParam)
+ return -1;
+
+ EnterCriticalSection(&cs);
+
+ i = SM_GetCount((char *)lParam);
+
+ LeaveCriticalSection(&cs);
+ return i;
+}
+
+INT_PTR Service_GetInfo(WPARAM wParam, LPARAM lParam)
+{
+ GC_INFO * gci = (GC_INFO *) lParam;
+ SESSION_INFO* si = NULL;
+
+ if (!gci || !gci->pszModule)
+ return 1;
+
+ EnterCriticalSection(&cs);
+
+ if (gci->Flags&BYINDEX)
+ si = SM_FindSessionByIndex(gci->pszModule, gci->iItem);
+ else
+ si = SM_FindSession(gci->pszID, gci->pszModule);
+
+ if (si) {
+ if (gci->Flags & DATA) gci->dwItemData = si->dwItemData;
+ if (gci->Flags & HCONTACT) gci->hContact = si->hContact;
+ if (gci->Flags & TYPE) gci->iType = si->iType;
+ if (gci->Flags & COUNT) gci->iCount = si->nUsersInNicklist;
+ if (gci->Flags & USERS) gci->pszUsers = SM_GetUsers(si);
+
+ if (si->dwFlags & GC_UNICODE) {
+ if (gci->Flags & ID) gci->pszID = si->ptszID;
+ if (gci->Flags & NAME) gci->pszName = si->ptszName;
+ }
+ else {
+ if (gci->Flags & ID) gci->pszID = (TCHAR*)si->pszID;
+ if (gci->Flags & NAME) gci->pszName = (TCHAR*)si->pszName;
+ }
+ LeaveCriticalSection(&cs);
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return 1;
+}
+
+INT_PTR Service_Register(WPARAM wParam, LPARAM lParam)
+{
+
+ GCREGISTER *gcr = (GCREGISTER *)lParam;
+ MODULEINFO * mi = NULL;
+ if (gcr == NULL)
+ return GC_REGISTER_ERROR;
+
+ if (gcr->cbSize != SIZEOF_STRUCT_GCREGISTER_V1)
+ return GC_REGISTER_WRONGVER;
+
+ EnterCriticalSection(&cs);
+
+ mi = MM_AddModule(gcr->pszModule);
+ if (mi) {
+ mi->ptszModDispName = a2tf( gcr->ptszModuleDispName, gcr->dwFlags, 0);
+ mi->bBold = gcr->dwFlags & GC_BOLD;
+ mi->bUnderline = gcr->dwFlags & GC_UNDERLINE ;
+ mi->bItalics = gcr->dwFlags & GC_ITALICS ;
+ mi->bColor = gcr->dwFlags & GC_COLOR ;
+ mi->bBkgColor = gcr->dwFlags & GC_BKGCOLOR ;
+ mi->bAckMsg = gcr->dwFlags & GC_ACKMSG ;
+ mi->bChanMgr = gcr->dwFlags & GC_CHANMGR ;
+ mi->iMaxText = gcr->iMaxText;
+ mi->nColorCount = gcr->nColors;
+ if (gcr->nColors > 0) {
+ mi->crColors = (COLORREF *)mir_alloc(sizeof(COLORREF) * gcr->nColors);
+ memcpy(mi->crColors, gcr->pColors, sizeof(COLORREF) * gcr->nColors);
+ }
+ mi->pszHeader = 0;
+
+ CheckColorsInModule((char*)gcr->pszModule);
+ CList_SetAllOffline(TRUE, gcr->pszModule);
+
+ LeaveCriticalSection(&cs);
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return GC_REGISTER_ERROR;
+}
+
+INT_PTR Service_NewChat(WPARAM wParam, LPARAM lParam)
+{
+ MODULEINFO* mi;
+ GCSESSION *gcw = (GCSESSION *)lParam;
+ if (gcw == NULL)
+ return GC_NEWSESSION_ERROR;
+
+ if (gcw->cbSize != SIZEOF_STRUCT_GCWINDOW_V1)
+ return GC_NEWSESSION_WRONGVER;
+
+ EnterCriticalSection(&cs);
+
+ if ((mi = MM_FindModule(gcw->pszModule)) != NULL) {
+ TCHAR* ptszID = a2tf(gcw->ptszID, gcw->dwFlags, 0);
+ SESSION_INFO* si = SM_AddSession(ptszID, gcw->pszModule);
+
+ // create a new session and set the defaults
+ if (si != NULL) {
+ TCHAR szTemp[256];
+
+ si->dwItemData = gcw->dwItemData;
+ if (gcw->iType != GCW_SERVER)
+ si->wStatus = ID_STATUS_ONLINE;
+ si->iType = gcw->iType;
+ si->dwFlags = gcw->dwFlags;
+ si->ptszName = a2tf(gcw->ptszName, gcw->dwFlags, 0);
+ si->ptszStatusbarText = a2tf(gcw->ptszStatusbarText, gcw->dwFlags, 0);
+ si->iSplitterX = g_Settings.iSplitterX;
+ si->bFilterEnabled = M->GetByte(si->hContact, "Chat", "FilterEnabled", M->GetByte("Chat", "FilterEnabled", 0));
+ si->bNicklistEnabled = M->GetByte("Chat", "ShowNicklist", 1);
+ if (!(gcw->dwFlags & GC_UNICODE)) {
+ si->pszID = mir_strdup(gcw->pszID);
+ si->pszName = mir_strdup(gcw->pszName);
+ }
+
+ if (mi->bColor) {
+ si->iFG = 4;
+ si->bFGSet = TRUE;
+ }
+ if (mi->bBkgColor) {
+ si->iBG = 2;
+ si->bBGSet = TRUE;
+ }
+ if (si->iType == GCW_SERVER)
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("Server: %s"), si->ptszName);
+ else
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), si->ptszName);
+ si->hContact = CList_AddRoom(gcw->pszModule, ptszID, szTemp, si->iType);
+ DBWriteContactSettingString(si->hContact, si->pszModule , "Topic", "");
+ DBDeleteContactSetting(si->hContact, "CList", "StatusMsg");
+ if (si->ptszStatusbarText)
+ M->WriteTString(si->hContact, si->pszModule, "StatusBar", si->ptszStatusbarText);
+ else
+ DBWriteContactSettingString(si->hContact, si->pszModule, "StatusBar", "");
+ if (si->hContact)
+ Chat_SetFilters(si);
+ } else {
+ SESSION_INFO* si2 = SM_FindSession(ptszID, gcw->pszModule);
+ if (si2) {
+
+ UM_RemoveAll(&si2->pUsers);
+ TM_RemoveAll(&si2->pStatuses);
+
+ si2->iStatusCount = 0;
+ si2->nUsersInNicklist = 0;
+
+ if (si2->hContact)
+ Chat_SetFilters(si2);
+ if (si2->hWnd)
+ RedrawWindow(GetDlgItem(si2->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE);
+ }
+ }
+
+ LeaveCriticalSection(&cs);
+ mir_free(ptszID);
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return GC_NEWSESSION_ERROR;
+}
+
+static int DoControl(GCEVENT * gce, WPARAM wp)
+{
+ if (gce->pDest->iType == GC_EVENT_CONTROL) {
+ switch (wp) {
+ case WINDOW_HIDDEN:
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ si->bInitDone = TRUE;
+ SetActiveSession(si->ptszID, si->pszModule);
+ if (si->hWnd)
+ ShowRoom(si, wp, FALSE);
+ }
+ }
+ return 0;
+
+ case WINDOW_MINIMIZE:
+ case WINDOW_MAXIMIZE:
+ case WINDOW_VISIBLE:
+ case SESSION_INITDONE:
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ si->bInitDone = TRUE;
+ if (wp != SESSION_INITDONE || M->GetByte("Chat", "PopupOnJoin", 0) == 0)
+ ShowRoom(si, wp, TRUE);
+ return 0;
+ } }
+ break;
+
+ case SESSION_OFFLINE:
+ SM_SetOffline(gce->pDest->ptszID, gce->pDest->pszModule);
+ // fall through
+
+ case SESSION_ONLINE:
+ SM_SetStatus(gce->pDest->ptszID, gce->pDest->pszModule, wp == SESSION_ONLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
+ break;
+
+ case WINDOW_CLEARLOG:
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ LM_RemoveAll(&si->pLog, &si->pLogEnd);
+ si->iEventCount = 0;
+ si->LastTime = 0;
+ }
+ break;
+ }
+ case SESSION_TERMINATE:
+ return SM_RemoveSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ }
+ SM_SendMessage(gce->pDest->ptszID, gce->pDest->pszModule, GC_EVENT_CONTROL + WM_USER + 500, wp, 0);
+ }
+
+ else if (gce->pDest->iType == GC_EVENT_CHUID && gce->pszText)
+ {
+ SM_ChangeUID(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszNick, gce->ptszText);
+ }
+
+ else if (gce->pDest->iType == GC_EVENT_CHANGESESSIONAME && gce->pszText)
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ replaceStr(&si->ptszName, gce->ptszText);
+ if (si->hWnd)
+ SendMessage(si->hWnd, GC_UPDATETITLE, 0, 0);
+ }
+ }
+
+ else if (gce->pDest->iType == GC_EVENT_SETITEMDATA) {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si)
+ si->dwItemData = gce->dwItemData;
+ }
+
+ else if (gce->pDest->iType == GC_EVENT_GETITEMDATA) {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ gce->dwItemData = si->dwItemData;
+ return si->dwItemData;
+ }
+ return 0;
+ }
+ else if (gce->pDest->iType == GC_EVENT_SETSBTEXT)
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ replaceStr(&si->ptszStatusbarText, gce->ptszText);
+ if (si->ptszStatusbarText)
+ M->WriteTString(si->hContact, si->pszModule, "StatusBar", si->ptszStatusbarText);
+ else
+ DBWriteContactSettingString(si->hContact, si->pszModule, "StatusBar", "");
+ if (si->hWnd) {
+ SendMessage(si->hWnd, GC_UPDATESTATUSBAR, 0, 0);
+ }
+ }
+ }
+ else if (gce->pDest->iType == GC_EVENT_ACK)
+ {
+ SM_SendMessage(gce->pDest->ptszID, gce->pDest->pszModule, GC_ACKMESSAGE, 0, 0);
+ }
+ else if (gce->pDest->iType == GC_EVENT_SENDMESSAGE && gce->pszText)
+ {
+ SM_SendUserMessage(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszText);
+ }
+ else if (gce->pDest->iType == GC_EVENT_SETSTATUSEX)
+ {
+ SM_SetStatusEx(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszText, gce->dwItemData);
+ }
+ else return 1;
+
+ return 0;
+}
+
+static void AddUser(GCEVENT * gce)
+{
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ WORD status = TM_StringToWord(si->pStatuses, gce->ptszStatus);
+ USERINFO * ui = SM_AddUser(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszNick, status);
+ if (ui) {
+ ui->pszNick = mir_tstrdup(gce->ptszNick);
+
+ if (gce->bIsMe)
+ si->pMe = ui;
+
+ ui->Status = status;
+ ui->Status |= si->pStatuses->Status;
+
+ if (si->hWnd) {
+ SendMessage(si->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ if(si->dat)
+ GetMyNick(si->dat);
+ }
+ }
+ }
+}
+
+HWND CreateNewRoom(TContainerData *pContainer, SESSION_INFO *si, BOOL bActivateTab, BOOL bPopupContainer, BOOL bWantPopup)
+{
+ TCHAR *contactName = NULL, newcontactname[128];
+ char *szProto, *szStatus;
+ WORD wStatus;
+ int newItem;
+ HWND hwndNew = 0;
+ struct TNewWindowData newData = {
+ 0
+ };
+ HANDLE hContact = si->hContact;
+ HWND hwndTab;
+
+ if (M->FindWindow(hContact) != 0)
+ return 0;
+ if (hContact != 0 && M->GetByte("limittabs", 0) && !_tcsncmp(pContainer->szName, _T("default"), 6)) {
+ if ((pContainer = FindMatchingContainer(_T("default"), hContact)) == NULL) {
+ TCHAR szName[CONTAINER_NAMELEN + 1];
+
+ _sntprintf(szName, CONTAINER_NAMELEN, _T("default"));
+ pContainer = CreateContainer(szName, CNT_CREATEFLAG_CLONED, hContact);
+ }
+ }
+ newData.hContact = hContact;
+ newData.isWchar = 0;
+ newData.szInitialText = NULL;
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) newData.hContact, 0);
+
+ ZeroMemory((void *)&newData.item, sizeof(newData.item));
+
+ contactName = (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) newData.hContact, GCDNF_TCHAR);
+
+ /*
+ * cut nickname if larger than x chars...
+ */
+
+ if (contactName && lstrlen(contactName) > 0) {
+ if (M->GetByte("cuttitle", 0))
+ CutContactName(contactName, newcontactname, safe_sizeof(newcontactname));
+ else {
+ lstrcpyn(newcontactname, contactName, safe_sizeof(newcontactname));
+ newcontactname[127] = 0;
+ }
+ } else
+ lstrcpyn(newcontactname, _T("_U_"), sizeof(newcontactname) / sizeof(TCHAR));
+
+ wStatus = szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord((HANDLE) newData.hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ szStatus = (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord((HANDLE)newData.hContact, szProto, "Status", ID_STATUS_OFFLINE), 0);
+
+ newData.item.pszText = newcontactname;
+
+ newData.item.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
+ newData.item.iImage = 0;
+
+ hwndTab = GetDlgItem(pContainer->hwnd, 1159);
+
+ // hide the active tab
+ if (pContainer->hwndActive && bActivateTab)
+ ShowWindow(pContainer->hwndActive, SW_HIDE);
+
+ {
+ int iTabIndex_wanted = M->GetDword(hContact, "tabindex", pContainer->iChilds * 100);
+ int iCount = TabCtrl_GetItemCount(hwndTab);
+ TCITEM item = {0};
+ HWND hwnd;
+ struct TWindowData *dat;
+ int relPos;
+ int i;
+
+ pContainer->iTabIndex = iCount;
+ if (iCount > 0) {
+ for (i = iCount - 1; i >= 0; i--) {
+ item.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, i, &item);
+ hwnd = (HWND)item.lParam;
+ dat = (struct TWindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (dat) {
+ relPos = M->GetDword(dat->hContact, "tabindex", i * 100);
+ if (iTabIndex_wanted <= relPos)
+ pContainer->iTabIndex = i;
+ }
+ }
+ }
+ }
+
+ newItem = TabCtrl_InsertItem(hwndTab, pContainer->iTabIndex, &newData.item);
+ SendMessage(hwndTab, EM_REFRESHWITHOUTCLIP, 0, 0);
+ if (bActivateTab)
+ TabCtrl_SetCurSel(hwndTab, newItem);
+ newData.iTabID = newItem;
+ newData.iTabImage = newData.item.iImage;
+ newData.pContainer = pContainer;
+ newData.iActivate = (int) bActivateTab;
+ pContainer->iChilds++;
+ newData.bWantPopup = bWantPopup;
+ newData.hdbEvent = (HANDLE)si;
+ hwndNew = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CHANNEL), GetDlgItem(pContainer->hwnd, 1159), RoomWndProc, (LPARAM) & newData);
+ if(pContainer->dwFlags & CNT_SIDEBAR) {
+ TWindowData *dat = (TWindowData *)GetWindowLongPtr(hwndNew, GWLP_USERDATA);
+ if(dat)
+ pContainer->SideBar->addSession(dat, pContainer->iTabIndex);
+ }
+ SendMessage(pContainer->hwnd, WM_SIZE, 0, 0);
+ // if the container is minimized, then pop it up...
+ if (IsIconic(pContainer->hwnd)) {
+ if (bPopupContainer) {
+ SendMessage(pContainer->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+ SetFocus(pContainer->hwndActive);
+ } else {
+ if (pContainer->dwFlags & CNT_NOFLASH)
+ SendMessage(pContainer->hwnd, DM_SETICON, 0, (LPARAM)LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+ else
+ FlashContainer(pContainer, 1, 0);
+ }
+ }
+ if (bActivateTab) {
+ if (PluginConfig.m_HideOnClose && !IsWindowVisible(pContainer->hwnd)){
+ WINDOWPLACEMENT wp={0};
+ wp.length = sizeof(wp);
+ GetWindowPlacement(pContainer->hwnd, &wp);
+
+ BroadCastContainer(pContainer, DM_CHECKSIZE, 0, 0); // make sure all tabs will re-check layout on activation
+ if(wp.showCmd == SW_SHOWMAXIMIZED)
+ ShowWindow(pContainer->hwnd, SW_SHOWMAXIMIZED);
+ else {
+ if(bPopupContainer)
+ ShowWindow(pContainer->hwnd, SW_SHOWNORMAL);
+ else
+ ShowWindow(pContainer->hwnd, SW_SHOWMINNOACTIVE);
+ }
+ SendMessage(pContainer->hwndActive, WM_SIZE, 0, 0);
+ SetFocus(hwndNew);
+ }
+ else {
+ SetFocus(hwndNew);
+ RedrawWindow(pContainer->hwnd, NULL, NULL, RDW_INVALIDATE);
+ UpdateWindow(pContainer->hwnd);
+ if (GetForegroundWindow() != pContainer->hwnd && bPopupContainer == TRUE)
+ SetForegroundWindow(pContainer->hwnd);
+ }
+ }
+ if(PluginConfig.m_bIsWin7 && PluginConfig.m_useAeroPeek && CSkin::m_skinEnabled && !M->GetByte("forceAeroPeek", 0))
+ CWarning::show(CWarning::WARN_AEROPEEK_SKIN, CWarning::CWF_UNTRANSLATED|MB_ICONWARNING|MB_OK);
+ return hwndNew; // return handle of the new dialog
+}
+
+void ShowRoom(SESSION_INFO* si, WPARAM wp, BOOL bSetForeground)
+{
+ if (!si)
+ return;
+
+ if (si->hWnd == NULL) {
+ TCHAR szName[CONTAINER_NAMELEN + 2];
+ struct TContainerData *pContainer = si->pContainer;
+
+ szName[0] = 0;
+ if (pContainer == NULL) {
+ GetContainerNameForContact(si->hContact, szName, CONTAINER_NAMELEN);
+ if (!g_Settings.OpenInDefault && !_tcscmp(szName, _T("default")))
+ _tcsncpy(szName, _T("Chat Rooms"), CONTAINER_NAMELEN);
+ szName[CONTAINER_NAMELEN] = 0;
+ pContainer = FindContainerByName(szName);
+ }
+ if (pContainer == NULL)
+ pContainer = CreateContainer(szName, FALSE, si->hContact);
+ si->hWnd = CreateNewRoom(pContainer, si, TRUE, TRUE, FALSE);
+ } else
+ ActivateExistingTab(si->pContainer, si->hWnd);
+}
+
+INT_PTR Service_AddEvent(WPARAM wParam, LPARAM lParam)
+{
+ GCEVENT *gce = (GCEVENT*)lParam;
+ GCDEST *gcd = NULL;
+ GCEVENT save_gce;
+ GCDEST save_gcd;
+ TCHAR* pWnd = NULL;
+ char* pMod = NULL;
+ BOOL bIsHighlighted = FALSE;
+ BOOL bRemoveFlag = FALSE;
+ int iRetVal = GC_EVENT_ERROR;
+ SESSION_INFO *si = NULL;
+ BOOL fFreeText = FALSE;
+
+ if (CMimAPI::m_shutDown)
+ return 0;
+
+ if (gce == NULL)
+ return GC_EVENT_ERROR;
+
+ gcd = gce->pDest;
+ if (gcd == NULL)
+ return GC_EVENT_ERROR;
+
+ if (gce->cbSize != SIZEOF_STRUCT_GCEVENT_V1 && gce->cbSize != SIZEOF_STRUCT_GCEVENT_V2)
+ return GC_EVENT_WRONGVER;
+
+ if (!IsEventSupported(gcd->iType))
+ return GC_EVENT_ERROR;
+
+ if (!(gce->dwFlags & GC_UNICODE)) {
+ save_gce = *gce;
+ save_gcd = *gce->pDest;
+ gce->pDest->ptszID = a2tf(gce->pDest->ptszID, gce->dwFlags, 0);
+ gce->ptszUID = a2tf(gce->ptszUID, gce->dwFlags, 0);
+ gce->ptszNick = a2tf(gce->ptszNick, gce->dwFlags, 0);
+ gce->ptszStatus = a2tf(gce->ptszStatus, gce->dwFlags, 0);
+ if (gcd->iType != GC_EVENT_MESSAGE && gcd->iType != GC_EVENT_ACTION) {
+ gce->ptszText = a2tf(gce->ptszText, gce->dwFlags, 0);
+ fFreeText = TRUE;
+ }
+ gce->ptszUserInfo = a2tf(gce->ptszUserInfo, gce->dwFlags, 0);
+ }
+
+ EnterCriticalSection(&cs);
+
+ // Do different things according to type of event
+ switch (gcd->iType) {
+ case GC_EVENT_ADDGROUP:
+ {
+ STATUSINFO* si = SM_AddStatus(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszStatus);
+ if (si && gce->dwItemData)
+ si->hIcon = CopyIcon((HICON)gce->dwItemData);
+ }
+ iRetVal = 0;
+ goto LBL_Exit;
+
+ case GC_EVENT_CHUID:
+ case GC_EVENT_CHANGESESSIONAME:
+ case GC_EVENT_SETITEMDATA:
+ case GC_EVENT_GETITEMDATA:
+ case GC_EVENT_CONTROL:
+ case GC_EVENT_SETSBTEXT:
+ case GC_EVENT_ACK:
+ case GC_EVENT_SENDMESSAGE :
+ case GC_EVENT_SETSTATUSEX :
+ iRetVal = DoControl(gce, wParam);
+ goto LBL_Exit;
+
+ case GC_EVENT_SETCONTACTSTATUS:
+ iRetVal = SM_SetContactStatus(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, (WORD)gce->dwItemData);
+ goto LBL_Exit;
+
+ case GC_EVENT_TOPIC: {
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ if (gce->pszText) {
+ replaceStr(&si->ptszTopic, RemoveFormatting(gce->ptszText));
+ M->WriteTString(si->hContact, si->pszModule , "Topic", /*RemoveFormatting*/(si->ptszTopic));
+ if (M->GetByte("Chat", "TopicOnClist", 1))
+ M->WriteTString(si->hContact, "CList" , "StatusMsg", /*RemoveFormatting*/(si->ptszTopic));
+ if(si->hWnd)
+ SendMessage(si->hWnd, DM_INVALIDATEPANEL, 0, 0);
+ }
+ }
+ break;
+ }
+ case GC_EVENT_ADDSTATUS:
+ SM_GiveStatus(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszStatus);
+ if (!gce->bIsMe) {
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ }
+ break;
+
+ case GC_EVENT_REMOVESTATUS:
+ SM_TakeStatus(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszStatus);
+ if (!gce->bIsMe) {
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ }
+ break;
+
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_ACTION: {
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (!(gce->dwFlags & GC_UNICODE)) {
+ fFreeText = TRUE;
+ if (si)
+ gce->ptszText = a2tf(gce->ptszText, gce->dwFlags, M->GetDword(si->hContact, "ANSIcodepage", 0));
+ else
+ gce->ptszText = a2tf(gce->ptszText, gce->dwFlags, 0);
+ }
+ if (!gce->bIsMe && gce->pDest->pszID && gce->pszText) {
+ if (si)
+ bIsHighlighted = si->Highlight->match(gce, si, CMUCHighlight::MATCH_TEXT | CMUCHighlight::MATCH_NICKNAME);
+ }
+ }
+ break;
+
+ case GC_EVENT_NICK:
+ SM_ChangeNick(gce->pDest->ptszID, gce->pDest->pszModule, gce);
+ if (!gce->bIsMe) {
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ }
+
+ break;
+
+ case GC_EVENT_JOIN:
+ AddUser(gce);
+ if (!gce->bIsMe) {
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ }
+ break;
+
+ case GC_EVENT_PART:
+ case GC_EVENT_QUIT:
+ case GC_EVENT_KICK:
+ bRemoveFlag = TRUE;
+ if (!gce->bIsMe) {
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ }
+ break;
+ }
+
+ // Decide which window (log) should have the event
+ if (gcd->pszID) {
+ pWnd = gcd->ptszID;
+ pMod = gcd->pszModule;
+ }
+ else if ( gcd->iType == GC_EVENT_NOTICE || gcd->iType == GC_EVENT_INFORMATION ) {
+ SESSION_INFO* si = GetActiveSession();
+ if (si && !lstrcmpA(si->pszModule, gcd->pszModule)) {
+ pWnd = si->ptszID;
+ pMod = si->pszModule;
+ }
+ else {
+ iRetVal = 0;
+ goto LBL_Exit;
+ }
+ }
+ else {
+ // Send the event to all windows with a user pszUID. Used for broadcasting QUIT etc
+ SM_AddEventToAllMatchingUID(gce, bIsHighlighted);
+ if (!bRemoveFlag) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ } }
+
+ // add to log
+ if (pWnd) {
+ if (si == NULL)
+ si = SM_FindSession(pWnd, pMod);
+
+ // fix for IRC's old stuyle mode notifications. Should not affect any other protocol
+ if ((gce->pDest->iType == GC_EVENT_ADDSTATUS || gce->pDest->iType == GC_EVENT_REMOVESTATUS) && !(gce->dwFlags & GCEF_ADDTOLOG)) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ }
+
+ if (gce && gce->pDest->iType == GC_EVENT_JOIN && gce->time == 0) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ }
+
+ if (si && (si->bInitDone || gce->pDest->iType == GC_EVENT_TOPIC || (gce->pDest->iType == GC_EVENT_JOIN && gce->bIsMe))) {
+ if (SM_AddEvent(pWnd, pMod, gce, bIsHighlighted) && si->hWnd) {
+ SendMessage(si->hWnd, GC_ADDLOG, 0, 0);
+ }
+ else if (si->hWnd) {
+ SendMessage(si->hWnd, GC_REDRAWLOG2, 0, 0);
+ }
+ DoSoundsFlashPopupTrayStuff(si, gce, bIsHighlighted, 0);
+ if ((gce->dwFlags & GCEF_ADDTOLOG) && g_Settings.LoggingEnabled)
+ LogToFile(si, gce);
+ }
+
+ if (!bRemoveFlag) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ } }
+
+ if (bRemoveFlag)
+ iRetVal = (SM_RemoveUser(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID) == 0) ? 1 : 0;
+
+LBL_Exit:
+ LeaveCriticalSection(&cs);
+
+ if (!(gce->dwFlags & GC_UNICODE)) {
+ if (fFreeText)
+ mir_free((void*)gce->ptszText);
+ mir_free((void*)gce->ptszNick);
+ mir_free((void*)gce->ptszUID);
+ mir_free((void*)gce->ptszStatus);
+ mir_free((void*)gce->ptszUserInfo);
+ mir_free((void*)gce->pDest->ptszID);
+ *gce = save_gce;
+ *gce->pDest = save_gcd;
+ }
+ return iRetVal;
+}
+
+static INT_PTR Service_GetAddEventPtr(WPARAM wParam, LPARAM lParam)
+{
+ GCPTRS * gp = (GCPTRS *) lParam;
+
+ EnterCriticalSection(&cs);
+
+ gp->pfnAddEvent = Service_AddEvent;
+ LeaveCriticalSection(&cs);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Service creation
+
+void HookEvents(void)
+{
+ InitializeCriticalSection(&cs);
+ g_hHookPrebuildMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, CList_PrebuildContactMenu); // MIRANDAHOOK should return INT_PTR too
+}
+
+void UnhookEvents(void)
+{
+ UnhookEvent(g_hHookPrebuildMenu);
+ DeleteCriticalSection(&cs);
+}
+
+int CreateServiceFunctions(void)
+{
+ PluginConfig.m_chat_enabled = false;
+
+ if(ServiceExists(MS_GC_REGISTER)) {
+ LRESULT result = CWarning::show(CWarning::WARN_CHAT_ENABLED, CWarning::CWF_NOALLOWHIDE | CWarning::CWF_UNTRANSLATED | MB_YESNOCANCEL | MB_ICONQUESTION);
+ if(result == IDYES)
+ M->WriteByte("PluginDisable", "chat.dll", 1);
+ return(0);
+ }
+ PluginConfig.m_chat_enabled = true;
+
+ hServiceRegister = CreateServiceFunction(MS_GC_REGISTER, Service_Register);
+ hServiceNewChat = CreateServiceFunction(MS_GC_NEWSESSION, Service_NewChat);
+ hServiceAddEvent = CreateServiceFunction(MS_GC_EVENT, Service_AddEvent);
+ hServiceGetAddEventPtr = CreateServiceFunction(MS_GC_GETEVENTPTR, Service_GetAddEventPtr);
+ hServiceGetInfo = CreateServiceFunction(MS_GC_GETINFO, Service_GetInfo);
+ hServiceGetCount = CreateServiceFunction(MS_GC_GETSESSIONCOUNT, Service_GetCount);
+
+ hEventDoubleclicked = CreateServiceFunction("GChat/DblClickEvent", CList_EventDoubleclicked);
+ hEventPrebuildMenu = CreateServiceFunction("GChat/PrebuildMenuEvent", CList_PrebuildContactMenuSvc);
+ hEventJoinChat = CreateServiceFunction("GChat/JoinChat", CList_JoinChat);
+ hEventLeaveChat = CreateServiceFunction("GChat/LeaveChat", CList_LeaveChat);
+ return(1);
+}
+
+void DestroyServiceFunctions(void)
+{
+ DestroyServiceFunction(hServiceRegister);
+ DestroyServiceFunction(hServiceNewChat);
+ DestroyServiceFunction(hServiceAddEvent);
+ DestroyServiceFunction(hServiceGetAddEventPtr);
+ DestroyServiceFunction(hServiceGetInfo);
+ DestroyServiceFunction(hServiceGetCount);
+ DestroyServiceFunction(hEventDoubleclicked);
+ DestroyServiceFunction(hEventPrebuildMenu);
+ DestroyServiceFunction(hEventJoinChat);
+ DestroyServiceFunction(hEventLeaveChat);
+}
+
+void CreateHookableEvents(void)
+{
+ hSendEvent = CreateHookableEvent(ME_GC_EVENT);
+ hBuildMenuEvent = CreateHookableEvent(ME_GC_BUILDMENU);
+}
+
+void DestroyHookableEvents(void)
+{
+ DestroyHookableEvent(hSendEvent);
+ DestroyHookableEvent(hBuildMenuEvent);
+}
+
diff --git a/plugins/TabSRMM/chat/tools.cpp b/plugins/TabSRMM/chat/tools.cpp
new file mode 100644
index 0000000000..0726a01869
--- /dev/null
+++ b/plugins/TabSRMM/chat/tools.cpp
@@ -0,0 +1,1351 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: tools.cpp 13650 2011-05-30 11:53:13Z silvercircle@gmail.com $
+ *
+ * Helper functions for the group chat module.
+ *
+ */
+
+#include "../src/commonheaders.h"
+
+// externs
+extern HICON hIcons[30];
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+extern HMENU g_hMenu;
+extern HANDLE hBuildMenuEvent ;
+extern HANDLE hSendEvent;
+
+int GetRichTextLength(HWND hwnd)
+{
+ GETTEXTLENGTHEX gtl;
+
+ gtl.flags = GTL_PRECISE;
+ gtl.codepage = CP_ACP ;
+ return (int) SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
+}
+
+/**
+ * @param pszWord string to strip of any IRC-style
+ * formatting
+ * @param fToLower convert to lowercase
+ * @param fStripCR strip cr/lf sequences (only for highlighter, defaults to false)
+ * @param buf caller-provided buffer, use a static one
+ * when the caller does not provide a
+ * buffer
+ * caller provided buffer is NEEDED to make
+ * this thread-safe.
+ *
+ * @return TCHAR* the stripped string
+ */
+TCHAR* RemoveFormatting(const TCHAR* pszWord, bool fToLower, bool fStripCR, TCHAR* buf, const size_t len)
+{
+ static TCHAR _szTemp[20000];
+ TCHAR* szTemp = 0;
+ size_t _buflen = 0;
+
+ if(0 == buf) {
+ szTemp = _szTemp;
+ _buflen = 20000;
+ } else {
+ szTemp = buf;
+ _buflen = len;
+ szTemp[len - 1] = 0;
+ }
+
+ size_t i = 0;
+ size_t j = 0;
+
+ if (pszWord == 0)
+ return NULL;
+
+ size_t wordlen = lstrlen(pszWord);
+
+ while (j < _buflen && i <= wordlen) {
+ if (pszWord[i] == '%') {
+ switch (pszWord[i+1]) {
+ case '%':
+ szTemp[j] = '%';
+ j++;
+ i++;
+ i++;
+ break;
+ case 'b':
+ case 'u':
+ case 'i':
+ case 'B':
+ case 'U':
+ case 'I':
+ case 'r':
+ case 'C':
+ case 'F':
+ i++;
+ i++;
+ break;
+
+ case 'c':
+ case 'f':
+ i += 4;
+ break;
+
+ default:
+ szTemp[j] = pszWord[i];
+ j++;
+ i++;
+ break;
+ }
+ } else {
+ if(fStripCR) {
+ if(0x0a == pszWord[i] || 0x0c == pszWord[i]) {
+ szTemp[j++] = ' ';
+ i++;
+ continue;
+ }
+ }
+ szTemp[j] = pszWord[i];
+ j++;
+ i++;
+ }
+ }
+ if(fToLower) {
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(szTemp);
+ }
+ return(szTemp);
+}
+
+static void __stdcall ShowRoomFromPopup(void * pi)
+{
+ SESSION_INFO* si = (SESSION_INFO*) pi;
+ ShowRoom(si, WINDOW_VISIBLE, TRUE);
+}
+
+static void TSAPI Chat_OpenPopup(SESSION_INFO* si, HWND hwndPopup)
+{
+ CallFunctionAsync(ShowRoomFromPopup, si);
+ PUDeletePopUp(hwndPopup);
+}
+
+static void TSAPI Chat_DismissPopup(const SESSION_INFO* si, HWND hwndPopup)
+{
+ if (si->hContact)
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+
+ if (si->hWnd && KillTimer(si->hWnd, TIMERID_FLASHWND))
+ FlashWindow(si->hWnd, FALSE);
+
+ PUDeletePopUp(hwndPopup);
+}
+
+static INT_PTR CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case WM_COMMAND:
+ if (HIWORD(wParam) == STN_CLICKED) {
+ SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd, (LPARAM)0);;
+
+ if(si) {
+ if(nen_options.maskActL & MASK_OPEN)
+ Chat_OpenPopup(si, hWnd);
+ else
+ Chat_DismissPopup(si, hWnd);
+ }
+ return TRUE;
+ }
+ break;
+ case WM_CONTEXTMENU: {
+ SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd, (LPARAM)0);
+
+ if(si && si->hContact) {
+ if(nen_options.maskActR & MASK_OPEN)
+ Chat_OpenPopup(si, hWnd);
+ else
+ Chat_DismissPopup(si, hWnd);
+ }
+ }
+ break;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+static int ShowPopup(HANDLE hContact, SESSION_INFO* si, HICON hIcon, char* pszProtoName, TCHAR* pszRoomName, COLORREF crBkg, const TCHAR* fmt, ...)
+{
+ POPUPDATAT_V2 pd = {0};
+ va_list marker;
+ static TCHAR szBuf[4*1024];
+
+ if (!fmt || lstrlen(fmt) == 0 || lstrlen(fmt) > 2000)
+ return 0;
+
+ va_start(marker, fmt);
+ _vstprintf(szBuf, fmt, marker);
+ va_end(marker);
+
+ pd.lchContact = hContact;
+
+ if (hIcon)
+ pd.lchIcon = hIcon ;
+ else
+ pd.lchIcon = LoadIconEx(IDI_CHANMGR, "window", 0, 0);
+
+ mir_sntprintf(pd.lptzContactName, MAX_CONTACTNAME - 1, _T(TCHAR_STR_PARAM) _T(" - %s"),
+ pszProtoName, CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+ lstrcpyn(pd.lptzText, TranslateTS(szBuf), MAX_SECONDLINE - 1);
+ pd.iSeconds = g_Settings.iPopupTimeout;
+
+ if (g_Settings.iPopupStyle == 2) {
+ pd.colorBack = 0;
+ pd.colorText = 0;
+ } else if (g_Settings.iPopupStyle == 3) {
+ pd.colorBack = g_Settings.crPUBkgColour;
+ pd.colorText = g_Settings.crPUTextColour;
+ } else {
+ pd.colorBack = M->GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR_MUC, SRMSGDEFSET_BKGCOLOUR);
+ pd.colorText = crBkg;
+ }
+
+ pd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ pd.PluginData = si;
+ return PUAddPopUpT(&pd);
+}
+
+static BOOL DoTrayIcon(SESSION_INFO* si, GCEVENT * gce)
+{
+ int iEvent = gce->pDest->iType;
+
+ if (si && (iEvent & si->iLogTrayFlags)) {
+ switch (iEvent) {
+ case GC_EVENT_MESSAGE | GC_EVENT_HIGHLIGHT :
+ case GC_EVENT_ACTION | GC_EVENT_HIGHLIGHT :
+ CList_AddEvent(si->hContact, PluginConfig.g_IconMsgEvent, szChatIconString, 0,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_HILIGHT), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_MESSAGE :
+ CList_AddEvent(si->hContact, hIcons[ICON_MESSAGE], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_MSG), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_ACTION:
+ CList_AddEvent(si->hContact, hIcons[ICON_ACTION], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_MSG), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_JOIN:
+ CList_AddEvent(si->hContact, hIcons[ICON_JOIN], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_JOINED), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_PART:
+ CList_AddEvent(si->hContact, hIcons[ICON_PART], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_LEFT), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_QUIT:
+ CList_AddEvent(si->hContact, hIcons[ICON_QUIT], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_QUIT), gce->ptszNick);
+ break;
+ case GC_EVENT_NICK:
+ CList_AddEvent(si->hContact, hIcons[ICON_NICK], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_NICK), gce->ptszNick, gce->pszText);
+ break;
+ case GC_EVENT_KICK:
+ CList_AddEvent(si->hContact, hIcons[ICON_KICK], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_KICK), gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_NOTICE:
+ CList_AddEvent(si->hContact, hIcons[ICON_NOTICE], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_NOTICE), gce->ptszNick);
+ break;
+ case GC_EVENT_TOPIC:
+ CList_AddEvent(si->hContact, hIcons[ICON_TOPIC], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_TOPIC), si->ptszName);
+ break;
+ case GC_EVENT_INFORMATION:
+ CList_AddEvent(si->hContact, hIcons[ICON_INFO], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_INFO), si->ptszName);
+ break;
+ case GC_EVENT_ADDSTATUS:
+ CList_AddEvent(si->hContact, hIcons[ICON_ADDSTATUS], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_STATUS_ON), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ CList_AddEvent(si->hContact, hIcons[ICON_REMSTATUS], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_STATUS_OFF), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+static BOOL DoPopup(SESSION_INFO* si, GCEVENT* gce, struct TWindowData* dat)
+{
+ int iEvent = gce->pDest->iType;
+ struct TContainerData *pContainer = dat ? dat->pContainer : NULL;
+ char *szProto = dat ? dat->szProto : si->pszModule;
+
+ TCHAR *bbStart, *bbEnd;
+ if (g_Settings.BBCodeInPopups)
+ {
+ bbStart = _T("[b]");
+ bbEnd = _T("[/b]");
+ } else
+ {
+ bbStart = bbEnd = _T("");
+ }
+
+ if (si && (iEvent & si->iLogPopupFlags)) {
+
+ if (nen_options.iMUCDisable) // no popups at all. Period
+ return 0;
+ /*
+ * check the status mode against the status mask
+ */
+
+ if (nen_options.dwStatusMask != -1) {
+ DWORD dwStatus = 0;
+ if (szProto != NULL) {
+ dwStatus = (DWORD)CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ if (!(dwStatus == 0 || dwStatus <= ID_STATUS_OFFLINE || ((1 << (dwStatus - ID_STATUS_ONLINE)) & nen_options.dwStatusMask))) // should never happen, but...
+ return 0;
+ }
+ }
+ if (dat && pContainer != 0) { // message window is open, need to check the container config if we want to see a popup nonetheless
+ if (nen_options.bWindowCheck) { // no popups at all for open windows... no exceptions
+ if(!PluginConfig.m_HideOnClose)
+ return(0);
+ if(pContainer->fHidden)
+ goto passed;
+ return(0);
+ }
+ if (pContainer->dwFlags & CNT_DONTREPORT && IsIconic(pContainer->hwnd)) // in tray counts as "minimised"
+ goto passed;
+ if (pContainer->dwFlags & CNT_DONTREPORTUNFOCUSED) {
+ if (!IsIconic(pContainer->hwnd) && GetForegroundWindow() != pContainer->hwnd && GetActiveWindow() != pContainer->hwnd)
+ goto passed;
+ }
+ if (pContainer->dwFlags & CNT_ALWAYSREPORTINACTIVE) {
+ if (pContainer->dwFlags & CNT_DONTREPORTFOCUSED)
+ goto passed;
+
+ if (pContainer->hwndActive == si->hWnd)
+ return 0;
+
+ goto passed;
+ }
+ return 0;
+ }
+passed:
+ int iNewEvent = iEvent;
+ COLORREF clr = 0;
+
+ if((iNewEvent & GC_EVENT_HIGHLIGHT)) {
+ clr = aFonts[16].color;
+ iNewEvent &= ~GC_EVENT_HIGHLIGHT;
+ }
+ switch (iNewEvent) {
+ case GC_EVENT_MESSAGE :
+ ShowPopup(si->hContact, si, hIcons[ICON_MESSAGE], si->pszModule, si->ptszName, clr ? clr : aFonts[9].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_MSG), bbStart, gce->ptszNick, bbEnd, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ACTION:
+ ShowPopup(si->hContact, si, hIcons[ICON_ACTION], si->pszModule, si->ptszName, clr ? clr : aFonts[15].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_JOIN:
+ ShowPopup(si->hContact, si, hIcons[ICON_JOIN], si->pszModule, si->ptszName, clr ? clr : aFonts[3].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_JOINED), gce->ptszNick);
+ break;
+ case GC_EVENT_PART:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, clr ? clr : aFonts[4].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_LEFT), gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, clr ? clr : aFonts[4].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_LEFT1), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_QUIT:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, clr ? clr : aFonts[5].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_QUIT), gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, clr ? clr : aFonts[5].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_QUIT1), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NICK:
+ ShowPopup(si->hContact, si, hIcons[ICON_NICK], si->pszModule, si->ptszName, clr ? clr : aFonts[7].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_NICK), gce->ptszNick, gce->ptszText);
+ break;
+ case GC_EVENT_KICK:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, clr ? clr : aFonts[6].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_KICK), (char *)gce->pszStatus, gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, clr ? clr : aFonts[6].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_KICK1), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NOTICE:
+ ShowPopup(si->hContact, si, hIcons[ICON_NOTICE], si->pszModule, si->ptszName, clr ? clr : aFonts[8].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_NOTICE), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_TOPIC:
+ if (!gce->ptszNick)
+ ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, clr ? clr : aFonts[11].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_TOPIC), RemoveFormatting(gce->ptszText));
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, clr ? clr : aFonts[11].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_TOPIC1), RemoveFormatting(gce->ptszText), gce->ptszNick);
+ break;
+ case GC_EVENT_INFORMATION:
+ ShowPopup(si->hContact, si, hIcons[ICON_INFO], si->pszModule, si->ptszName, clr ? clr : aFonts[12].color, _T("%s"), RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ADDSTATUS:
+ ShowPopup(si->hContact, si, hIcons[ICON_ADDSTATUS], si->pszModule, si->ptszName, clr ? clr : aFonts[13].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_STATUS_ON), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ ShowPopup(si->hContact, si, hIcons[ICON_REMSTATUS], si->pszModule, si->ptszName, clr ? clr : aFonts[14].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_STATUS_OFF), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+void TSAPI DoFlashAndSoundWorker(FLASH_PARAMS* p)
+{
+ SESSION_INFO* si = SM_FindSessionByHCONTACT(p->hContact);
+ TWindowData* dat = 0;
+
+ if(si == 0)
+ return;
+
+ if (si->hWnd) {
+ dat = si->dat;
+ if (dat) {
+ p->bInactive = dat->pContainer->hwnd != GetForegroundWindow();
+ p->bActiveTab = (dat->pContainer->hwndActive == si->hWnd);
+ }
+ if (p->sound && Utils::mustPlaySound(si->dat))
+ SkinPlaySound(p->sound);
+ }
+ else if(p->sound)
+ SkinPlaySound(p->sound);
+
+ if (dat) {
+ HWND hwndTab = GetParent(si->hWnd);
+ BOOL bForcedIcon = (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT] || p->hNotifyIcon == hIcons[ICON_MESSAGE]);
+
+ if ((p->iEvent & si->iLogTrayFlags) || bForcedIcon) {
+ if (!p->bActiveTab) {
+ if (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT])
+ dat->iFlashIcon = p->hNotifyIcon;
+ else {
+ if (dat->iFlashIcon != hIcons[ICON_HIGHLIGHT] && dat->iFlashIcon != hIcons[ICON_MESSAGE])
+ dat->iFlashIcon = p->hNotifyIcon;
+ }
+ dat->mayFlashTab = TRUE;
+ SetTimer(si->hWnd, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ }
+ }
+ if(dat->pWnd) {
+ dat->pWnd->updateIcon(p->hNotifyIcon);
+ dat->pWnd->setOverlayIcon(p->hNotifyIcon, true);
+ }
+
+ // autoswitch tab..
+ if (p->bMustAutoswitch) {
+ if ((IsIconic(dat->pContainer->hwnd)) && !IsZoomed(dat->pContainer->hwnd) && PluginConfig.haveAutoSwitch() && dat->pContainer->hwndActive != si->hWnd) {
+ int iItem = GetTabIndexFromHWND(hwndTab, si->hWnd);
+ if (iItem >= 0) {
+ TabCtrl_SetCurSel(hwndTab, iItem);
+ ShowWindow(dat->pContainer->hwndActive, SW_HIDE);
+ dat->pContainer->hwndActive = si->hWnd;
+ SendMessage(dat->pContainer->hwnd, DM_UPDATETITLE, (WPARAM)dat->hContact, 0);
+ dat->pContainer->dwFlags |= CNT_DEFERREDTABSELECT;
+ }
+ }
+ }
+
+ /*
+ * flash window if it is not focused
+ */
+ if (p->bMustFlash && p->bInactive)
+ if (!(dat->pContainer->dwFlags & CNT_NOFLASH))
+ FlashContainer(dat->pContainer, 1, 0);
+
+ if (p->hNotifyIcon && p->bInactive && ((p->iEvent & si->iLogTrayFlags) || bForcedIcon)) {
+ HICON hIcon;
+
+ if (p->bMustFlash)
+ dat->hTabIcon = p->hNotifyIcon;
+ else if (dat->iFlashIcon) {
+ TCITEM item = {0};
+
+ dat->hTabIcon = dat->iFlashIcon;
+ item.mask = TCIF_IMAGE;
+ item.iImage = 0;
+ TabCtrl_SetItem(GetParent(si->hWnd), dat->iTabID, &item);
+ }
+ hIcon = (HICON)SendMessage(dat->pContainer->hwnd, WM_GETICON, ICON_BIG, 0);
+ if (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT] || (hIcon != hIcons[ICON_MESSAGE] && hIcon != hIcons[ICON_HIGHLIGHT])) {
+ SendMessage(dat->pContainer->hwnd, DM_SETICON, (WPARAM)dat, (LPARAM)p->hNotifyIcon);
+ dat->pContainer->dwFlags |= CNT_NEED_UPDATETITLE;
+ }
+ }
+
+ if (p->bMustFlash && p->bInactive)
+ UpdateTrayMenu(dat, si->wStatus, si->pszModule, dat ? dat->szStatus : NULL, si->hContact, p->bHighlight ? 1 : 1);
+ }
+
+ free(p);
+}
+
+BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix)
+{
+ FLASH_PARAMS* params;
+ struct TWindowData *dat = 0;
+ bool fFlagUnread = false;
+ WPARAM wParamForHighLight = 0;
+
+ if (gce == 0 || si == 0 || gce->bIsMe || si->iType == GCW_SERVER)
+ return FALSE;
+
+ params = (FLASH_PARAMS*)calloc(1, sizeof(FLASH_PARAMS));
+ params->hContact = si->hContact;
+ params->bInactive = TRUE;
+ if(si->hWnd && si->dat) {
+ dat = si->dat;
+ if((si->hWnd == si->dat->pContainer->hwndActive) && GetForegroundWindow() == si->dat->pContainer->hwnd)
+ params->bInactive = FALSE;
+ }
+ params->bActiveTab = params->bMustFlash = params->bMustAutoswitch = FALSE;
+
+ params->iEvent = gce->pDest->iType;
+
+ if (bHighlight) {
+ gce->pDest->iType |= GC_EVENT_HIGHLIGHT;
+ params->sound = "ChatHighlight";
+ if (M->GetByte(si->hContact, "CList", "Hidden", 0) != 0)
+ DBDeleteContactSetting(si->hContact, "CList", "Hidden");
+ if (params->bInactive) {
+ fFlagUnread = true;
+ DoTrayIcon(si, gce);
+ }
+
+ /* TODO fix for 3.0 final !!! */
+#if !defined(__DELAYED_FOR_3_1)
+ if(g_Settings.CreateWindowOnHighlight && 0 == dat)
+ wParamForHighLight = 1;
+
+ if(dat && g_Settings.AnnoyingHighlight && params->bInactive && dat->pContainer->hwnd != GetForegroundWindow()) {
+ wParamForHighLight = 2;
+ params->hWnd = dat->hwnd;
+ }
+#endif
+ if (dat || !nen_options.iMUCDisable)
+ DoPopup(si, gce, dat);
+ if (params->bInactive && si && si->hWnd)
+ SendMessage(si->hWnd, GC_SETMESSAGEHIGHLIGHT, 0, (LPARAM) si);
+ if (g_Settings.FlashWindowHightlight && params->bInactive)
+ params->bMustFlash = TRUE;
+ params->bMustAutoswitch = TRUE;
+ params->hNotifyIcon = hIcons[ICON_HIGHLIGHT];
+ } else {
+ // do blinking icons in tray
+ if (params->bInactive || !g_Settings.TrayIconInactiveOnly) {
+ DoTrayIcon(si, gce);
+ if(params->iEvent == GC_EVENT_MESSAGE)
+ fFlagUnread = true;
+ }
+ // stupid thing to not create multiple popups for a QUIT event for instance
+ if (bManyFix == 0) {
+ // do popups
+ if (dat || !nen_options.iMUCDisable)
+ DoPopup(si, gce, dat);
+
+ // do sounds and flashing
+ switch (params->iEvent) {
+ case GC_EVENT_JOIN:
+ params->sound = "ChatJoin";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_JOIN];
+ break;
+ case GC_EVENT_PART:
+ params->sound = "ChatPart";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_PART];
+ break;
+ case GC_EVENT_QUIT:
+ params->sound = "ChatQuit";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_QUIT];
+ break;
+ case GC_EVENT_ADDSTATUS:
+ case GC_EVENT_REMOVESTATUS:
+ params->sound = "ChatMode";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[params->iEvent == GC_EVENT_ADDSTATUS ? ICON_ADDSTATUS : ICON_REMSTATUS];
+ break;
+ case GC_EVENT_KICK:
+ params->sound = "ChatKick";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_KICK];
+ break;
+ case GC_EVENT_MESSAGE:
+ params->sound = "ChatMessage";
+ if (params->bInactive && !(si->wState&STATE_TALK)) {
+ si->wState |= STATE_TALK;
+ DBWriteContactSettingWord(si->hContact, si->pszModule, "ApparentMode", (LPARAM)(WORD) 40071);
+ }
+ break;
+ case GC_EVENT_ACTION:
+ params->sound = "ChatAction";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_ACTION];
+ break;
+ case GC_EVENT_NICK:
+ params->sound = "ChatNick";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_NICK];
+ break;
+ case GC_EVENT_NOTICE:
+ params->sound = "ChatNotice";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_NOTICE];
+ break;
+ case GC_EVENT_TOPIC:
+ params->sound = "ChatTopic";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_TOPIC];
+ break;
+ }
+ } else {
+ switch (params->iEvent) {
+ case GC_EVENT_JOIN:
+ params->hNotifyIcon = hIcons[ICON_JOIN];
+ break;
+ case GC_EVENT_PART:
+ params->hNotifyIcon = hIcons[ICON_PART];
+ break;
+ case GC_EVENT_QUIT:
+ params->hNotifyIcon = hIcons[ICON_QUIT];
+ break;
+ case GC_EVENT_KICK:
+ params->hNotifyIcon = hIcons[ICON_KICK];
+ break;
+ case GC_EVENT_ACTION:
+ params->hNotifyIcon = hIcons[ICON_ACTION];
+ break;
+ case GC_EVENT_NICK:
+ params->hNotifyIcon = hIcons[ICON_NICK];
+ break;
+ case GC_EVENT_NOTICE:
+ params->hNotifyIcon = hIcons[ICON_NOTICE];
+ break;
+ case GC_EVENT_TOPIC:
+ params->hNotifyIcon = hIcons[ICON_TOPIC];
+ break;
+ case GC_EVENT_ADDSTATUS:
+ params->hNotifyIcon = hIcons[ICON_ADDSTATUS];
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ params->hNotifyIcon = hIcons[ICON_REMSTATUS];
+ break;
+ }
+ }
+
+ if (params->iEvent == GC_EVENT_MESSAGE) {
+ params->bMustAutoswitch = TRUE;
+ if (g_Settings.FlashWindow)
+ params->bMustFlash = TRUE;
+ params->hNotifyIcon = hIcons[ICON_MESSAGE];
+ }
+ }
+ if(dat && fFlagUnread) {
+ dat->dwUnread++;
+ if(dat->pWnd)
+ dat->pWnd->Invalidate();
+ }
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_MUCFLASHWORKER, wParamForHighLight, (LPARAM)params);
+ return TRUE;
+}
+
+int Chat_GetColorIndex(const char* pszModule, COLORREF cr)
+{
+ MODULEINFO * pMod = 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 = MM_FindModule(pszModule);
+ int i = 0;
+ COLORREF crFG;
+ COLORREF crBG = (COLORREF)M->GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR);
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &crFG, FONTMODULE);
+
+ if (!pMod)
+ return;
+
+ for (i = 0; i < pMod->nColorCount; i++) {
+ if (pMod->crColors[i] == crFG || pMod->crColors[i] == crBG) {
+ if (pMod->crColors[i] == RGB(255, 255, 255))
+ pMod->crColors[i]--;
+ else
+ pMod->crColors[i]++;
+ }
+ }
+}
+
+TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2)
+{
+ int i, j, k;
+
+ _tsetlocale(LC_ALL, _T(""));
+ for (i = 0;s1[i];i++)
+ for (j = i, k = 0; _totlower(s1[j]) == _totlower(s2[k]);j++, k++)
+ if (!s2[k+1])
+ return (TCHAR*)(s1 + i);
+
+ return NULL;
+}
+
+/*
+ * log the event to the log file
+ * allows selective logging of wanted events
+ */
+BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce)
+{
+ MODULEINFO * mi = NULL;
+ TCHAR szBuffer[4096];
+ TCHAR szLine[4096];
+ TCHAR szTime[100];
+ FILE *hFile = NULL;
+ TCHAR tszFolder[MAX_PATH];
+ TCHAR p = '\0';
+ BOOL bFileJustCreated = TRUE;
+
+ if (!si || !gce)
+ return FALSE;
+
+ mi = MM_FindModule(si->pszModule);
+ if (!mi)
+ return FALSE;
+
+ /*
+ * check whether we have to log this event
+ */
+ if(!(gce->pDest->iType & si->iDiskLogFlags))
+ return FALSE;
+
+ szBuffer[0] = '\0';
+
+ GetChatLogsFilename(si, gce->time);
+ bFileJustCreated = !PathFileExists(si->pszLogFileName);
+ _tcscpy(tszFolder, si->pszLogFileName);
+ PathRemoveFileSpec(tszFolder);
+ if (!PathIsDirectory(tszFolder))
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)tszFolder);
+
+ lstrcpyn(szTime, MakeTimeStamp(g_Settings.pszTimeStampLog, gce->time), 99);
+
+ hFile = _tfopen(si->pszLogFileName, _T("ab+"));
+ if (hFile) {
+ TCHAR szTemp[512], szTemp2[512];
+ TCHAR* pszNick = NULL;
+ if (bFileJustCreated)
+ fputws((const wchar_t*)"\377\376", hFile); //UTF-16 LE BOM == FF FE
+ if (gce->ptszNick) {
+ if (g_Settings.LogLimitNames && lstrlen(gce->ptszNick) > 20) {
+ lstrcpyn(szTemp2, gce->ptszNick, 20);
+ lstrcpyn(szTemp2 + 20, _T("..."), 4);
+ } else lstrcpyn(szTemp2, gce->ptszNick, 511);
+
+ if (gce->pszUserInfo)
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, gce->pszUserInfo);
+ else
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), szTemp2);
+ pszNick = szTemp;
+ }
+ switch (gce->pDest->iType) {
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_MESSAGE | GC_EVENT_HIGHLIGHT:
+ p = '*';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ACTION:
+ case GC_EVENT_ACTION | GC_EVENT_HIGHLIGHT:
+ p = '*';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_JOIN:
+ p = '>';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_JOINED), (char *)pszNick);
+ break;
+ case GC_EVENT_PART:
+ p = '<';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_LEFT), (char *)pszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_LEFT1), (char *)pszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_QUIT:
+ p = '<';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_QUIT), (char *)pszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_QUIT1), (char *)pszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NICK:
+ p = '^';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_NICK), gce->ptszNick, gce->ptszText);
+ break;
+ case GC_EVENT_KICK:
+ p = '~';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_KICK), (char *)gce->pszStatus, gce->ptszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_KICK1), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NOTICE:
+ p = 'o';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_NOTICE), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_TOPIC:
+ p = '#';
+ if (!gce->pszNick)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_TOPIC), RemoveFormatting(gce->ptszText));
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_TOPIC1), RemoveFormatting(gce->ptszText), gce->ptszNick);
+ break;
+ case GC_EVENT_INFORMATION:
+ p = '!';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s"), RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ADDSTATUS:
+ p = '+';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_STATUS_ON), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ p = '-';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_STATUS_OFF), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ }
+ /*
+ * formatting strings don't need to be translatable - changing them via language pack would
+ * only screw up the log format.
+ */
+ if (p)
+ mir_sntprintf(szLine, SIZEOF(szLine), _T("%s %c %s\r\n"), szTime, p, szBuffer);
+ else
+ mir_sntprintf(szLine, SIZEOF(szLine), _T("%s %s\r\n"), szTime, szBuffer);
+
+ if (szLine[0]) {
+ _fputts(szLine, hFile);
+
+ if (g_Settings.LoggingLimit > 0) {
+ long dwSize;
+ long trimlimit;
+
+ fseek(hFile, 0, SEEK_END);
+ dwSize = ftell(hFile);
+ rewind(hFile);
+
+ trimlimit = g_Settings.LoggingLimit * 1024;
+ if (dwSize > trimlimit) {
+ TCHAR tszDrive[_MAX_DRIVE];
+ TCHAR tszDir[_MAX_DIR];
+ TCHAR tszName[_MAX_FNAME];
+ TCHAR tszExt[_MAX_EXT];
+ TCHAR tszNewName[_MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20];
+ TCHAR tszNewPath[_MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20];
+ TCHAR tszTimestamp[20];
+ time_t now = time(0);
+
+ _tcsftime(tszTimestamp, 20, _T("%Y%m%d-%H%M%S"), _localtime32((__time32_t *)&now));
+ tszTimestamp[19] = 0;
+ /*
+ * max size reached, rotate the log
+ * move old logs to /archived sub folder just inside the log root folder.
+ * add a time stamp to the file name.
+ */
+ _tsplitpath(si->pszLogFileName, tszDrive, tszDir, tszName, tszExt);
+
+ mir_sntprintf(tszNewPath, _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20, _T("%s%sarchived\\"),
+ tszDrive, tszDir);
+
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)tszNewPath);
+ mir_sntprintf(tszNewName, _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20, _T("%s%s-%s%s"), tszNewPath, tszName, tszTimestamp, tszExt);
+ fclose(hFile);
+ hFile = 0;
+ if(!PathFileExists(tszNewName))
+ CopyFile(si->pszLogFileName, tszNewName, TRUE);
+ DeleteFile(si->pszLogFileName);
+ }
+ }
+ }
+
+ if (hFile)
+ fclose(hFile);
+ hFile = NULL;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText)
+{
+ GCMENUITEMS gcmi = {0};
+ int i;
+ HMENU hSubMenu = 0;
+ DWORD codepage = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ int pos;
+
+ *hMenu = GetSubMenu(g_hMenu, iIndex);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) *hMenu, 0);
+ gcmi.pszID = si->ptszID;
+ gcmi.pszModule = si->pszModule;
+ gcmi.pszUID = pszUID;
+
+ if (iIndex == 1) {
+ int i = GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_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]) {
+ TCHAR szMenuText[4096];
+ mir_sntprintf(szMenuText, 4096, CTranslator::get(CTranslator::GEN_MUC_LOOKUP), pszWordText);
+ ModifyMenu(*hMenu, 4, MF_STRING | MF_BYPOSITION, 4, szMenuText);
+ } else ModifyMenu(*hMenu, 4, MF_STRING | MF_GRAYED | MF_BYPOSITION, 4, CTranslator::get(CTranslator::GEN_MUC_LOOKUP_NOWORD));
+ gcmi.Type = MENU_ON_LOG;
+ } else if (iIndex == 0) {
+ TCHAR szTemp[30], szTemp2[30];
+ lstrcpyn(szTemp, CTranslator::get(CTranslator::GEN_MUC_MESSAGEAMP), 24);
+ if (pszUID)
+ mir_sntprintf(szTemp2, SIZEOF(szTemp2), _T("%s %s"), szTemp, pszUID);
+ else
+ lstrcpyn(szTemp2, szTemp, 24);
+
+ if (lstrlen(szTemp2) > 22)
+ lstrcpyn(szTemp2 + 22, _T("..."), 4);
+ ModifyMenu(*hMenu, ID_MESS, MF_STRING | MF_BYCOMMAND, ID_MESS, szTemp2);
+ gcmi.Type = MENU_ON_NICKLIST;
+ }
+
+ NotifyEventHooks(hBuildMenuEvent, 0, (WPARAM)&gcmi);
+
+ if (gcmi.nItems > 0)
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+
+ for (i = 0; i < gcmi.nItems; i++) {
+ TCHAR* ptszDescr = a2tf(gcmi.Item[i].pszDesc, si->dwFlags, 0);
+ 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, ptszDescr);
+ } else if (gcmi.Item[i].uType == MENU_POPUPHMENU)
+ AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPITEM)
+ AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPCHECK)
+ AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPSEPARATOR)
+ AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, MF_SEPARATOR, 0, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_SEPARATOR)
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_HMENU)
+ AppendMenu(*hMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_ITEM)
+ AppendMenu(*hMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_CHECK)
+ AppendMenu(*hMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+
+ mir_free(ptszDescr);
+ }
+
+#if !defined(__DELAYED_FOR_3_1)
+ if (iIndex == 0) {
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+ pos = GetMenuItemCount(*hMenu);
+ InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20020, CTranslator::get(CTranslator::GEN_MUC_MENU_ADDTOHIGHLIGHT));
+ InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20021, CTranslator::get(CTranslator::GEN_MUC_MENU_EDITHIGHLIGHTLIST));
+ }
+#endif
+ if (iIndex == 1 && si->iType != GCW_SERVER && !(si->dwFlags & GC_UNICODE)) {
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+ InsertMenu(PluginConfig.g_hMenuEncoding, 1, MF_BYPOSITION | MF_STRING, (UINT_PTR)CP_UTF8, CTranslator::get(CTranslator::GEN_STRING_UTF8));
+ pos = GetMenuItemCount(*hMenu);
+ InsertMenu(*hMenu, pos, MF_BYPOSITION | MF_POPUP, (UINT_PTR) PluginConfig.g_hMenuEncoding, CTranslator::get(CTranslator::GEN_MSG_ENCODING));
+ for (i = 0; i < GetMenuItemCount(PluginConfig.g_hMenuEncoding); i++)
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, i, MF_BYPOSITION | MF_UNCHECKED);
+ if (codepage == CP_ACP)
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, 0, MF_BYPOSITION | MF_CHECKED);
+ else
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, codepage, MF_BYCOMMAND | MF_CHECKED);
+
+ }
+
+ return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+}
+
+void DestroyGCMenu(HMENU *hMenu, int iIndex)
+{
+ MENUITEMINFO mi;
+ mi.cbSize = sizeof(mi);
+ mi.fMask = MIIM_SUBMENU;
+ while (GetMenuItemInfo(*hMenu, iIndex, TRUE, &mi)) {
+ if (mi.hSubMenu != NULL)
+ DestroyMenu(mi.hSubMenu);
+ RemoveMenu(*hMenu, iIndex, MF_BYPOSITION);
+ }
+}
+
+BOOL DoEventHookAsync(HWND hwnd, const TCHAR* pszID, const char* pszModule, int iType, TCHAR* pszUID, TCHAR* pszText, DWORD dwItem)
+{
+ SESSION_INFO* si;
+ GCHOOK* gch = (GCHOOK*)mir_alloc(sizeof(GCHOOK));
+ GCDEST* gcd = (GCDEST*)mir_alloc(sizeof(GCDEST));
+
+ memset(gch, 0, sizeof(GCHOOK));
+ memset(gcd, 0, sizeof(GCDEST));
+
+ replaceStrA(&gcd->pszModule, pszModule);
+ if ((si = SM_FindSession(pszID, pszModule)) == NULL)
+ return FALSE;
+
+ if (!(si->dwFlags & GC_UNICODE)) {
+ DWORD dwCP = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ gcd->pszID = t2a(pszID, 0);
+ gch->pszUID = t2a(pszUID, 0);
+ gch->pszText = t2a(pszText, dwCP);
+ } else {
+ replaceStr(&gcd->ptszID, pszID);
+ replaceStr(&gch->ptszUID, pszUID);
+ replaceStr(&gch->ptszText, pszText);
+ }
+ gcd->iType = iType;
+ gch->dwData = dwItem;
+ gch->pDest = gcd;
+ PostMessage(hwnd, GC_FIREHOOK, 0, (LPARAM) gch);
+ return TRUE;
+}
+
+BOOL DoEventHook(const TCHAR* pszID, const char* pszModule, int iType, const TCHAR* pszUID, const TCHAR* pszText, DWORD dwItem)
+{
+ SESSION_INFO* si;
+ GCHOOK gch = {0};
+ GCDEST gcd = {0};
+
+ gcd.pszModule = (char*)pszModule;
+ if ((si = SM_FindSession(pszID, pszModule)) == NULL)
+ return FALSE;
+
+ if (!(si->dwFlags & GC_UNICODE)) {
+ DWORD dwCP = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ gcd.pszID = t2a(pszID, 0);
+ gch.pszUID = t2a(pszUID, 0);
+ gch.pszText = t2a(pszText, dwCP);
+ } else {
+ gcd.ptszID = mir_tstrdup(pszID);
+ gch.ptszUID = mir_tstrdup(pszUID);
+ gch.ptszText = mir_tstrdup(pszText);
+ }
+ gcd.iType = iType;
+ gch.dwData = dwItem;
+ gch.pDest = &gcd;
+ NotifyEventHooks(hSendEvent, 0, (WPARAM)&gch);
+
+ mir_free(gcd.pszID);
+ mir_free(gch.ptszUID);
+ mir_free(gch.ptszText);
+ return TRUE;
+}
+
+BOOL IsEventSupported(int eventType)
+{
+ switch (eventType) {
+ // Supported events
+ case GC_EVENT_JOIN:
+ case GC_EVENT_PART:
+ case GC_EVENT_QUIT:
+ case GC_EVENT_KICK:
+ case GC_EVENT_NICK:
+ case GC_EVENT_NOTICE:
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_TOPIC:
+ case GC_EVENT_INFORMATION:
+ case GC_EVENT_ACTION:
+ case GC_EVENT_ADDSTATUS:
+ case GC_EVENT_REMOVESTATUS:
+ case GC_EVENT_CHUID:
+ case GC_EVENT_CHANGESESSIONAME:
+ case GC_EVENT_ADDGROUP:
+ case GC_EVENT_SETITEMDATA:
+ case GC_EVENT_GETITEMDATA:
+ case GC_EVENT_SETSBTEXT:
+ case GC_EVENT_ACK:
+ case GC_EVENT_SENDMESSAGE:
+ case GC_EVENT_SETSTATUSEX:
+ case GC_EVENT_CONTROL:
+ case GC_EVENT_SETCONTACTSTATUS:
+ return TRUE;
+ }
+
+ // Other events
+ return FALSE;
+}
+
+TCHAR* a2tf(const TCHAR* str, int flags, DWORD cp)
+{
+ if (str == NULL)
+ return NULL;
+
+ if (flags & GC_UNICODE)
+ return mir_tstrdup(str);
+ else {
+ int cbLen;
+ TCHAR *result;
+
+ if (cp == CP_UTF8)
+ return(M->utf8_decodeW((char *)str));
+
+ if (cp == 0)
+ cp = PluginConfig.m_LangPackCP; // CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 );
+ cbLen = MultiByteToWideChar(cp, 0, (char*)str, -1, 0, 0);
+ result = (TCHAR*)mir_alloc(sizeof(TCHAR) * (cbLen + 1));
+ if (result == NULL)
+ return NULL;
+
+ MultiByteToWideChar(cp, 0, (char*)str, -1, result, cbLen);
+ result[ cbLen ] = 0;
+ return result;
+ }
+}
+
+static char* u2a(const wchar_t* src, DWORD cp)
+{
+ int cbLen;
+ char *result;
+
+ if (cp == 0)
+ cp = PluginConfig.m_LangPackCP;
+ else if (cp == CP_UTF8)
+ return(M->utf8_encodeW(src));
+
+ cbLen = WideCharToMultiByte(cp, 0, src, -1, NULL, 0, NULL, NULL);
+ result = (char*)mir_alloc(cbLen + 1);
+ if (result == NULL)
+ return NULL;
+
+ WideCharToMultiByte(cp, 0, src, -1, result, cbLen, NULL, NULL);
+ result[ cbLen ] = 0;
+ return result;
+}
+
+char* t2a(const TCHAR* src, DWORD cp)
+{
+ return u2a(src, cp);
+}
+
+TCHAR* replaceStr(TCHAR** dest, const TCHAR* src)
+{
+ mir_free(*dest);
+ *dest = mir_tstrdup(src);
+ return *dest;
+}
+
+char* replaceStrA(char** dest, const char* src)
+{
+ mir_free(*dest);
+ *dest = mir_strdup(src);
+ return *dest;
+}
+
+/*
+ * set all filters and notification config for a session
+ * uses per channel mask + filterbits, default config as backup
+ */
+
+void Chat_SetFilters(SESSION_INFO *si)
+{
+ DWORD dwFlags_default = 0, dwMask = 0, dwFlags_local = 0;
+ int i;
+
+ if (si == NULL)
+ return;
+
+ dwFlags_default = M->GetDword("Chat", "FilterFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "FilterFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "FilterMask", 0);
+
+ si->iLogFilterFlags = dwFlags_default;
+ for (i = 0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogFilterFlags = (dwFlags_local & (1 << i) ? si->iLogFilterFlags | (1 << i) : si->iLogFilterFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "PopupFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "PopupFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "PopupMask", 0);
+
+ si->iLogPopupFlags = dwFlags_default;
+ for (i = 0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogPopupFlags = (dwFlags_local & (1 << i) ? si->iLogPopupFlags | (1 << i) : si->iLogPopupFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "TrayIconFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "TrayIconFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "TrayIconMask", 0);
+
+ si->iLogTrayFlags = dwFlags_default;
+ for (i = 0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogTrayFlags = (dwFlags_local & (1 << i) ? si->iLogTrayFlags | (1 << i) : si->iLogTrayFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "DiskLogFlags", 0xFFFF);
+ si->iDiskLogFlags = dwFlags_default;
+
+
+ if (si->iLogFilterFlags == 0)
+ si->bFilterEnabled = 0;
+}
+
+static TCHAR tszOldTimeStamp[30] = _T("\0");
+
+TCHAR* GetChatLogsFilename(SESSION_INFO *si, time_t tTime)
+{
+ REPLACEVARSARRAY rva[11];
+ REPLACEVARSDATA dat = {0};
+ TCHAR *p = 0, *tszParsedName = 0;
+ int i;
+ bool fReparse = false;
+
+ if(!tTime)
+ time(&tTime);
+
+ /*
+ * check whether relevant parts of the timestamp have changed and
+ * we have to reparse the filename
+ */
+
+ TCHAR *tszNow = MakeTimeStamp(_T("%a%d%m%Y"), tTime);
+
+ if(_tcscmp(tszOldTimeStamp, tszNow)) {
+ _tcsncpy(tszOldTimeStamp, tszNow, 30);
+ tszOldTimeStamp[29] = 0;
+ fReparse = true;
+ }
+
+ if(fReparse || 0 == si->pszLogFileName[0]) {
+ rva[0].lptzKey = _T("d");
+ rva[0].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%#d"), tTime));
+ // day 01-31
+ rva[1].lptzKey = _T("dd");
+ rva[1].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%d"), tTime));
+ // month 1-12
+ rva[2].lptzKey = _T("m");
+ rva[2].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%#m"), tTime));
+ // month 01-12
+ rva[3].lptzKey = _T("mm");
+ rva[3].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%m"), tTime));
+ // month text short
+ rva[4].lptzKey = _T("mon");
+ rva[4].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%b"), tTime));
+ // month text
+ rva[5].lptzKey = _T("month");
+ rva[5].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%B"), tTime));
+ // year 01-99
+ rva[6].lptzKey = _T("yy");
+ rva[6].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%y"), tTime));
+ // year 1901-9999
+ rva[7].lptzKey = _T("yyyy");
+ rva[7].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%Y"), tTime));
+ // weekday short
+ rva[8].lptzKey = _T("wday");
+ rva[8].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%a"), tTime));
+ // weekday
+ rva[9].lptzKey = _T("weekday");
+ rva[9].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%A"), tTime));
+ // end of array
+ rva[10].lptzKey = NULL;
+ rva[10].lptzValue = NULL;
+
+ if (g_Settings.pszLogDir[lstrlen(g_Settings.pszLogDir)-1] == '\\')
+ _tcscat(g_Settings.pszLogDir, _T("%userid%.log"));
+
+ dat.cbSize = sizeof(dat);
+ dat.dwFlags = RVF_TCHAR;
+ dat.hContact = si->hContact;
+ dat.variables = rva;
+ tszParsedName = (TCHAR*) CallService(MS_UTILS_REPLACEVARS, (WPARAM)g_Settings.pszLogDir, (LPARAM)&dat);
+
+ if(!M->pathIsAbsolute(tszParsedName))
+ mir_sntprintf(si->pszLogFileName, MAX_PATH, _T("%s%s"), M->getChatLogPath(), tszParsedName);
+ else
+ mir_sntprintf(si->pszLogFileName, MAX_PATH, _T("%s"), tszParsedName);
+
+ mir_free(tszParsedName);
+
+ for (i=0; i < SIZEOF(rva);i++)
+ mir_free(rva[i].lptzValue);
+
+ for (p = si->pszLogFileName + 2; *p; ++p) {
+ if (*p == ':' || *p == '*' || *p == '?' || *p == '"' || *p == '<' || *p == '>' || *p == '|' )
+ *p = _T('_');
+ }
+ }
+
+ return si->pszLogFileName;
+}
diff --git a/plugins/TabSRMM/chat/window.cpp b/plugins/TabSRMM/chat/window.cpp
new file mode 100644
index 0000000000..0c7d3c8f99
--- /dev/null
+++ b/plugins/TabSRMM/chat/window.cpp
@@ -0,0 +1,3840 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM 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.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: window.cpp 13631 2011-04-24 08:44:57Z silvercircle $
+ *
+ * This implements the group chat dialog window
+ *
+ */
+
+#include "../src/commonheaders.h"
+
+#include <tom.h>
+
+//#include "../m_MathModule.h"
+
+// externs...
+extern LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+extern HRESULT(WINAPI *MyCloseThemeData)(HANDLE);
+extern REOLECallback *mREOLECallback;
+
+int g_cLinesPerPage=0;
+int g_iWheelCarryover=0;
+//
+
+extern HBRUSH hListBkgBrush;
+extern HANDLE hSendEvent;
+extern HICON hIcons[30];
+extern HMENU g_hMenu;
+extern WNDPROC OldSplitterProc;
+
+static WNDPROC OldMessageProc;
+static WNDPROC OldNicklistProc;
+static WNDPROC OldFilterButtonProc;
+static WNDPROC OldLogProc;
+static HKL hkl = NULL;
+static HCURSOR hCurHyperlinkHand;
+
+typedef struct
+{
+ time_t lastEnterTime;
+ TCHAR* szSearchQuery;
+ TCHAR* szSearchResult;
+ SESSION_INFO *lastSession;
+ TCHAR szTabSave[20];
+ BOOL iSavedSpaces;
+} MESSAGESUBDATA;
+
+static const CLSID IID_ITextDocument= { 0x8CC497C0,0xA1DF,0x11CE, { 0x80,0x98, 0x00,0xAA, 0x00,0x47,0xBE,0x5D} };
+extern WNDPROC OldIEViewProc;
+
+static void Chat_SetMessageLog(TWindowData *dat)
+{
+ unsigned int iLogMode = M->GetByte("Chat", "useIEView", 0);
+
+ if (iLogMode == WANT_IEVIEW_LOG && dat->hwndIEView == 0) {
+ IEVIEWWINDOW ieWindow;
+ IEVIEWEVENT iee;
+
+ //CheckAndDestroyHPP(dat);
+ ZeroMemory(&ieWindow, sizeof(ieWindow));
+ ZeroMemory(&iee, sizeof(iee));
+ ieWindow.cbSize = sizeof(ieWindow);
+ ieWindow.iType = IEW_CREATE;
+ ieWindow.dwFlags = 0;
+ ieWindow.dwMode = IEWM_TABSRMM;
+ ieWindow.parent = dat->hwnd;
+ ieWindow.x = 0;
+ ieWindow.y = 0;
+ ieWindow.cx = 200;
+ ieWindow.cy = 300;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ dat->hwndIEView = ieWindow.hwnd;
+ ZeroMemory(&iee, sizeof(iee));
+ iee.cbSize = sizeof(iee);
+ iee.iType = IEE_CLEAR_LOG;
+ iee.hwnd = dat->hwndIEView;
+ iee.hContact = dat->hContact;
+ iee.codepage = dat->codePage;
+
+ SESSION_INFO *si = (SESSION_INFO *)dat->si;
+
+ iee.pszProto = si->pszModule;
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&iee);
+
+ Utils::showDlgControl(dat->hwnd, IDC_CHAT_LOG, SW_HIDE);
+ Utils::enableDlgControl(dat->hwnd, IDC_CHAT_LOG, FALSE);
+ } else if (iLogMode == WANT_HPP_LOG && dat->hwndHPP == 0) {
+ IEVIEWWINDOW ieWindow;
+
+ ZeroMemory(&ieWindow, sizeof(ieWindow));
+ //CheckAndDestroyIEView(dat);
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_CREATE;
+ ieWindow.dwFlags = 0;
+ ieWindow.dwMode = IEWM_MUCC;
+ ieWindow.parent = dat->hwnd;
+ ieWindow.x = 0;
+ ieWindow.y = 0;
+ ieWindow.cx = 10;
+ ieWindow.cy = 10;
+ CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow);
+ dat->hwndHPP = ieWindow.hwnd;
+ Utils::showDlgControl(dat->hwnd, IDC_CHAT_LOG, SW_HIDE);
+ Utils::enableDlgControl(dat->hwnd, IDC_CHAT_LOG, FALSE);
+ } else {
+ if (iLogMode != WANT_IEVIEW_LOG)
+ CheckAndDestroyIEView(dat);
+ Utils::showDlgControl(dat->hwnd, IDC_CHAT_LOG, SW_SHOW);
+ Utils::enableDlgControl(dat->hwnd, IDC_CHAT_LOG, TRUE);
+ dat->hwndIEView = 0;
+ dat->hwndIWebBrowserControl = 0;
+ dat->hwndHPP = 0;
+ }
+}
+
+
+/*
+ * checking if theres's protected text at the point
+ * emulates EN_LINK WM_NOTIFY to parent to process links
+ */
+static BOOL CheckCustomLink(HWND hwndDlg, POINT* ptClient, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bUrlNeeded)
+{
+ long res = 0, cnt = 0;
+ long cpMin = 0, cpMax = 0;
+ POINT ptEnd = {0};
+ IRichEditOle* RichEditOle = NULL;
+ ITextDocument* TextDocument = NULL;
+ ITextRange* TextRange = NULL;
+ ITextFont* TextFont = NULL;
+ BOOL bIsCustomLink = FALSE;
+
+ POINT pt = *ptClient;
+ ClientToScreen(hwndDlg, &pt);
+
+ do {
+ if (!SendMessage(hwndDlg, EM_GETOLEINTERFACE, 0, (LPARAM)&RichEditOle)) break;
+ if (RichEditOle->QueryInterface(IID_ITextDocument, (void**)&TextDocument) != S_OK) break;
+ if (TextDocument->RangeFromPoint(pt.x, pt.y, &TextRange) != S_OK) break;
+
+ TextRange->GetStart(&cpMin);
+ cpMax = cpMin+1;
+ TextRange->SetEnd(cpMax);
+
+ if (TextRange->GetFont(&TextFont) != S_OK)
+ break;
+
+ TextFont->GetProtected(&res);
+ if (res != tomTrue)
+ break;
+
+ TextRange->GetPoint(tomEnd+TA_BOTTOM+TA_RIGHT, &ptEnd.x, &ptEnd.y);
+ if (pt.x > ptEnd.x || pt.y > ptEnd.y)
+ break;
+
+ if (bUrlNeeded) {
+ TextRange->GetStoryLength(&cnt);
+ for (; cpMin > 0; cpMin--) {
+ res = tomTrue;
+ TextRange->SetIndex(tomCharacter, cpMin+1, tomTrue);
+ TextFont->GetProtected(&res);
+ if (res != tomTrue) { cpMin++; break; }
+ }
+ for (cpMax--; cpMax < cnt; cpMax++) {
+ res = tomTrue;
+ TextRange->SetIndex(tomCharacter, cpMax+1, tomTrue);
+ TextFont->GetProtected(&res);
+ if (res != tomTrue)
+ break;
+ }
+ }
+
+ bIsCustomLink = (cpMin < cpMax);
+ } while(FALSE);
+
+ if (TextFont) TextFont->Release();
+ if (TextRange) TextRange->Release();
+ if (TextDocument) TextDocument->Release();
+ if (RichEditOle) RichEditOle->Release();
+
+ if (bIsCustomLink) {
+ ENLINK enlink = {0};
+ enlink.nmhdr.hwndFrom = hwndDlg;
+ enlink.nmhdr.idFrom = IDC_CHAT_LOG;
+ enlink.nmhdr.code = EN_LINK;
+ enlink.msg = uMsg;
+ enlink.wParam = wParam;
+ enlink.lParam = lParam;
+ enlink.chrg.cpMin = cpMin;
+ enlink.chrg.cpMax = cpMax;
+ SendMessage(GetParent(hwndDlg), WM_NOTIFY, (WPARAM)IDC_CHAT_LOG, (LPARAM)&enlink);
+ }
+ return bIsCustomLink;
+}
+
+static BOOL IsStringValidLink(TCHAR* pszText)
+{
+ TCHAR *p = pszText;
+
+ if (pszText == NULL)
+ return FALSE;
+ if (lstrlen(pszText) < 5)
+ return FALSE;
+
+ while (*p) {
+ if (*p == (TCHAR)'"')
+ return FALSE;
+ p++;
+ }
+ if (_totlower(pszText[0]) == 'w' && _totlower(pszText[1]) == 'w' && _totlower(pszText[2]) == 'w' && pszText[3] == '.' && _istalnum(pszText[4]))
+ return TRUE;
+
+ return(_tcsstr(pszText, _T("://")) == NULL ? FALSE : TRUE);
+}
+
+/*
+ * called whenever a group chat tab becomes active (either by switching tabs or activating a
+ * container window
+ */
+
+static void Chat_UpdateWindowState(TWindowData *dat, UINT msg)
+{
+ if (dat == NULL)
+ return;
+
+ HWND hwndDlg = dat->hwnd;
+ HWND hwndTab = GetParent(hwndDlg);
+ SESSION_INFO *si = (SESSION_INFO *)dat->si;
+
+ if (msg == WM_ACTIVATE) {
+ if (dat->pContainer->dwFlags & CNT_TRANSPARENCY && CMimAPI::m_pSetLayeredWindowAttributes != NULL) {
+ DWORD trans = LOWORD(dat->pContainer->settings->dwTransparency);
+ CMimAPI::m_pSetLayeredWindowAttributes(dat->pContainer->hwnd, CSkin::m_ContainerColorKey, (BYTE)trans, (dat->pContainer->dwFlags & CNT_TRANSPARENCY ? LWA_ALPHA : 0));
+ }
+ }
+
+ if(si->hwndFilter) {
+ POINT pt;
+ RECT rcFilter;
+
+ GetCursorPos(&pt);
+ GetWindowRect(si->hwndFilter, &rcFilter);
+ if(!PtInRect(&rcFilter, pt)) {
+ SendMessage(si->hwndFilter, WM_CLOSE, 1, 1);
+ si->hwndFilter = 0;
+ }
+ }
+
+#if defined(__FEAT_EXP_AUTOSPLITTER)
+ if(dat->fIsAutosizingInput && dat->iInputAreaHeight == -1) {
+ dat->iInputAreaHeight = 0;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_REQUESTRESIZE, 0, 0);
+ }
+#endif
+ dat->Panel->dismissConfig();
+ dat->dwUnread = 0;
+ if(dat->pWnd) {
+ dat->pWnd->activateTab();
+ dat->pWnd->setOverlayIcon(0, true);
+ }
+
+ if (dat->pContainer->hwndSaved == hwndDlg || dat->bWasDeleted)
+ return;
+
+ dat->pContainer->hwndSaved = hwndDlg;
+
+ SetActiveSession(si->ptszID, si->pszModule);
+ dat->hTabIcon = dat->hTabStatusIcon;
+
+ if (dat->iTabID >= 0) {
+ if (DBGetContactSettingWord(si->hContact, si->pszModule , "ApparentMode", 0) != 0)
+ DBWriteContactSettingWord(si->hContact, si->pszModule , "ApparentMode", (LPARAM) 0);
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+
+ SendMessage(hwndDlg, GC_UPDATETITLE, 0, 1);
+ dat->dwTickLastEvent = 0;
+ dat->dwFlags &= ~MWF_DIVIDERSET;
+ if (KillTimer(hwndDlg, TIMERID_FLASHWND) || dat->iFlashIcon) {
+ FlashTab(dat, hwndTab, dat->iTabID, &dat->bTabFlash, FALSE, dat->hTabIcon);
+ dat->mayFlashTab = FALSE;
+ dat->iFlashIcon = 0;
+ }
+ if (dat->pContainer->dwFlashingStarted != 0) {
+ FlashContainer(dat->pContainer, 0, 0);
+ dat->pContainer->dwFlashingStarted = 0;
+ }
+ dat->pContainer->dwFlags &= ~CNT_NEED_UPDATETITLE;
+
+ if (dat->dwFlags & MWF_NEEDCHECKSIZE)
+ PostMessage(hwndDlg, DM_SAVESIZE, 0, 0);
+
+ if (PluginConfig.m_AutoLocaleSupport) {
+ if (dat->hkl == 0)
+ DM_LoadLocale(dat);
+ else
+ SendMessage(hwndDlg, DM_SETLOCALE, 0, 0);
+ }
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ dat->dwLastActivity = GetTickCount();
+ dat->pContainer->dwLastActivity = dat->dwLastActivity;
+ dat->pContainer->MenuBar->configureMenu();
+ UpdateTrayMenuState(dat, FALSE);
+ DM_SetDBButtonStates(hwndDlg, dat);
+
+ if (g_Settings.MathMod) {
+ CallService(MTH_Set_ToolboxEditHwnd, 0, (LPARAM)GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ MTH_updateMathWindow(dat);
+ }
+
+ if (dat->dwFlagsEx & MWF_EX_DELAYEDSPLITTER) {
+ dat->dwFlagsEx &= ~MWF_EX_DELAYEDSPLITTER;
+ ShowWindow(dat->pContainer->hwnd, SW_RESTORE);
+ PostMessage(hwndDlg, DM_SPLITTERGLOBALEVENT, dat->wParam, dat->lParam);
+ PostMessage(hwndDlg, WM_SIZE, 0, 0);
+ dat->wParam = dat->lParam = 0;
+ }
+ /*
+ if (dat->hwndIEView) {
+ RECT rcRTF;
+ POINT pt;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rcRTF);
+ rcRTF.left += 20;
+ rcRTF.top += 20;
+ pt.x = rcRTF.left;
+ pt.y = rcRTF.top;
+ if (dat->hwndIEView) {
+ if (M->GetByte("subclassIEView", 0) && dat->oldIEViewProc == 0) {
+ WNDPROC wndProc = (WNDPROC)SetWindowLongPtr(dat->hwndIEView, GWLP_WNDPROC, (LONG_PTR)IEViewSubclassProc);
+ if (OldIEViewProc == 0)
+ OldIEViewProc = wndProc;
+ dat->oldIEViewProc = wndProc;
+ }
+ }
+ dat->hwndIWebBrowserControl = WindowFromPoint(pt);
+ }
+ */
+ }
+ if(M->isAero())
+ InvalidateRect(hwndTab, NULL, FALSE);
+ if(dat->pContainer->dwFlags & CNT_SIDEBAR)
+ dat->pContainer->SideBar->setActiveItem(dat);
+ BB_SetButtonsPos(dat);
+
+ if(dat->pWnd)
+ dat->pWnd->Invalidate();
+}
+
+/*
+ * initialize button bar, set all the icons and ensure proper button state
+ */
+
+static void InitButtons(HWND hwndDlg, SESSION_INFO* si)
+{
+ BOOL isFlat = M->GetByte("tbflat", 1);
+ BOOL isThemed = PluginConfig.m_bIsXP;
+ MODULEINFO *pInfo = si ? MM_FindModule(si->pszModule) : NULL;
+ BOOL bFilterEnabled = si ? si->bFilterEnabled : FALSE;
+
+ int i = 0;
+
+ if (pInfo) {
+ Utils::enableDlgControl(hwndDlg, IDC_CHAT_BOLD, pInfo->bBold);
+ Utils::enableDlgControl(hwndDlg, IDC_ITALICS, pInfo->bItalics);
+ Utils::enableDlgControl(hwndDlg, IDC_CHAT_UNDERLINE, pInfo->bUnderline);
+ Utils::enableDlgControl(hwndDlg, IDC_COLOR, pInfo->bColor);
+ Utils::enableDlgControl(hwndDlg, IDC_BKGCOLOR, pInfo->bBkgColor);
+ if (si->iType == GCW_CHATROOM)
+ Utils::enableDlgControl(hwndDlg, IDC_CHANMGR, pInfo->bChanMgr);
+ }
+}
+
+static void Chat_ResizeIeView(const TWindowData *dat)
+{
+ RECT rcRichEdit;
+ POINT pt;
+ IEVIEWWINDOW ieWindow;
+ int iMode = dat->hwndIEView ? 1 : 2;
+ HWND hwndDlg = dat->hwnd;
+
+ ZeroMemory(&ieWindow, sizeof(ieWindow));
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rcRichEdit);
+ pt.x = rcRichEdit.left;
+ pt.y = rcRichEdit.top;
+ ScreenToClient(hwndDlg, &pt);
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_SETPOS;
+ ieWindow.parent = hwndDlg;
+ ieWindow.hwnd = iMode == 1 ? dat->hwndIEView : dat->hwndHPP;
+ ieWindow.x = pt.x;
+ ieWindow.y = pt.y;
+ ieWindow.cx = rcRichEdit.right - rcRichEdit.left;
+ ieWindow.cy = rcRichEdit.bottom - rcRichEdit.top;
+ if (ieWindow.cx != 0 && ieWindow.cy != 0) {
+ CallService(iMode == 1 ? MS_IEVIEW_WINDOW : MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow);
+ }
+}
+
+/*
+ * resizer callback for the group chat session window. Called from Mirandas dialog
+ * resizing service
+ */
+
+static int RoomWndResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc)
+{
+ RECT rc, rcTabs;
+ SESSION_INFO* si = (SESSION_INFO*)lParam;
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ int TabHeight;
+ BOOL bToolbar = !(dat->pContainer->dwFlags & CNT_HIDETOOLBAR);
+ BOOL bBottomToolbar = dat->pContainer->dwFlags & CNT_BOTTOMTOOLBAR ? 1 : 0;
+ int panelHeight = dat->Panel->getHeight() + 1;
+
+ BOOL bNick = si->iType != GCW_SERVER && si->bNicklistEnabled;
+ int i = 0;
+ static int msgBottom = 0, msgTop = 0;
+ bool fInfoPanel = dat->Panel->isActive();
+
+ rc.bottom = rc.top = rc.left = rc.right = 0;
+
+ GetClientRect(hwndDlg, &rcTabs);
+ TabHeight = rcTabs.bottom - rcTabs.top;
+
+ if(dat->fIsAutosizingInput)
+ Utils::showDlgControl(hwndDlg, IDC_SPLITTERY, SW_HIDE);
+
+ if (si->iType != GCW_SERVER) {
+ Utils::showDlgControl(hwndDlg, IDC_LIST, si->bNicklistEnabled ? SW_SHOW : SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_SPLITTERX, si->bNicklistEnabled ? SW_SHOW : SW_HIDE);
+
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWNICKLIST, TRUE);
+ Utils::enableDlgControl(hwndDlg, IDC_FILTER, TRUE);
+ if (si->iType == GCW_CHATROOM) {
+ MODULEINFO* tmp = MM_FindModule(si->pszModule);
+ if (tmp)
+ Utils::enableDlgControl(hwndDlg, IDC_CHANMGR, tmp->bChanMgr);
+ }
+ } else {
+ Utils::showDlgControl(hwndDlg, IDC_LIST, SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_SPLITTERX, SW_HIDE);
+ }
+
+ if (si->iType == GCW_SERVER) {
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWNICKLIST, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_FILTER, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_CHANMGR, FALSE);
+ }
+ //ShowWindow(GetDlgItem(hwndDlg, IDC_CHAT_TOGGLESIDEBAR), dat->pContainer->dwFlags & CNT_SIDEBAR ? SW_SHOW : SW_HIDE);
+
+ switch (urc->wId) {
+ case IDC_PANELSPLITTER:
+ urc->rcItem.bottom = panelHeight;
+ urc->rcItem.top = panelHeight - 2;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
+ case IDC_CHAT_LOG:
+ urc->rcItem.top = 0;
+ urc->rcItem.left = 0;
+ urc->rcItem.right = bNick ? urc->dlgNewSize.cx - si->iSplitterX : urc->dlgNewSize.cx;
+ urc->rcItem.bottom = (bToolbar&&!bBottomToolbar) ? (urc->dlgNewSize.cy - si->iSplitterY - (PluginConfig.g_DPIscaleY > 1.0 ? DPISCALEY_S(24) : DPISCALEY_S(23))) : (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(2));
+ if (fInfoPanel)
+ urc->rcItem.top += panelHeight;
+ if (CSkin::m_skinEnabled) {
+ CSkinItem *item = &SkinItems[ID_EXTBKHISTORY];
+ if (!item->IGNORED) {
+ urc->rcItem.left += item->MARGIN_LEFT;
+ urc->rcItem.right -= item->MARGIN_RIGHT;
+ urc->rcItem.top += item->MARGIN_TOP;
+ urc->rcItem.bottom -= item->MARGIN_BOTTOM;
+ }
+ }
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
+
+ case IDC_LIST:
+ urc->rcItem.top = 0;
+ urc->rcItem.right = urc->dlgNewSize.cx ;
+ urc->rcItem.left = urc->dlgNewSize.cx - si->iSplitterX + 2;
+ urc->rcItem.bottom = (bToolbar&&!bBottomToolbar) ? (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(23)) : (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(2));
+ if (fInfoPanel)
+ urc->rcItem.top += panelHeight;
+ if (CSkin::m_skinEnabled) {
+ CSkinItem *item = &SkinItems[ID_EXTBKUSERLIST];
+ if (!item->IGNORED) {
+ urc->rcItem.left += item->MARGIN_LEFT;
+ urc->rcItem.right -= item->MARGIN_RIGHT;
+ urc->rcItem.top += item->MARGIN_TOP;
+ urc->rcItem.bottom -= item->MARGIN_BOTTOM;
+ }
+ }
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
+
+ case IDC_SPLITTERX:
+ urc->rcItem.right = urc->dlgNewSize.cx - si->iSplitterX + 2;
+ urc->rcItem.left = urc->dlgNewSize.cx - si->iSplitterX;
+ urc->rcItem.bottom = (bToolbar&&!bBottomToolbar) ? (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(23)) : (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(2));
+ urc->rcItem.top = 0;
+ if (fInfoPanel)
+ urc->rcItem.top += panelHeight;
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
+
+ case IDC_SPLITTERY:
+ urc->rcItem.right = urc->dlgNewSize.cx;
+ urc->rcItem.top = (bToolbar&&!bBottomToolbar) ? urc->dlgNewSize.cy - si->iSplitterY : urc->dlgNewSize.cy - si->iSplitterY;
+ urc->rcItem.bottom = (bToolbar&&!bBottomToolbar) ? (urc->dlgNewSize.cy - si->iSplitterY + DPISCALEY_S(2)) : (urc->dlgNewSize.cy - si->iSplitterY + DPISCALEY_S(2));
+ urc->rcItem.left = 0;
+ urc->rcItem.bottom++;
+ urc->rcItem.top++;
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
+
+ case IDC_CHAT_MESSAGE:
+ urc->rcItem.right = urc->dlgNewSize.cx ;
+ urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY + 3;
+ urc->rcItem.bottom = urc->dlgNewSize.cy; // - 1 ;
+ msgBottom = urc->rcItem.bottom;
+
+ if(dat->fIsAutosizingInput)
+ urc->rcItem.top -= DPISCALEY_S(1);
+
+ msgTop = urc->rcItem.top;
+ if (bBottomToolbar&&bToolbar)
+ urc->rcItem.bottom -= DPISCALEY_S(22);
+ if (CSkin::m_skinEnabled) {
+ CSkinItem *item = &SkinItems[ID_EXTBKINPUTAREA];
+ if (!item->IGNORED) {
+ urc->rcItem.left += item->MARGIN_LEFT;
+ urc->rcItem.right -= item->MARGIN_RIGHT;
+ urc->rcItem.top += item->MARGIN_TOP;
+ urc->rcItem.bottom -= item->MARGIN_BOTTOM;
+ }
+ }
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+}
+
+
+/*
+ * subclassing for the message input control (a richedit text control)
+ */
+
+static LRESULT CALLBACK MessageSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ MESSAGESUBDATA *dat;
+ SESSION_INFO* Parentsi;
+ struct TWindowData *mwdat;
+ HWND hwndParent = GetParent(hwnd);
+
+ mwdat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ Parentsi = (SESSION_INFO *)mwdat->si;
+
+ dat = (MESSAGESUBDATA *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ if(mwdat->fkeyProcessed && (msg == WM_KEYUP)) {
+ GetKeyboardState(mwdat->kstate);
+ if(mwdat->kstate[VK_CONTROL] & 0x80 || mwdat->kstate[VK_SHIFT] & 0x80)
+ return(0);
+ else {
+ mwdat->fkeyProcessed = false;
+ return(0);
+ }
+ }
+ switch (msg) {
+ case WM_NCCALCSIZE:
+ return(CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, OldMessageProc));
+
+ case WM_NCPAINT:
+ return(CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, OldMessageProc));
+
+ case EM_SUBCLASSED:
+ dat = (MESSAGESUBDATA *) mir_calloc(sizeof(MESSAGESUBDATA));
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) dat);
+ return 0;
+
+ case WM_CONTEXTMENU: {
+ MODULEINFO* mi = MM_FindModule(Parentsi->pszModule);
+ HMENU hMenu, hSubMenu;
+ CHARRANGE sel, all = { 0, -1};
+ int iSelection;
+ int iPrivateBG = M->GetByte(mwdat->hContact, "private_bg", 0);
+ MessageWindowPopupData mwpd;
+ POINT pt;
+ int idFrom = IDC_CHAT_MESSAGE;
+
+ GetCursorPos(&pt);
+ hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ hSubMenu = GetSubMenu(hMenu, 2);
+ RemoveMenu(hSubMenu, 9, MF_BYPOSITION);
+ RemoveMenu(hSubMenu, 8, MF_BYPOSITION);
+ RemoveMenu(hSubMenu, 4, MF_BYPOSITION);
+ EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | ((mi && mi->bBold) ? MF_ENABLED : MF_GRAYED));
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hSubMenu, 0);
+
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin == sel.cpMax) {
+ EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);
+ if (idFrom == IDC_CHAT_MESSAGE)
+ EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED);
+ }
+ mwpd.cbSize = sizeof(mwpd);
+ mwpd.uType = MSG_WINDOWPOPUP_SHOWING;
+ mwpd.uFlags = (idFrom == IDC_LOG ? MSG_WINDOWPOPUP_LOG : MSG_WINDOWPOPUP_INPUT);
+ mwpd.hContact = mwdat->hContact;
+ mwpd.hwnd = hwnd;
+ mwpd.hMenu = hSubMenu;
+ mwpd.selection = 0;
+ mwpd.pt = pt;
+ NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd);
+
+ iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, GetParent(hwnd), NULL);
+
+ mwpd.selection = iSelection;
+ mwpd.uType = MSG_WINDOWPOPUP_SELECTED;
+ NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd);
+
+ switch (iSelection) {
+ case IDM_COPY:
+ SendMessage(hwnd, WM_COPY, 0, 0);
+ break;
+ case IDM_CUT:
+ SendMessage(hwnd, WM_CUT, 0, 0);
+ break;
+ case IDM_PASTE:
+ case IDM_PASTEFORMATTED:
+ if (idFrom == IDC_CHAT_MESSAGE)
+ SendMessage(hwnd, EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_TEXTT : 0, 0);
+ break;
+ case IDM_COPYALL:
+ SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & all);
+ SendMessage(hwnd, WM_COPY, 0, 0);
+ SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & sel);
+ break;
+ case IDM_SELECTALL:
+ SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & all);
+ break;
+ }
+ DestroyMenu(hMenu);
+ return TRUE;
+ }
+
+ case WM_MOUSEWHEEL: {
+ LRESULT result = DM_MouseWheelHandler(hwnd, hwndParent, mwdat, wParam, lParam);
+ if (result == 0)
+ return 0;
+
+ dat->lastEnterTime = 0;
+ break;
+ }
+
+ case WM_SYSKEYUP:
+ if(wParam == VK_MENU) {
+ ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_CHAT_MESSAGE);
+ return(0);
+ }
+ break;
+
+ case WM_SYSKEYDOWN:
+ mwdat->fkeyProcessed = false;
+ if(ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_CHAT_MESSAGE)) {
+ mwdat->fkeyProcessed = true;
+ return(0);
+ }
+ break;
+
+ case WM_SYSCHAR: {
+ if(mwdat->fkeyProcessed) {
+ mwdat->fkeyProcessed = false; // preceeding key event has been processed by miranda hotkey service
+ return(0);
+ }
+ BOOL isMenu = GetKeyState(VK_MENU) & 0x8000;
+
+ if ((wParam >= '0' && wParam <= '9') && isMenu) { // ALT-1 -> ALT-0 direct tab selection
+ BYTE bChar = (BYTE)wParam;
+ int iIndex;
+
+ if (bChar == '0')
+ iIndex = 10;
+ else
+ iIndex = bChar - (BYTE)'0';
+ SendMessage(mwdat->pContainer->hwnd, DM_SELECTTAB, DM_SELECT_BY_INDEX, (LPARAM)iIndex);
+ return 0;
+ }
+ break;
+ }
+
+ case WM_CHAR: {
+ BOOL isShift, isAlt, isCtrl;
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+
+ //MAD: sound on typing..
+ if(PluginConfig.g_bSoundOnTyping && !isAlt &&!isCtrl&&!(mwdat->pContainer->dwFlags&CNT_NOSOUND)&&wParam!=VK_ESCAPE&&!(wParam==VK_TAB&&PluginConfig.m_AllowTab))
+ SkinPlaySound("SoundOnTyping");
+ //MAD
+
+ if (wParam == 0x0d && isCtrl && PluginConfig.m_MathModAvail) {
+ TCHAR toInsert[100];
+ BYTE keyState[256];
+ size_t i;
+ size_t iLen = lstrlen(PluginConfig.m_MathModStartDelimiter);
+ ZeroMemory(keyState, 256);
+ _tcsncpy(toInsert, PluginConfig.m_MathModStartDelimiter, 30);
+ _tcsncat(toInsert, PluginConfig.m_MathModStartDelimiter, 30);
+ SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM)toInsert);
+ SetKeyboardState(keyState);
+ for (i = 0; i < iLen; i++)
+ SendMessage(hwnd, WM_KEYDOWN, mwdat->dwFlags & MWF_LOG_RTL ? VK_RIGHT : VK_LEFT, 0);
+ return 0;
+ }
+ if(isCtrl && !isAlt && !isShift) {
+ MODULEINFO* mi = MM_FindModule(Parentsi->pszModule);
+
+ switch(wParam) {
+ case 0x09: // ctrl-i (italics)
+ if(mi && mi->bItalics) {
+ CheckDlgButton(hwndParent, IDC_ITALICS, IsDlgButtonChecked(hwndParent, IDC_ITALICS) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0);
+ }
+ return(0);
+ case 0x02: // ctrl-b (bold)
+ if(mi && mi->bBold) {
+ CheckDlgButton(hwndParent, IDC_CHAT_BOLD, IsDlgButtonChecked(hwndParent, IDC_CHAT_BOLD) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CHAT_BOLD, 0), 0);
+ }
+ return 0;
+ case 0x20: // ctrl-space clear formatting
+ if(mi && mi->bBold && mi->bItalics && mi->bUnderline) {
+ CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_UNCHECKED);
+ CheckDlgButton(hwndParent, IDC_COLOR, BST_UNCHECKED);
+ CheckDlgButton(hwndParent, IDC_CHAT_BOLD, BST_UNCHECKED);
+ CheckDlgButton(hwndParent, IDC_CHAT_UNDERLINE, BST_UNCHECKED);
+ CheckDlgButton(hwndParent, IDC_ITALICS, BST_UNCHECKED);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CHAT_BOLD, 0), 0);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CHAT_UNDERLINE, 0), 0);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0);
+ }
+ return 0;
+ case 0x0c: // ctrl-l background color
+ if(mi && mi->bBkgColor) {
+ CheckDlgButton(hwndParent, IDC_BKGCOLOR, IsDlgButtonChecked(hwndParent, IDC_BKGCOLOR) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0);
+ }
+ return 0;
+ case 0x15: // ctrl-u underlined
+ if(mi && mi->bUnderline) {
+ CheckDlgButton(hwndParent, IDC_CHAT_UNDERLINE, IsDlgButtonChecked(hwndParent, IDC_CHAT_UNDERLINE) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CHAT_UNDERLINE, 0), 0);
+ }
+ return 0; // ctrl-k color
+ case 0x0b:
+ if(mi && mi->bColor) {
+ CheckDlgButton(hwndParent, IDC_COLOR, IsDlgButtonChecked(hwndParent, IDC_COLOR) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0);
+ }
+ return 0;
+ case 0x17:
+ PostMessage(hwndParent, WM_CLOSE, 0, 1);
+ return 0;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ case WM_KEYDOWN: {
+ static size_t start, end;
+ BOOL isShift, isCtrl, isAlt;
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+
+ //MAD: sound on typing..
+ if(PluginConfig.g_bSoundOnTyping&&!isAlt&&wParam == VK_DELETE)
+ SkinPlaySound("SoundOnTyping");
+ //
+ if (wParam == VK_INSERT && !isShift && !isCtrl && !isAlt) {
+ mwdat->fInsertMode = !mwdat->fInsertMode;
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd);
+ }
+ if (wParam == VK_CAPITAL || wParam == VK_NUMLOCK)
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd);
+
+ if (isCtrl && isAlt && !isShift) {
+ switch (wParam) {
+ case VK_UP:
+ case VK_DOWN:
+ case VK_PRIOR:
+ case VK_NEXT:
+ case VK_HOME:
+ case VK_END: {
+ WPARAM wp = 0;
+
+ if (wParam == VK_UP)
+ wp = MAKEWPARAM(SB_LINEUP, 0);
+ else if (wParam == VK_PRIOR)
+ wp = MAKEWPARAM(SB_PAGEUP, 0);
+ else if (wParam == VK_NEXT)
+ wp = MAKEWPARAM(SB_PAGEDOWN, 0);
+ else if (wParam == VK_HOME)
+ wp = MAKEWPARAM(SB_TOP, 0);
+ else if (wParam == VK_END) {
+ DM_ScrollToBottom(mwdat, 0, 0);
+ return 0;
+ } else if (wParam == VK_DOWN)
+ wp = MAKEWPARAM(SB_LINEDOWN, 0);
+
+ SendMessage(GetDlgItem(hwndParent, IDC_CHAT_LOG), WM_VSCROLL, wp, 0);
+ return 0;
+ }
+ }
+ }
+
+ if (wParam == VK_RETURN) {
+ if (isShift) {
+ if (PluginConfig.m_SendOnShiftEnter) {
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ } else
+ break;
+ }
+ if ((isCtrl && !isShift) ^(0 != PluginConfig.m_SendOnEnter)) {
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ if (PluginConfig.m_SendOnEnter || PluginConfig.m_SendOnDblEnter) {
+ if (isCtrl)
+ break;
+ else {
+ if (PluginConfig.m_SendOnDblEnter) {
+ if (dat->lastEnterTime + 2 < time(NULL)) {
+ dat->lastEnterTime = time(NULL);
+ break;
+ } else {
+ SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0);
+ SendMessage(hwnd, WM_KEYUP, VK_BACK, 0);
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ }
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ } else
+ break;
+ } else
+ dat->lastEnterTime = 0;
+
+ if ((wParam == VK_NEXT && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && !isShift)) { // CTRL-TAB (switch tab/window)
+ SendMessage(mwdat->pContainer->hwnd, DM_SELECTTAB, DM_SELECT_NEXT, 0);
+ return TRUE;
+ }
+
+ if ((wParam == VK_PRIOR && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && isShift)) { // CTRL_SHIFT-TAB (switch tab/window)
+ SendMessage(mwdat->pContainer->hwnd, DM_SELECTTAB, DM_SELECT_PREV, 0);
+ return TRUE;
+ }
+ if (wParam == VK_TAB && !isCtrl && !isShift) { //tab-autocomplete
+ int iLen, end, topicStart;
+ BOOL isTopic = FALSE;
+ BOOL isRoom = FALSE;
+ wchar_t* pszText = NULL;
+ GETTEXTEX gt = {0};
+ LRESULT lResult = (LRESULT)SendMessage(hwnd, EM_GETSEL, (WPARAM)NULL, (LPARAM)NULL);
+ bool fCompleted = false;
+
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+ start = LOWORD(lResult);
+ end = HIWORD(lResult);
+ SendMessage(hwnd, EM_SETSEL, end, end);
+
+ gt.codepage = 1200;
+ gt.flags = GTL_DEFAULT | GTL_PRECISE;
+
+ iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, (LPARAM)0);
+ if (iLen > 0) {
+ wchar_t* pszName = NULL;
+ pszText = reinterpret_cast<wchar_t*>(Utils::safeMirCalloc((iLen + 10) * sizeof(wchar_t)));
+ gt.flags = GT_DEFAULT;
+ gt.cb = (iLen + 9) * sizeof(wchar_t);
+
+ SendMessage(hwnd, EM_GETTEXTEX, (WPARAM)&gt, (LPARAM)pszText);
+
+ if(start > 1 && pszText[start-1] == ' ' && pszText[start-2] == ':')
+ start--;
+
+ 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(pszText[start] == '#')
+ isRoom = TRUE;
+ else {
+ topicStart = (int)start;
+ while ( topicStart >0 && (pszText[topicStart-1] == ' ' || pszText[topicStart-1] == 13 || pszText[topicStart-1] == VK_TAB))
+ topicStart--;
+ if (topicStart > 5 && _tcsstr(&pszText[topicStart-6], _T("/topic")) == &pszText[topicStart-6])
+ isTopic = TRUE;
+ }
+ if (dat->szSearchQuery == NULL) {
+ size_t len = (end - start) + 1;
+ dat->szSearchQuery = reinterpret_cast<wchar_t*>(Utils::safeMirAlloc(sizeof(wchar_t) * len));
+ wcsncpy( dat->szSearchQuery, pszText + start, len);
+ dat->szSearchQuery[len - 1] = 0;
+ dat->szSearchResult = mir_tstrdup(dat->szSearchQuery);
+ dat->lastSession = NULL;
+ }
+ if (isTopic) {
+ pszName = Parentsi->ptszTopic;
+ } else if (isRoom) {
+ dat->lastSession = SM_FindSessionAutoComplete(Parentsi->pszModule, Parentsi, dat->lastSession, dat->szSearchQuery, dat->szSearchResult);
+ if (dat->lastSession != NULL)
+ pszName = dat->lastSession->ptszName;
+ } else
+ pszName = UM_FindUserAutoComplete(Parentsi->pUsers, dat->szSearchQuery, dat->szSearchResult);
+
+ mir_free(pszText);
+ pszText = NULL;
+ mir_free(dat->szSearchResult);
+ dat->szSearchResult = 0;
+ if (pszName == 0) {
+ if ((int)end != (int)start) {
+ SendMessage(hwnd, EM_SETSEL, start, end);
+ SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM) dat->szSearchQuery);
+ }
+ mir_free(dat->szSearchQuery);
+ dat->szSearchQuery = NULL;
+ } else {
+ pszText = 0;
+ dat->szSearchResult = mir_tstrdup(pszName);
+ if ((int)end != (int)start) {
+ if (!isRoom && !isTopic && g_Settings.AddColonToAutoComplete && start == 0) {
+ pszText = reinterpret_cast<wchar_t*>(Utils::safeMirAlloc((wcslen(pszName) + 4) * sizeof(wchar_t)));
+ wcscpy(pszText, pszName);
+ wcscat(pszText, L": ");
+ pszName = pszText;
+ }
+ SendMessage(hwnd, EM_SETSEL, start, end);
+ SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM)pszName);
+ }
+ if(pszText)
+ mir_free(pszText);
+ fCompleted = true;
+ }
+ }
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
+ if(!fCompleted && !PluginConfig.m_AllowTab) {
+ if((GetSendButtonState(mwdat->hwnd) != PBS_DISABLED))
+ SetFocus(GetDlgItem(mwdat->hwnd, IDOK));
+ else
+ SetFocus(GetDlgItem(mwdat->hwnd, IDC_CHAT_LOG));
+ }
+ return 0;
+ } else if (wParam != VK_RIGHT && wParam != VK_LEFT) {
+ mir_free(dat->szSearchQuery);
+ dat->szSearchQuery = NULL;
+ mir_free(dat->szSearchResult);
+ dat->szSearchResult = NULL;
+ }
+
+ if (wParam == VK_F4 && isCtrl && !isAlt) { // ctrl-F4 (close tab)
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CHAT_CLOSE, BN_CLICKED), 0);
+ return 0;
+ }
+
+ if (wParam == VK_NEXT || wParam == VK_PRIOR) {
+ HWND htemp = hwndParent;
+ SendDlgItemMessage(htemp, IDC_CHAT_LOG, msg, wParam, lParam);
+ dat->lastEnterTime = 0;
+ return 0;
+ }
+
+ if (wParam == VK_UP && isCtrl && !isAlt) {
+ int iLen;
+ GETTEXTLENGTHEX gtl = {0};
+ SETTEXTEX ste;
+ LOGFONTA lf;
+ char* lpPrevCmd = SM_GetPrevCommand(Parentsi->ptszID, Parentsi->pszModule);
+
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, &lf, NULL, FONTMODULE);
+ ste.flags = ST_DEFAULT;
+ ste.codepage = CP_ACP;
+ if (lpPrevCmd)
+ SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd);
+ else
+ SetWindowText(hwnd, _T(""));
+
+ gtl.flags = GTL_PRECISE;
+ gtl.codepage = CP_ACP;
+ iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM) & gtl, (LPARAM)NULL);
+ 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 0;
+ }
+
+ if (wParam == VK_DOWN && isCtrl && !isAlt) {
+ int iLen;
+ GETTEXTLENGTHEX gtl = {0};
+ SETTEXTEX ste;
+
+ char* lpPrevCmd = SM_GetNextCommand(Parentsi->ptszID, Parentsi->pszModule);
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ ste.flags = ST_DEFAULT;
+ ste.codepage = CP_ACP;
+ if (lpPrevCmd)
+ SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM) lpPrevCmd);
+ else
+ SetWindowText(hwnd, _T(""));
+
+ gtl.flags = GTL_PRECISE;
+ gtl.codepage = CP_ACP;
+ iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM) & gtl, (LPARAM)NULL);
+ 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 0;
+ }
+ if (wParam == VK_RETURN)
+ break;
+ //fall through
+ }
+
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_KILLFOCUS:
+ dat->lastEnterTime = 0;
+ break;
+
+ case WM_KEYUP:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP: {
+ CHARFORMAT2 cf;
+ UINT u = 0;
+ UINT u2 = 0;
+ COLORREF cr;
+ MODULEINFO* mi = MM_FindModule(Parentsi->pszModule);
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &cr, FONTMODULE);
+
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_BACKCOLOR | CFM_COLOR | CFM_UNDERLINETYPE;
+ cf.dwEffects = 0;
+ SendMessage(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+
+ if (mi && mi->bColor) {
+ int index = Chat_GetColorIndex(Parentsi->pszModule, cf.crTextColor);
+ u = IsDlgButtonChecked(GetParent(hwnd), IDC_COLOR);
+
+ if (index >= 0) {
+ Parentsi->bFGSet = TRUE;
+ Parentsi->iFG = index;
+ }
+
+ if (u == BST_UNCHECKED && cf.crTextColor != cr)
+ CheckDlgButton(hwndParent, IDC_COLOR, BST_CHECKED);
+ else if (u == BST_CHECKED && cf.crTextColor == cr)
+ CheckDlgButton(hwndParent, IDC_COLOR, BST_UNCHECKED);
+ }
+
+ if (mi && mi->bBkgColor) {
+ int index = Chat_GetColorIndex(Parentsi->pszModule, cf.crBackColor);
+ COLORREF crB = (COLORREF)M->GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR);
+ u = IsDlgButtonChecked(hwndParent, IDC_BKGCOLOR);
+
+ if (index >= 0) {
+ Parentsi->bBGSet = TRUE;
+ Parentsi->iBG = index;
+ }
+
+ if (u == BST_UNCHECKED && cf.crBackColor != crB)
+ CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_CHECKED);
+ else if (u == BST_CHECKED && cf.crBackColor == crB)
+ CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_UNCHECKED);
+ }
+
+ if (mi && mi->bBold) {
+ u = IsDlgButtonChecked(hwndParent, IDC_CHAT_BOLD);
+ u2 = cf.dwEffects;
+ u2 &= CFE_BOLD;
+ if (u == BST_UNCHECKED && u2)
+ CheckDlgButton(hwndParent, IDC_CHAT_BOLD, BST_CHECKED);
+ else if (u == BST_CHECKED && u2 == 0)
+ CheckDlgButton(hwndParent, IDC_CHAT_BOLD, BST_UNCHECKED);
+ }
+
+ if (mi && mi->bItalics) {
+ u = IsDlgButtonChecked(hwndParent, IDC_ITALICS);
+ u2 = cf.dwEffects;
+ u2 &= CFE_ITALIC;
+ if (u == BST_UNCHECKED && u2)
+ CheckDlgButton(hwndParent, IDC_ITALICS, BST_CHECKED);
+ else if (u == BST_CHECKED && u2 == 0)
+ CheckDlgButton(hwndParent, IDC_ITALICS, BST_UNCHECKED);
+ }
+
+ if (mi && mi->bUnderline) {
+ u = IsDlgButtonChecked(hwndParent, IDC_CHAT_UNDERLINE);
+ if(cf.dwEffects & CFE_UNDERLINE && (cf.bUnderlineType & CFU_UNDERLINE || cf.bUnderlineType & CFU_UNDERLINEWORD)) {
+ if (u == BST_UNCHECKED )
+ CheckDlgButton(hwndParent, IDC_CHAT_UNDERLINE, BST_CHECKED);
+ }
+ else {
+ if (u == BST_CHECKED)
+ CheckDlgButton(hwndParent, IDC_CHAT_UNDERLINE, BST_UNCHECKED);
+ }
+ }
+ }
+ break;
+
+ case WM_INPUTLANGCHANGEREQUEST:
+ return DefWindowProc(hwnd, WM_INPUTLANGCHANGEREQUEST, wParam, lParam);
+
+ case WM_INPUTLANGCHANGE:
+ if (PluginConfig.m_AutoLocaleSupport && GetFocus() == hwnd && mwdat->pContainer->hwndActive == hwndParent && GetForegroundWindow() == mwdat->pContainer->hwnd && GetActiveWindow() == mwdat->pContainer->hwnd) {
+ DM_SaveLocale(mwdat, wParam, lParam);
+ SendMessage(hwnd, EM_SETLANGOPTIONS, 0, (LPARAM) SendMessage(hwnd, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
+ return 1;
+ }
+ break;
+
+ case WM_ERASEBKGND: {
+ return(CSkin::m_skinEnabled ? 0 : 1);
+ }
+
+ case EM_UNSUBCLASSED:
+ mir_free(dat);
+ return 0;
+ }
+
+ return CallWindowProc(OldMessageProc, hwnd, msg, wParam, lParam);
+}
+
+
+/*
+ * subclassing for the message filter dialog (set and configure event filters for the current
+ * session
+ */
+
+static UINT _eventorder[] = { GC_EVENT_ACTION,
+ GC_EVENT_MESSAGE,
+ GC_EVENT_NICK,
+ GC_EVENT_JOIN,
+ GC_EVENT_PART,
+ GC_EVENT_TOPIC,
+ GC_EVENT_ADDSTATUS,
+ GC_EVENT_INFORMATION,
+ GC_EVENT_QUIT,
+ GC_EVENT_KICK,
+ GC_EVENT_NOTICE,
+ 0
+};
+
+static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ SESSION_INFO * si = (SESSION_INFO *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (uMsg) {
+ case WM_INITDIALOG: {
+
+ si = (SESSION_INFO *)lParam;
+ DWORD dwMask = M->GetDword(si->hContact, "Chat", "FilterMask", 0);
+ DWORD dwFlags = M->GetDword(si->hContact, "Chat", "FilterFlags", 0);
+
+ DWORD dwPopupMask = M->GetDword(si->hContact, "Chat", "PopupMask", 0);
+ DWORD dwPopupFlags = M->GetDword(si->hContact, "Chat", "PopupFlags", 0);
+
+ DWORD dwTrayMask = M->GetDword(si->hContact, "Chat", "TrayIconMask", 0);
+ DWORD dwTrayFlags = M->GetDword(si->hContact, "Chat", "TrayIconFlags", 0);
+
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)si);
+
+ for(int i = 0; _eventorder[i]; i++) {
+ CheckDlgButton(hwndDlg, IDC_1 + i, dwMask & _eventorder[i] ? (dwFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE);
+ CheckDlgButton(hwndDlg, IDC_P1 + i, dwPopupMask & _eventorder[i] ? (dwPopupFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE);
+ CheckDlgButton(hwndDlg, IDC_T1 + i, dwTrayMask & _eventorder[i] ? (dwTrayFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE);
+ }
+ return(FALSE);
+ }
+ 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_CLOSE:
+ if (wParam == 1 && lParam == 1) {
+ int iFlags = 0, i;
+ UINT result;
+ DWORD dwMask = 0, dwFlags = 0;
+
+ for(i = 0; _eventorder[i]; i++) {
+ result = IsDlgButtonChecked(hwndDlg, IDC_1 + i);
+ dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0);
+ iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0);
+ }
+
+ if (iFlags&GC_EVENT_ADDSTATUS)
+ iFlags |= GC_EVENT_REMOVESTATUS;
+
+ if (si) {
+ if (dwMask == 0) {
+ DBDeleteContactSetting(si->hContact, "Chat", "FilterFlags");
+ DBDeleteContactSetting(si->hContact, "Chat", "FilterMask");
+ } else {
+ M->WriteDword(si->hContact, "Chat", "FilterFlags", iFlags);
+ M->WriteDword(si->hContact, "Chat", "FilterMask", dwMask);
+ }
+ }
+
+ dwMask = iFlags = 0;
+
+ for(i = 0; _eventorder[i]; i++) {
+ result = IsDlgButtonChecked(hwndDlg, IDC_P1 + i);
+ dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0);
+ iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0);
+ }
+
+ if (iFlags&GC_EVENT_ADDSTATUS)
+ iFlags |= GC_EVENT_REMOVESTATUS;
+
+ if (si) {
+ if (dwMask == 0) {
+ DBDeleteContactSetting(si->hContact, "Chat", "PopupFlags");
+ DBDeleteContactSetting(si->hContact, "Chat", "PopupMask");
+ } else {
+ M->WriteDword(si->hContact, "Chat", "PopupFlags", iFlags);
+ M->WriteDword(si->hContact, "Chat", "PopupMask", dwMask);
+ }
+ }
+
+ dwMask = iFlags = 0;
+
+ for(i = 0; _eventorder[i]; i++) {
+ result = IsDlgButtonChecked(hwndDlg, IDC_T1 + i);
+ dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0);
+ iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0);
+ }
+ if (iFlags&GC_EVENT_ADDSTATUS)
+ iFlags |= GC_EVENT_REMOVESTATUS;
+
+ if (si) {
+ if (dwMask == 0) {
+ DBDeleteContactSetting(si->hContact, "Chat", "TrayIconFlags");
+ DBDeleteContactSetting(si->hContact, "Chat", "TrayIconMask");
+ } else {
+ M->WriteDword(si->hContact, "Chat", "TrayIconFlags", iFlags);
+ M->WriteDword(si->hContact, "Chat", "TrayIconMask", dwMask);
+ }
+ Chat_SetFilters(si);
+ SendMessage(si->hWnd, GC_CHANGEFILTERFLAG, 0, (LPARAM)iFlags);
+ if (si->bFilterEnabled)
+ SendMessage(si->hWnd, GC_REDRAWLOG, 0, 0);
+ }
+ }
+ DestroyWindow(hwndDlg);
+ break;
+ case WM_DESTROY:
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ break;
+ }
+ return(FALSE);
+}
+
+/**
+ * subclass for some tool bar buttons which must perform special actions
+ * on right click.
+ */
+static LRESULT CALLBACK ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndParent = GetParent(hwnd);
+
+ switch (msg) {
+ case WM_RBUTTONUP: {
+ HWND hFilter = GetDlgItem(hwndParent, IDC_FILTER);
+ HWND hColor = GetDlgItem(hwndParent, IDC_COLOR);
+ HWND hBGColor = GetDlgItem(hwndParent, IDC_BKGCOLOR);
+
+ if (M->GetByte("Chat", "RightClickFilter", 0) != 0) {
+ if (hFilter == hwnd)
+ SendMessage(hwndParent, GC_SHOWFILTERMENU, 0, 0);
+ if (hColor == hwnd)
+ SendMessage(hwndParent, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_COLOR);
+ if (hBGColor == hwnd)
+ SendMessage(hwndParent, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_BKGCOLOR);
+ }
+ }
+ break;
+ }
+
+ return CallWindowProc(OldFilterButtonProc, hwnd, msg, wParam, lParam);
+}
+
+
+/*
+ * subclassing for the message history display (rich edit control in which the chat history appears)
+ */
+
+static LRESULT CALLBACK LogSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndParent = GetParent(hwnd);
+ struct TWindowData *mwdat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_NCCALCSIZE:
+ return(CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, OldLogProc));
+
+ case WM_NCPAINT:
+ return(CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, OldLogProc));
+
+ case WM_COPY:
+ return(DM_WMCopyHandler(hwnd, OldLogProc, wParam, lParam));
+
+ case WM_SETCURSOR:
+ if (g_Settings.ClickableNicks && (LOWORD(lParam) == HTCLIENT)) {
+ POINT pt;
+ GetCursorPos(&pt);
+ ScreenToClient(hwnd,&pt);
+ if (CheckCustomLink(hwnd, &pt, msg, wParam, lParam, FALSE)) return TRUE;
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONUP:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONDBLCLK:
+ if (g_Settings.ClickableNicks) {
+ POINT pt={LOWORD(lParam), HIWORD(lParam)};
+ CheckCustomLink(hwnd, &pt, msg, wParam, lParam, TRUE);
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ {
+ CHARRANGE sel;
+ if (g_Settings.ClickableNicks) {
+ POINT pt={LOWORD(lParam), HIWORD(lParam)};
+ CheckCustomLink(hwnd, &pt, msg, wParam, lParam, TRUE);
+ }
+ if(true || M->GetByte("autocopy", 0)) {
+ 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(hwndParent, IDC_CHAT_MESSAGE));
+ }
+ }
+ }
+ break;
+
+ case WM_KEYDOWN:
+ if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window)
+ PostMessage(hwndParent, WM_CLOSE, 0, 1);
+ return TRUE;
+ }
+ break;
+
+ case WM_SYSKEYUP:
+ if(wParam == VK_MENU) {
+ ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_CHAT_LOG);
+ return(0);
+ }
+ break;
+
+ case WM_SYSKEYDOWN:
+ mwdat->fkeyProcessed = false;
+ if(ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_CHAT_LOG)) {
+ mwdat->fkeyProcessed = true;
+ return(0);
+ }
+ break;
+
+ case WM_SYSCHAR: {
+ if(mwdat->fkeyProcessed) {
+ mwdat->fkeyProcessed = false;
+ return(0);
+ }
+ 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(hwndParent, IDC_CHAT_MESSAGE));
+ SendMessage(GetDlgItem(hwndParent, IDC_CHAT_MESSAGE), WM_CHAR, wParam, lParam);
+ break;
+ }
+
+ return CallWindowProc(OldLogProc, hwnd, msg, wParam, lParam);
+}
+
+
+/*
+ * process mouse - hovering for the nickname list. fires events so the protocol can
+ * show the userinfo - tooltip.
+ */
+
+static void ProcessNickListHovering(HWND hwnd, int hoveredItem, POINT * pt, SESSION_INFO * parentdat)
+{
+ static int currentHovered = -1;
+ static HWND hwndToolTip = NULL;
+ static HWND oldParent = NULL;
+ TOOLINFO ti = {0};
+ RECT clientRect;
+ BOOL bNewTip = FALSE;
+ USERINFO *ui1 = 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);
+
+ } else {
+
+ 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;
+ }
+
+ GetClientRect(hwnd, &clientRect);
+ ti.cbSize = sizeof(TOOLINFO);
+ ti.uFlags = TTF_SUBCLASS;
+ ti.hinst = g_hInst;
+ ti.hwnd = hwnd;
+ ti.uId = 1;
+ ti.rect = clientRect;
+
+ ti.lpszText = NULL;
+
+ ui1 = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, currentHovered);
+ if (ui1) {
+ char serviceName[256];
+ _snprintf(serviceName, SIZEOF(serviceName), "%s"MS_GC_PROTO_GETTOOLTIPTEXT, parentdat->pszModule);
+ if (ServiceExists(serviceName))
+ ti.lpszText = (TCHAR*)CallService(serviceName, (WPARAM)parentdat->ptszID, (LPARAM)ui1->pszUID);
+ else {
+ TCHAR ptszBuf[ 1024 ];
+ mir_sntprintf( ptszBuf, SIZEOF(ptszBuf), _T("%s: %s\r\n%s: %s\r\n%s: %s"),
+ CTranslator::get(CTranslator::GEN_MUC_NICKNAME), ui1->pszNick,
+ CTranslator::get(CTranslator::GEN_MUC_UID), ui1->pszUID,
+ CTranslator::get(CTranslator::GEN_MUC_STATUS), TM_WordToString( parentdat->pStatuses, ui1->Status ));
+ ti.lpszText = mir_tstrdup( ptszBuf );
+ }
+ }
+
+ SendMessage(hwndToolTip, bNewTip ? TTM_ADDTOOL : TTM_UPDATETIPTEXT, 0, (LPARAM) &ti);
+ SendMessage(hwndToolTip, TTM_ACTIVATE, (ti.lpszText != NULL) , 0);
+ SendMessage(hwndToolTip, TTM_SETMAXTIPWIDTH, 0 , 400);
+ if (ti.lpszText)
+ mir_free(ti.lpszText);
+ }
+}
+
+/*
+ * subclassing for the nickname list control. It is an ownerdrawn listbox
+ */
+
+static LRESULT CALLBACK NicklistSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndParent = GetParent(hwnd);
+ struct TWindowData *mwdat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+
+ static BOOL isToolTip = NULL;
+ static int currentHovered = -1;
+
+ switch (msg) {
+ //MAD: attemp to fix weird bug, when combobox with hidden vscroll
+ //can't be scrolled with mouse-wheel.
+ case WM_NCCALCSIZE: {
+ if (CSkin::m_DisableScrollbars) {
+ RECT lpRect;
+ LONG itemHeight;
+
+ GetClientRect (hwnd, &lpRect);
+ itemHeight = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0);
+ g_cLinesPerPage = (lpRect.bottom - lpRect.top) /itemHeight ;
+ }
+ return(CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKUSERLIST, msg, wParam, lParam, OldNicklistProc));
+ }
+ //
+ case WM_NCPAINT:
+ return(CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKUSERLIST, msg, wParam, lParam, OldNicklistProc));
+
+ case WM_ERASEBKGND: {
+ HDC dc = (HDC)wParam;
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ SESSION_INFO *parentdat = (SESSION_INFO *)dat->si;
+ if (dc) {
+ int height, index, items = 0;
+
+ index = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0);
+ if (index == LB_ERR || parentdat->nUsersInNicklist <= 0)
+ return 0;
+
+ items = parentdat->nUsersInNicklist - index;
+ height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0);
+
+ if (height != LB_ERR) {
+ RECT rc = {0};
+ GetClientRect(hwnd, &rc);
+
+ if (rc.bottom - rc.top > items * height) {
+ rc.top = items * height;
+ FillRect(dc, &rc, hListBkgBrush);
+ }
+ }
+ }
+ }
+ return 1;
+
+ //MAD
+ case WM_MOUSEWHEEL: {
+ if (CSkin::m_DisableScrollbars) {
+ UINT uScroll;
+ int dLines;
+ short zDelta=(short)HIWORD(wParam);
+ if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uScroll, 0))
+ uScroll = 3; /* default value */
+
+ if (uScroll == WHEEL_PAGESCROLL)
+ uScroll = g_cLinesPerPage;
+ if (uScroll == 0)
+ return 0;
+
+ zDelta += g_iWheelCarryover; /* Accumulate wheel motion */
+
+ dLines = zDelta * (int)uScroll / WHEEL_DELTA;
+
+
+ //Record the unused portion as the next carryover.
+ g_iWheelCarryover = zDelta - dLines * WHEEL_DELTA / (int)uScroll;
+
+
+ // scrolling.
+ while (abs(dLines)) {
+ if (dLines > 0) {
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
+ dLines--;
+ } else {
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
+ dLines++;
+ }
+ }
+ return 0;
+ }
+ break;
+ }
+//MAD_
+ case WM_KEYDOWN:
+ if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window)
+ PostMessage(hwndParent, WM_CLOSE, 0, 1);
+ return TRUE;
+ }
+ if (wParam == VK_ESCAPE || wParam == VK_UP || wParam == VK_DOWN || wParam == VK_NEXT ||
+ wParam == VK_PRIOR || wParam == VK_TAB || wParam == VK_HOME || wParam == VK_END) {
+ if (mwdat && mwdat->si) {
+ SESSION_INFO *si = (SESSION_INFO *)mwdat->si;
+ si->szSearch[0] = 0;
+ si->iSearchItem = -1;
+ }
+ }
+ break;
+
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS:
+ if (mwdat && mwdat->si) { // set/kill focus invalidates incremental search status
+ SESSION_INFO *si = (SESSION_INFO *)mwdat->si;
+ si->szSearch[0] = 0;
+ si->iSearchItem = -1;
+ }
+ break;
+
+ case WM_CHAR:
+ case WM_UNICHAR: {
+ /*
+ * simple incremental search for the user (nick) - list control
+ * typing esc or movement keys will clear the current search string
+ */
+
+ if (mwdat && mwdat->si) {
+ SESSION_INFO *si = (SESSION_INFO *)mwdat->si;
+ if (wParam == 27 && si->szSearch[0]) { // escape - reset everything
+ si->szSearch[0] = 0;
+ si->iSearchItem = -1;
+ break;
+ } else if (wParam == '\b' && si->szSearch[0]) // backspace
+ si->szSearch[lstrlen(si->szSearch) - 1] = '\0';
+ else if (wParam < ' ')
+ break;
+ else {
+ TCHAR szNew[2];
+ szNew[0] = (TCHAR) wParam;
+ szNew[1] = '\0';
+ if (lstrlen(si->szSearch) >= SIZEOF(si->szSearch) - 2) {
+ MessageBeep(MB_OK);
+ break;
+ }
+ _tcscat(si->szSearch, szNew);
+ }
+ if (si->szSearch[0]) {
+ int iItems = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
+ int i;
+ USERINFO *ui;
+
+ /*
+ * iterate over the (sorted) list of nicknames and search for the
+ * string we have
+ */
+
+ for (i = 0; i < iItems; i++) {
+ ui = UM_FindUserFromIndex(si->pUsers, i);
+ if (ui) {
+ if (!_tcsnicmp(ui->pszNick, si->szSearch, lstrlen(si->szSearch))) {
+ SendMessage(hwnd, LB_SETSEL, FALSE, -1);
+ SendMessage(hwnd, LB_SETSEL, TRUE, i);
+ si->iSearchItem = i;
+ InvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+ }
+ }
+ }
+ if (i == iItems) {
+ MessageBeep(MB_OK);
+ si->szSearch[lstrlen(si->szSearch) - 1] = '\0';
+ return 0;
+ }
+ }
+ }
+ break;
+ }
+
+ case WM_RBUTTONDOWN: {
+ int iCounts = SendMessage(hwnd, LB_GETSELCOUNT, 0, 0);
+
+ if (iCounts != LB_ERR && iCounts > 1)
+ return 0;
+ 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 CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+ return FALSE;
+ }
+
+ case WM_DRAWITEM: {
+ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam;
+ if (dis->CtlType == ODT_MENU)
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+ return FALSE;
+ }
+ case WM_CONTEXTMENU: {
+ TVHITTESTINFO hti;
+ int item;
+ int height;
+ USERINFO * ui;
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ SESSION_INFO *parentdat = (SESSION_INFO *)dat->si;
+
+
+ hti.pt.x = (short) LOWORD(lParam);
+ hti.pt.y = (short) HIWORD(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);
+
+ item = (DWORD)(SendMessage(hwnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y)));
+ if ( HIWORD( item ) == 1 )
+ item = (DWORD)(-1);
+ else
+ item &= 0xFFFF;
+
+ ui = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, item);
+ // ui = (USERINFO *)SendMessage(GetDlgItem(hwndParent, IDC_LIST), LB_GETITEMDATA, item, 0);
+ if (ui) {
+ HMENU hMenu = 0;
+ UINT uID;
+ 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);
+ uID = CreateGCMenu(hwnd, &hMenu, 0, hti.pt, parentdat, uinew.pszUID, NULL);
+
+ switch (uID) {
+ case 0:
+ break;
+
+ case 20020: { // add to highlight...
+ RECT rc, rcWnd;
+ THighLightEdit the = {THighLightEdit::CMD_ADD, parentdat, ui};
+
+ if(parentdat && ui) {
+ HWND hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_ADDHIGHLIGHT), parentdat->dat->pContainer->hwnd, CMUCHighlight::dlgProcAdd, (LPARAM)&the);
+ TranslateDialogDefault(hwnd);
+ GetClientRect(parentdat->pContainer->hwnd, &rcWnd);
+ GetWindowRect(hwnd, &rc);
+
+ SetWindowPos(hwnd, HWND_TOP, (rcWnd.right - (rc.right - rc.left)) / 2, (rcWnd.bottom - (rc.bottom - rc.top)) / 2 , 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
+ }
+ break;
+ }
+
+ case ID_MESS:
+ DoEventHookAsync(GetParent(hwnd), parentdat->ptszID, parentdat->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ break;
+
+ default: {
+ int iCount = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
+
+ if (iCount != LB_ERR) {
+ int iSelectedItems = SendMessage(hwnd, LB_GETSELCOUNT, 0, 0);
+
+ if (iSelectedItems != LB_ERR) {
+ int *pItems = (int *)malloc(sizeof(int) * (iSelectedItems + 1));
+
+ if (pItems) {
+ if (SendMessage(hwnd, LB_GETSELITEMS, (WPARAM)iSelectedItems, (LPARAM)pItems) != LB_ERR) {
+ USERINFO *ui1 = NULL;
+ int i;
+
+ for (i = 0; i < iSelectedItems; i++) {
+ ui1 = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, pItems[i]);
+ if (ui1)
+ DoEventHookAsync(hwndParent, parentdat->ptszID, parentdat->pszModule, GC_USER_NICKLISTMENU, ui1->pszUID, NULL, (LPARAM)uID);
+ }
+ }
+ free(pItems);
+ }
+ }
+ }
+ //DoEventHookAsync(hwndParent, parentdat->ptszID, parentdat->pszModule, GC_USER_NICKLISTMENU, ui->pszUID, NULL, (LPARAM)uID);
+ break;
+ }
+ }
+ DestroyGCMenu(&hMenu, 1);
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE: {
+ POINT pt;
+ RECT clientRect;
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+ GetClientRect(hwnd, &clientRect);
+ if (PtInRect(&clientRect, pt)) {
+ //hit test item under mouse
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ SESSION_INFO *parentdat = (SESSION_INFO *)dat->si;
+
+ DWORD nItemUnderMouse = (DWORD)SendMessage(hwnd, LB_ITEMFROMPOINT, 0, lParam);
+ if (HIWORD(nItemUnderMouse) == 1)
+ nItemUnderMouse = (DWORD)(-1);
+ else
+ nItemUnderMouse &= 0xFFFF;
+
+ if (M->GetByte("adv_TipperTooltip", 1) && ServiceExists("mToolTip/HideTip")) {
+ if ((int)nItemUnderMouse == currentHovered) break;
+ currentHovered = (int)nItemUnderMouse;
+
+ KillTimer(hwnd, 1);
+
+ if (isToolTip) {
+ CallService("mToolTip/HideTip", 0, 0);
+ isToolTip = FALSE;
+ }
+
+ if (nItemUnderMouse != -1)
+ SetTimer(hwnd, 1, 450, 0);
+ }
+ else ProcessNickListHovering(hwnd, (int)nItemUnderMouse, &pt, parentdat);
+ }
+ else
+ {
+ if (M->GetByte("adv_TipperTooltip", 1) && ServiceExists("mToolTip/HideTip")) {
+ KillTimer(hwnd, 1);
+ if (isToolTip) {
+ CallService("mToolTip/HideTip", 0, 0);
+ isToolTip = FALSE;
+ }
+ }
+ else ProcessNickListHovering(hwnd, -1, &pt, NULL);
+ }
+ }
+ break;
+
+ case WM_TIMER:
+ {
+ CLCINFOTIP ti = {0};
+ USERINFO *ui1 = NULL;
+ TCHAR ptszBuf[1024];
+ char serviceName[256];
+ POINT pt;
+
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ SESSION_INFO * parentdat = dat->si;
+
+ GetCursorPos(&pt);
+ ScreenToClient(hwnd, &pt);
+
+ DWORD nItemUnderMouse = (DWORD)SendMessage(GetDlgItem(dat->hwnd, IDC_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
+ if (HIWORD(nItemUnderMouse) == 1)
+ nItemUnderMouse = (DWORD)(-1);
+ else
+ nItemUnderMouse &= 0xFFFF;
+ if (((int)nItemUnderMouse != currentHovered) || (nItemUnderMouse == -1)) {
+ KillTimer(hwnd, 1);
+ break;
+ }
+
+ ui1 = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, currentHovered);
+
+ if (ui1) {
+ ti.cbSize = sizeof(ti);
+ mir_snprintf(serviceName, SIZEOF(serviceName), "%s"MS_GC_PROTO_GETTOOLTIPTEXT, parentdat->pszModule);
+
+ if (ServiceExists(serviceName))
+ mir_sntprintf(ptszBuf, SIZEOF(ptszBuf), _T("%s"), (TCHAR*)CallService(serviceName, (WPARAM)parentdat->ptszID, (LPARAM)ui1->pszUID));
+ else
+ mir_sntprintf(ptszBuf, SIZEOF(ptszBuf), _T("<b>%s:</b>\t%s\n<b>%s:</b>\t%s\n<b>%s:</b>\t%s"),
+ TranslateT("Nick"), ui1->pszNick,
+ TranslateT("Unique id"), ui1->pszUID,
+ TranslateT("Status"), TM_WordToString(parentdat->pStatuses, ui1->Status));
+
+ if (ptszBuf != NULL)
+ if (CallService("mToolTip/ShowTipW", (WPARAM)mir_tstrdup(ptszBuf), (LPARAM)&ti))
+ isToolTip = TRUE;
+ }
+ KillTimer(hwnd, 1);
+ }
+ break;
+ }
+ return CallWindowProc(OldNicklistProc, hwnd, msg, wParam, lParam);
+}
+
+/*
+ * calculate the required rectangle for a string using the given font. This is more
+ * precise than using GetTextExtentPoint...()
+ */
+
+int GetTextPixelSize(TCHAR* pszText, HFONT hFont, BOOL bWidth)
+{
+ HDC hdc;
+ HFONT hOldFont;
+ RECT rc = {0};
+ int i;
+
+ if (!pszText || !hFont)
+ return 0;
+
+ hdc = GetDC(NULL);
+ hOldFont = (HFONT)SelectObject(hdc, hFont);
+ i = 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);
+}
+
+
+/*
+ * the actual group chat session window procedure. Handles the entire chat session window
+ * which is usually a (tabbed) child of a container class window.
+ */
+
+INT_PTR CALLBACK RoomWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ SESSION_INFO * si = NULL;
+ HWND hwndTab = GetParent(hwndDlg);
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ if (dat)
+ si = (SESSION_INFO *)dat->si;
+
+ if (dat == NULL && (uMsg == WM_ACTIVATE || uMsg == WM_SETFOCUS))
+ return 0;
+
+ switch (uMsg) {
+ case WM_INITDIALOG: {
+ int mask;
+ struct TNewWindowData *newData = (struct TNewWindowData *) lParam;
+ struct TWindowData *dat;
+ SESSION_INFO *psi = (SESSION_INFO*)newData->hdbEvent;
+ RECT rc;
+
+ dat = (struct TWindowData *)malloc(sizeof(struct TWindowData));
+ ZeroMemory(dat, sizeof(struct TWindowData));
+ si = psi;
+ dat->si = psi;
+ dat->hContact = psi->hContact;
+ dat->szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)psi->hContact, 0);
+ dat->bType = SESSIONTYPE_CHAT;
+ dat->Panel = new CInfoPanel(dat);
+
+ dat->cache = CContactCache::getContactCache(dat->hContact);
+ dat->cache->updateState();
+ dat->cache->updateUIN();
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ newData->item.lParam = (LPARAM) hwndDlg;
+ TabCtrl_SetItem(hwndTab, newData->iTabID, &newData->item);
+ dat->iTabID = newData->iTabID;
+ dat->pContainer = newData->pContainer;
+ psi->pContainer = newData->pContainer;
+ dat->hwnd = hwndDlg;
+ psi->hWnd = hwndDlg;
+ psi->dat = dat;
+ dat->fIsAutosizingInput = IsAutoSplitEnabled(dat);
+ dat->fLimitedUpdate = false;
+ dat->iInputAreaHeight = -1;
+ if(!dat->pContainer->settings->fPrivate)
+ psi->iSplitterY = g_Settings.iSplitterY;
+ else {
+ if(M->GetByte("Chat", "SyncSplitter", 0))
+ psi->iSplitterY = dat->pContainer->settings->splitterPos - DPISCALEY_S(23);
+ else
+ psi->iSplitterY = g_Settings.iSplitterY;
+ }
+#if defined(__FEAT_EXP_AUTOSPLITTER)
+ if(dat->fIsAutosizingInput)
+ psi->iSplitterY = GetDefaultMinimumInputHeight(dat);
+#endif
+ dat->pWnd = 0;
+ CProxyWindow::add(dat);
+
+ dat->fInsertMode = FALSE;
+
+ dat->codePage = M->GetDword(dat->hContact, "ANSIcodepage", CP_ACP);
+ dat->Panel->getVisibility();
+ dat->Panel->Configure();
+ M->AddWindow(hwndDlg, dat->hContact);
+ BroadCastContainer(dat->pContainer, DM_REFRESHTABINDEX, 0, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETOLECALLBACK, 0, (LPARAM) mREOLECallback);
+
+ BB_InitDlgButtons(dat);
+ DM_InitTip(dat);
+
+ SendMessage(GetDlgItem(hwndDlg,IDC_COLOR), BUTTONSETASPUSHBTN, 0, 0);
+
+ OldSplitterProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTERX), GWLP_WNDPROC, (LONG_PTR)SplitterSubclassProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTERY), GWLP_WNDPROC, (LONG_PTR)SplitterSubclassProc);
+ OldNicklistProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LIST), GWLP_WNDPROC, (LONG_PTR)NicklistSubclassProc);
+ OldLogProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_LOG), GWLP_WNDPROC, (LONG_PTR)LogSubclassProc);
+ OldFilterButtonProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_FILTER), GWLP_WNDPROC, (LONG_PTR)ButtonSubclassProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_COLOR), GWLP_WNDPROC, (LONG_PTR)ButtonSubclassProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_BKGCOLOR), GWLP_WNDPROC, (LONG_PTR)ButtonSubclassProc);
+ OldMessageProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), GWLP_WNDPROC, (LONG_PTR)MessageSubclassProc);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SUBCLASSED, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_AUTOURLDETECT, 1, 0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PANELSPLITTER), GWLP_WNDPROC, (LONG_PTR) SplitterSubclassProc);
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING, 0);
+
+ mask = (int)SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_GETEVENTMASK, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETEVENTMASK, 0, mask | ENM_LINK | ENM_MOUSEEVENTS | ENM_KEYEVENTS);
+
+#if defined(__FEAT_EXP_AUTOSPLITTER)
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE | ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE);
+#else
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE);
+#endif
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_LIMITTEXT, (WPARAM)0x7FFFFFFF, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3));
+ dat->Panel->loadHeight();
+ Utils::enableDlgControl(hwndDlg, IDC_SMILEYBTN, TRUE);
+
+ if (PluginConfig.g_hMenuTrayUnread != 0 && dat->hContact != 0 && dat->szProto != NULL)
+ UpdateTrayMenu(0, dat->wStatus, dat->szProto, dat->szStatus, dat->hContact, FALSE);
+
+ DM_ThemeChanged(dat);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_HIDESELECTION, TRUE, 0);
+
+ CreateWindowEx(0, _T("TSButtonClass"), _T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20),
+ hwndDlg, (HMENU)IDC_CHAT_TOGGLESIDEBAR, g_hInst, NULL);
+
+ GetMYUIN(dat);
+ GetMyNick(dat);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONSETASFLATBTN + 10, 0, PluginConfig.m_bIsXP);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONSETASFLATBTN + 12, 0, (LPARAM)dat->pContainer);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONSETASTOOLBARBUTTON, 0, 1);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Expand or collapse the side bar"), 1);
+
+ dat->hwndIEView = dat->hwndHPP = 0;
+
+ //Chat_SetMessageLog(dat);
+
+ SendMessage(hwndDlg, GC_SETWNDPROPS, 0, 0);
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ SendMessage(hwndDlg, GC_UPDATETITLE, 0, 1);
+ SendMessage(dat->pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc);
+ SetWindowPos(hwndDlg, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), 0);
+ ShowWindow(hwndDlg, SW_SHOW);
+ PostMessage(hwndDlg, GC_UPDATENICKLIST, 0, 0);
+ dat->pContainer->hwndActive = hwndDlg;
+ BB_SetButtonsPos(dat);
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN, 0);
+ }
+ break;
+
+ case WM_SETFOCUS:
+ if (CMimAPI::m_shutDown)
+ break;
+
+ Chat_UpdateWindowState(dat, WM_SETFOCUS);
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ return 1;
+
+ case WM_TIMECHANGE:
+ PostMessage(hwndDlg, GC_REDRAWLOG, 0, 0);
+ break;
+
+ case DM_LOADBUTTONBARICONS: {
+ BB_UpdateIcons(hwndDlg, dat);
+ return 0;
+ }
+
+ case GC_SETWNDPROPS: {
+ //HICON hIcon;
+ COLORREF colour = M->GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR);
+ InitButtons(hwndDlg, si);
+ ConfigureSmileyButton(dat);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETBKGNDCOLOR, 0, colour);
+
+ DM_InitRichEdit(dat);
+ SendDlgItemMessage(hwndDlg, IDOK, BUTTONSETASFLATBTN + 14, 0, 0);
+ {
+ SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETITEMHEIGHT, 0, (LPARAM)g_Settings.iNickListFontHeight);
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_LIST), NULL, TRUE);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_FILTER, BUTTONSETOVERLAYICON, 0,
+ (LPARAM)(si->bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled));
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SendMessage(hwndDlg, GC_REDRAWLOG2, 0, 0);
+ }
+ break;
+
+ case DM_UPDATETITLE:
+ return(SendMessage(hwndDlg, GC_UPDATETITLE, wParam, lParam));
+
+ case GC_UPDATETITLE: {
+ TCHAR szTemp [100];
+ HICON hIcon;
+ BOOL fNoCopy = TRUE;
+ const TCHAR* szNick = dat->cache->getNick();
+
+ if(dat->bWasDeleted)
+ return(0);
+
+ dat->wStatus = si->wStatus;
+
+ if (lstrlen(szNick) > 0) {
+ if (M->GetByte("cuttitle", 0))
+ CutContactName(szNick, dat->newtitle, safe_sizeof(dat->newtitle));
+ else {
+ lstrcpyn(dat->newtitle, szNick, safe_sizeof(dat->newtitle));
+ dat->newtitle[129] = 0;
+ }
+ }
+
+ switch (si->iType) {
+ case GCW_CHATROOM:
+ hIcon = dat->wStatus <= ID_STATUS_OFFLINE ? LoadSkinnedProtoIcon(si->pszModule, ID_STATUS_OFFLINE) : LoadSkinnedProtoIcon(si->pszModule, dat->wStatus);
+ fNoCopy = FALSE;
+ mir_sntprintf(szTemp, SIZEOF(szTemp),
+ (si->nUsersInNicklist == 1) ? CTranslator::get(CTranslator::GEN_MUC_ROOM_TITLE_USER) :
+ CTranslator::get(CTranslator::GEN_MUC_ROOM_TITLE_USERS),
+ si->ptszName, si->nUsersInNicklist, si->bFilterEnabled ? CTranslator::get(CTranslator::GEN_MUC_ROOM_TITLE_FILTER) : _T(""));
+ break;
+ case GCW_PRIVMESS:
+ mir_sntprintf(szTemp, SIZEOF(szTemp),
+ (si->nUsersInNicklist == 1) ? CTranslator::get(CTranslator::GEN_MUC_PRIVSESSION) :
+ CTranslator::get(CTranslator::GEN_MUC_PRIVSESSION_MULTI), si->ptszName, si->nUsersInNicklist);
+ break;
+ case GCW_SERVER:
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s: Server"), si->ptszName);
+ hIcon = LoadIconEx(IDI_CHANMGR, "window", 16, 16);
+ break;
+ }
+
+ if(dat->pWnd) {
+ dat->pWnd->updateTitle(dat->newtitle);
+ dat->pWnd->updateIcon(hIcon);
+ }
+ dat->hTabStatusIcon = hIcon;
+
+ if (lParam)
+ dat->hTabIcon = dat->hTabStatusIcon;
+
+ if (dat->cache->getStatus() != dat->cache->getOldStatus()) {
+ TCITEM item;
+
+ ZeroMemory(&item, sizeof(item));
+ item.mask = TCIF_TEXT;
+
+ lstrcpyn(dat->szStatus, (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)dat->wStatus, GSMDF_TCHAR), 50);
+ dat->szStatus[49] = 0;
+ item.pszText = dat->newtitle;
+ item.cchTextMax = 120;
+ TabCtrl_SetItem(hwndTab, dat->iTabID, &item);
+ }
+ SetWindowText(hwndDlg, szTemp);
+ if (dat->pContainer->hwndActive == hwndDlg) {
+ SendMessage(dat->pContainer->hwnd, DM_UPDATETITLE, (WPARAM)hwndDlg, 1);
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ }
+ }
+ break;
+
+ case GC_UPDATESTATUSBAR:
+ if(dat->bWasDeleted)
+ return(0);
+
+ if (dat->pContainer->hwndActive != hwndDlg || dat->pContainer->hwndStatus == 0 || CMimAPI::m_shutDown || dat->szStatusBar[0])
+ break;
+ if (si->pszModule != NULL) {
+ TCHAR szFinalStatusBarText[512];
+ MODULEINFO* mi=NULL;
+ int x = 12;
+
+ //Mad: strange rare crash here...
+ mi = MM_FindModule(si->pszModule);
+ if(!mi)
+ break;
+
+ if(!mi->ptszModDispName)
+ break;
+
+ x += GetTextPixelSize(mi->ptszModDispName, (HFONT)SendMessage(dat->pContainer->hwndStatus, WM_GETFONT, 0, 0), TRUE);
+ x += GetSystemMetrics(SM_CXSMICON);
+
+ if(dat->Panel->isActive()) {
+ time_t now = time(0);
+ DWORD diff = (now - mi->idleTimeStamp) / 60;
+
+ if((diff >= 1 && diff != mi->lastIdleCheck) || lParam) {
+ mi->lastIdleCheck = diff;
+ if(diff == 0)
+ mi->tszIdleMsg[0] = 0;
+ else if(diff > 59) {
+ DWORD hours = diff / 60;
+ DWORD minutes = diff % 60;
+ mir_sntprintf(mi->tszIdleMsg, 60, CTranslator::get(CTranslator::MUC_SBAR_IDLEFORMAT), hours, hours > 1 ?
+ CTranslator::get(CTranslator::GEN_STRING_HOURS) : CTranslator::get(CTranslator::GEN_STRING_HOUR),
+ minutes, minutes > 1 ? CTranslator::get(CTranslator::GEN_STRING_MINUTES) : CTranslator::get(CTranslator::GEN_STRING_MINUTE));
+ }
+ else
+ mir_sntprintf(mi->tszIdleMsg, 60, CTranslator::get(CTranslator::MUC_SBAR_IDLEFORMAT_SHORT),
+ diff, diff > 1 ? CTranslator::get(CTranslator::GEN_STRING_MINUTES) : CTranslator::get(CTranslator::GEN_STRING_MINUTE));
+ }
+ mir_sntprintf(szFinalStatusBarText, SIZEOF(szFinalStatusBarText), CTranslator::get(CTranslator::MUC_SBAR_ON_SERVER), dat->szMyNickname, mi->ptszModDispName, mi->tszIdleMsg);
+ } else {
+ if (si->ptszStatusbarText)
+ mir_sntprintf(szFinalStatusBarText, SIZEOF(szFinalStatusBarText), _T("%s %s"), mi->ptszModDispName, si->ptszStatusbarText);
+ else {
+ lstrcpyn(szFinalStatusBarText, mi->ptszModDispName, SIZEOF(szFinalStatusBarText));
+ szFinalStatusBarText[511] = 0;
+ }
+ }
+ SendMessage(dat->pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)szFinalStatusBarText);
+ UpdateStatusBar(dat);
+ dat->Panel->Invalidate();
+ if(dat->pWnd)
+ dat->pWnd->Invalidate();
+ return TRUE;
+ }
+ break;
+
+ case WM_SIZE: {
+ UTILRESIZEDIALOG urd;
+ RECT rc;
+ int panelHeight = dat->Panel->getHeight() + 1;
+ LONG cx;
+
+ if (dat->ipFieldHeight == 0)
+ dat->ipFieldHeight = CInfoPanel::m_ipConfig.height1;
+
+ if (wParam == SIZE_MAXIMIZED)
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+
+ if (IsIconic(hwndDlg)) break;
+ ZeroMemory(&urd, sizeof(urd));
+ urd.cbSize = sizeof(urd);
+ urd.hInstance = g_hInst;
+ urd.hwndDlg = hwndDlg;
+ urd.lParam = (LPARAM)si;
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_CHANNEL);
+ urd.pfnResizer = RoomWndResize;
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
+ //mad
+ BB_SetButtonsPos(dat);
+
+ GetClientRect(hwndDlg, &rc);
+ cx = rc.right;
+
+ rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO;
+ rc.right = cx;
+ rc.top = 1;
+ rc.bottom = (panelHeight > CInfoPanel::DEGRADE_THRESHOLD ? rc.top + dat->ipFieldHeight - 2 : panelHeight - 1);
+ dat->rcNick = rc;
+
+ rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO;
+ rc.right = cx;
+ rc.bottom = panelHeight - 2;
+ rc.top = dat->rcNick.bottom + 1;
+ dat->rcUIN = rc;
+
+ if (dat->hwndIEView || dat->hwndHPP)
+ Chat_ResizeIeView(dat);
+ DetermineMinHeight(dat);
+ }
+ 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_EVENT_CONTROL + WM_USER + 500, 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: {
+ BOOL fInactive = (GetForegroundWindow() != dat->pContainer->hwnd || GetActiveWindow() != dat->pContainer->hwnd);
+
+ if (g_Settings.UseDividers && g_Settings.DividersUsePopupConfig) {
+ if (!MessageWindowOpened(0, (LPARAM)hwndDlg))
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ } else if (g_Settings.UseDividers) {
+ if (fInactive)
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ else {
+ if (dat->pContainer->hwndActive != hwndDlg)
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ }
+ }
+
+ if (si->pLogEnd)
+ Log_StreamInEvent(hwndDlg, si->pLog, si, FALSE, FALSE);
+ else
+ SendMessage(hwndDlg, GC_EVENT_CONTROL + WM_USER + 500, WINDOW_CLEARLOG, 0);
+ break;
+ }
+
+ case GC_ACKMESSAGE:
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETREADONLY, FALSE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, WM_SETTEXT, 0, (LPARAM)_T(""));
+ return TRUE;
+
+ case WM_CTLCOLORLISTBOX:
+ SetBkColor((HDC) wParam, g_Settings.crUserListBGColor);
+ return (INT_PTR) hListBkgBrush;
+
+ case WM_MEASUREITEM: {
+ MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *) lParam;
+
+ if (mis->CtlType == ODT_MENU) {
+ if(dat->Panel->isHovered()) {
+ mis->itemHeight = 0;
+ mis->itemWidth = 6;
+ return(TRUE);
+ }
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+ }
+ else
+ mis->itemHeight = g_Settings.iNickListFontHeight;
+ return TRUE;
+ }
+
+ case WM_DRAWITEM: {
+ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam;
+
+ if (dis->CtlType == ODT_MENU) {
+ if(dat->Panel->isHovered()) {
+ DrawMenuItem(dis, (HICON)dis->itemData, 0);
+ return(TRUE);
+ }
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+ }
+ else {
+ if (dis->CtlID == IDC_LIST) {
+ HFONT hFont, hOldFont;
+ HICON hIcon;
+ int offset, x_offset = 0;
+ int height;
+ int index = dis->itemID;
+ USERINFO * ui = UM_FindUserFromIndex(si->pUsers, index);
+ char szIndicator = 0;
+
+ if (ui) {
+ height = dis->rcItem.bottom - dis->rcItem.top;
+
+ if (height&1)
+ height++;
+ if (height == 10)
+ offset = 0;
+ else
+ offset = height / 2;
+ hIcon = SM_GetStatusIcon(si, ui, &szIndicator);
+ hFont = (ui->iStatusEx == 0) ? g_Settings.UserListFont : g_Settings.UserListHeadingsFont;
+ hOldFont = (HFONT) SelectObject(dis->hDC, hFont);
+ SetBkMode(dis->hDC, TRANSPARENT);
+
+ if (dis->itemState & ODS_SELECTED) {
+ FillRect(dis->hDC, &dis->rcItem, g_Settings.SelectionBGBrush);
+ SetTextColor(dis->hDC, g_Settings.nickColors[6]);
+ } else {
+ FillRect(dis->hDC, &dis->rcItem, hListBkgBrush);
+ if (g_Settings.ColorizeNicks && szIndicator != 0) {
+ COLORREF clr;
+
+ switch (szIndicator) {
+ case '@':
+ clr = g_Settings.nickColors[0];
+ break;
+ case '%':
+ clr = g_Settings.nickColors[1];
+ break;
+ case '+':
+ clr = g_Settings.nickColors[2];
+ break;
+ case '!':
+ clr = g_Settings.nickColors[3];
+ break;
+ case '*':
+ clr = g_Settings.nickColors[4];
+ break;
+ }
+ SetTextColor(dis->hDC, clr);
+ } else SetTextColor(dis->hDC, ui->iStatusEx == 0 ? g_Settings.crUserListColor : g_Settings.crUserListHeadingsColor);
+ }
+ x_offset = 2;
+
+ if (g_Settings.ShowContactStatus && g_Settings.ContactStatusFirst && ui->ContactStatus) {
+ HICON hIcon = LoadSkinnedProtoIcon(si->pszModule, ui->ContactStatus);
+ DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ x_offset += 18;
+ }
+
+ if (g_Settings.ClassicIndicators) {
+ char szTemp[3];
+ SIZE szUmode;
+
+ szTemp[1] = 0;
+ szTemp[0] = szIndicator;
+ if (szTemp[0]) {
+ GetTextExtentPoint32A(dis->hDC, szTemp, 1, &szUmode);
+ TextOutA(dis->hDC, x_offset, dis->rcItem.top, szTemp, 1);
+ x_offset += szUmode.cx + 2;
+ } else x_offset += 8;
+ } else {
+ DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 5, hIcon, 10, 10, 0, NULL, DI_NORMAL);
+ x_offset += 12;
+ }
+
+ if (g_Settings.ShowContactStatus && !g_Settings.ContactStatusFirst && ui->ContactStatus) {
+ HICON hIcon = LoadSkinnedProtoIcon(si->pszModule, ui->ContactStatus);
+ DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ x_offset += 18;
+ }
+
+ {
+ SIZE sz;
+
+ if (si->iSearchItem != -1 && si->iSearchItem == index && si->szSearch[0]) {
+ COLORREF clr_orig = GetTextColor(dis->hDC);
+ GetTextExtentPoint32(dis->hDC, ui->pszNick, lstrlen(si->szSearch), &sz);
+ SetTextColor(dis->hDC, RGB(250, 250, 0));
+ TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, lstrlen(si->szSearch));
+ SetTextColor(dis->hDC, clr_orig);
+ x_offset += sz.cx;
+ TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick + lstrlen(si->szSearch), lstrlen(ui->pszNick) - lstrlen(si->szSearch));
+ } else {
+ GetTextExtentPoint32(dis->hDC, ui->pszNick, lstrlen(ui->pszNick), &sz);
+ TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, lstrlen(ui->pszNick));
+ SelectObject(dis->hDC, hOldFont);
+ }
+ }
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+ case WM_CONTEXTMENU:{
+ //mad
+ DWORD idFrom=GetDlgCtrlID((HWND)wParam);
+ if(idFrom>=MIN_CBUTTONID&&idFrom<=MAX_CBUTTONID)
+ BB_CustomButtonClick(dat,idFrom,(HWND) wParam,1);
+ }break;
+ //
+ case GC_UPDATENICKLIST: {
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_GETTOPINDEX, 0, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETCOUNT, si->nUsersInNicklist, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETTOPINDEX, i, 0);
+ SendMessage(hwndDlg, GC_UPDATETITLE, 0, 0);
+ }
+ break;
+
+ case GC_EVENT_CONTROL + WM_USER + 500: {
+ switch (wParam) {
+ case SESSION_OFFLINE:
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ SendMessage(si->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ return TRUE;
+
+ case SESSION_ONLINE:
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ return TRUE;
+
+ case WINDOW_HIDDEN:
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 1);
+ return TRUE;
+
+ case WINDOW_CLEARLOG:
+ SetDlgItemText(hwndDlg, IDC_CHAT_LOG, _T(""));
+ return TRUE;
+
+ case SESSION_TERMINATE:
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+
+ si->wState &= ~STATE_TALK;
+ dat->bWasDeleted = 1;
+ DBWriteContactSettingWord(si->hContact, si->pszModule , "ApparentMode", (LPARAM) 0);
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, lParam == 2 ? lParam : 1);
+ 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 (M->GetByte("Chat", "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 DM_SPLITTERMOVED: {
+ POINT pt;
+ RECT rc;
+ RECT rcLog;
+ BOOL bFormat = TRUE; //IsWindowVisible(GetDlgItem(hwndDlg,IDC_SMILEY));
+
+ static int x = 0;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_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;
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ } else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SPLITTERY) || lParam == -1) {
+ int oldSplitterY;
+ GetClientRect(hwndDlg, &rc);
+ rc.top += (dat->Panel->isActive() ? dat->Panel->getHeight() + 40 : 30);
+ pt.x = 0;
+ pt.y = wParam;
+ ScreenToClient(hwndDlg, &pt);
+
+ oldSplitterY = si->iSplitterY;
+ si->iSplitterY = bFormat ? rc.bottom - pt.y + DPISCALEY_S(1) : rc.bottom - pt.y + DPISCALEY_S(20);
+ if (si->iSplitterY < DPISCALEY_S(23))
+ si->iSplitterY = DPISCALEY_S(23);
+ if (si->iSplitterY > rc.bottom - rc.top - DPISCALEY_S(40))
+ si->iSplitterY = rc.bottom - rc.top - DPISCALEY_S(40);
+ g_Settings.iSplitterY = si->iSplitterY;
+ CSkin::UpdateToolbarBG(dat, RDW_ALLCHILDREN);
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ } else if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_PANELSPLITTER)) {
+ RECT rc;
+ POINT pt;
+ pt.x = 0;
+ pt.y = wParam;
+ ScreenToClient(hwndDlg, &pt);
+ GetClientRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rc);
+ if ((pt.y + 2 >= MIN_PANELHEIGHT + 2) && (pt.y + 2 < 100) && (pt.y + 2 < rc.bottom - 30))
+ dat->Panel->setHeight(pt.y + 2);
+ dat->panelWidth = -1;
+ RedrawWindow(hwndDlg, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
+ if(M->isAero())
+ InvalidateRect(GetParent(hwndDlg), NULL, FALSE);
+ SendMessage(hwndDlg, WM_SIZE, DM_SPLITTERMOVED, 0);
+ break;
+ }
+ }
+ break;
+
+ case GC_FIREHOOK:
+ if (lParam) {
+ GCHOOK* gch = (GCHOOK *) lParam;
+ NotifyEventHooks(hSendEvent, 0, (WPARAM)gch);
+ if (gch->pDest) {
+ mir_free(gch->pDest->pszID);
+ mir_free(gch->pDest->pszModule);
+ mir_free(gch->pDest);
+ }
+ mir_free(gch->ptszText);
+ mir_free(gch->ptszUID);
+ mir_free(gch);
+ }
+ break;
+
+ case GC_CHANGEFILTERFLAG:
+ if (si->iLogFilterFlags == 0 && si->bFilterEnabled)
+ SendMessage(hwndDlg, WM_COMMAND, IDC_FILTER, 0);
+ break;
+
+ case GC_SHOWFILTERMENU: {
+ RECT rcFilter, rcLog;
+ POINT pt;
+
+ si->hwndFilter = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER), dat->pContainer->hwnd, FilterWndProc, (LPARAM)si);
+ TranslateDialogDefault(si->hwndFilter);
+
+ GetClientRect(si->hwndFilter, &rcFilter);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rcLog);
+ pt.x = rcLog.right;
+ pt.y = rcLog.bottom;
+ ScreenToClient(dat->pContainer->hwnd, &pt);
+
+ SetWindowPos(si->hwndFilter, HWND_TOP, pt.x - rcFilter.right, pt.y - rcFilter.bottom, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
+ }
+ break;
+
+ case DM_SPLITTERGLOBALEVENT: {
+ DM_SplitterGlobalEvent(dat, wParam, lParam);
+ return(0);
+ }
+
+ case GC_SHOWCOLORCHOOSER: {
+ HWND ColorWindow;
+ RECT rc;
+ BOOL bFG = lParam == IDC_COLOR ? TRUE : FALSE;
+ COLORCHOOSER *pCC = (COLORCHOOSER *)mir_alloc(sizeof(COLORCHOOSER));
+
+ GetWindowRect(GetDlgItem(hwndDlg, bFG ? IDC_COLOR : IDC_BKGCOLOR), &rc);
+ pCC->hWndTarget = GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE);
+ pCC->pModule = MM_FindModule(si->pszModule);
+ pCC->xPosition = rc.left + 3;
+ pCC->yPosition = IsWindowVisible(GetDlgItem(hwndDlg, IDC_COLOR)) ? rc.top - 1 : rc.top + 20;
+ pCC->bForeground = bFG;
+ pCC->si = si;
+
+ ColorWindow = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_COLORCHOOSER), hwndDlg, DlgProcColorToolWindow, (LPARAM) pCC);
+ }
+ break;
+
+ case GC_SCROLLTOBOTTOM: {
+ return(DM_ScrollToBottom(dat, wParam, lParam));
+ }
+
+ case WM_TIMER:
+ if (wParam == TIMERID_FLASHWND)
+ if (dat->mayFlashTab)
+ FlashTab(dat, hwndTab, dat->iTabID, &dat->bTabFlash, TRUE, dat->hTabIcon);
+ break;
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_ACTIVE) {
+ dat->pContainer->hwndSaved = 0;
+ break;
+ }
+
+ //fall through
+ case WM_MOUSEACTIVATE:
+ Chat_UpdateWindowState(dat, WM_ACTIVATE);
+ return 1;
+
+ case WM_NOTIFY: {
+ LPNMHDR pNmhdr = (LPNMHDR)lParam;
+ switch (pNmhdr->code) {
+ case EN_MSGFILTER: {
+ UINT msg = ((MSGFILTER *) lParam)->msg;
+ WPARAM wp = ((MSGFILTER *) lParam)->wParam;
+ LPARAM lp = ((MSGFILTER *) lParam)->lParam;
+
+ BOOL isShift, isCtrl, isMenu;
+ KbdState(dat, isShift, isCtrl, isMenu);
+
+ MSG message;
+ message.hwnd = hwndDlg;
+ message.message = msg;
+ message.lParam = lp;
+ message.wParam = wp;
+
+ if(msg == WM_SYSKEYUP) {
+ if(wp == VK_MENU) {
+ if(!dat->fkeyProcessed && !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000) && !(lp & (1 << 24)))
+ dat->pContainer->MenuBar->autoShow();
+ }
+ return(_dlgReturn(hwndDlg, 0));
+ }
+
+ if(msg == WM_MOUSEMOVE) {
+ POINT pt;
+ GetCursorPos(&pt);
+ DM_DismissTip(dat, pt);
+ dat->Panel->trackMouse(pt);
+ break;
+ }
+ if(msg == WM_KEYDOWN) {
+ if ((wp == VK_INSERT && isShift && !isCtrl && !isMenu) || (wp == 'V' && !isShift && !isMenu && isCtrl)) {
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_PASTESPECIAL, CF_TEXTT, 0);
+ ((MSGFILTER *) lParam)->msg = WM_NULL;
+ ((MSGFILTER *) lParam)->wParam = 0;
+ ((MSGFILTER *) lParam)->lParam = 0;
+ return(_dlgReturn(hwndDlg, 1));
+ }
+ }
+
+ if(msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN)
+ dat->pContainer->MenuBar->Cancel();
+
+ if ((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && !(GetKeyState(VK_RMENU) & 0x8000)) {
+
+ if(DM_GenericHotkeysCheck(&message, dat)) {
+ dat->fkeyProcessed = true;
+ return(_dlgReturn(hwndDlg, 1));
+ }
+
+ LRESULT mim_hotkey_check = CallService(MS_HOTKEY_CHECK, (WPARAM)&message, (LPARAM)(TABSRMM_HK_SECTION_GC));
+ if(mim_hotkey_check)
+ dat->fkeyProcessed = true;
+ switch(mim_hotkey_check) { // nothing (yet) FIXME
+ case TABSRMM_HK_CHANNELMGR:
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHANMGR, BN_CLICKED), 0);
+ return(_dlgReturn(hwndDlg, 1));
+ case TABSRMM_HK_FILTERTOGGLE:
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_FILTER, BN_CLICKED), 0);
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_FILTER), NULL, TRUE);
+ return(_dlgReturn(hwndDlg, 1));
+ case TABSRMM_HK_LISTTOGGLE:
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_SHOWNICKLIST, BN_CLICKED), 0);
+ return(_dlgReturn(hwndDlg, 1));
+ case TABSRMM_HK_MUC_SHOWSERVER:
+ if(si->iType != GCW_SERVER)
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, L"/servershow", (LPARAM)NULL);
+ return(_dlgReturn(hwndDlg, 1));
+ default:
+ break;
+ }
+ }
+
+ if(msg == WM_KEYDOWN && wp == VK_TAB) {
+ if(((NMHDR *)lParam)->idFrom == IDC_CHAT_LOG) {
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ return(_dlgReturn(hwndDlg, 1));
+ }
+ }
+
+ if (pNmhdr->idFrom == IDC_CHAT_LOG && ((MSGFILTER *) lParam)->msg == WM_RBUTTONUP) {
+ CHARRANGE sel, all = { 0, -1 };
+ POINT pt;
+ UINT uID = 0;
+ HMENU hMenu = 0;
+ TCHAR pszWord[4096];
+ int pos;
+
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(pNmhdr->hwndFrom, &pt);
+
+ { // fixing stuff for searches
+ long iCharIndex, iLineIndex, iChars, start, end, iRes;
+ POINTL ptl;
+
+ pszWord[0] = '\0';
+ ptl.x = (LONG)pt.x;
+ ptl.y = (LONG)pt.y;
+ ScreenToClient(GetDlgItem(hwndDlg, IDC_CHAT_LOG), (LPPOINT)&ptl);
+ iCharIndex = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_CHARFROMPOS, 0, (LPARAM) & ptl);
+ if (iCharIndex < 0)
+ break;
+ iLineIndex = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_EXLINEFROMCHAR, 0, (LPARAM)iCharIndex);
+ iChars = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_LINEINDEX, (WPARAM)iLineIndex, 0);
+ start = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_FINDWORDBREAK, WB_LEFT, iCharIndex);//-iChars;
+ end = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_FINDWORDBREAK, WB_RIGHT, iCharIndex);//-iChars;
+
+ if (end - start > 0) {
+ TEXTRANGE tr;
+ CHARRANGE cr;
+ static char szTrimString[] = ":;,.!?\'\"><()[]- \r\n";
+ ZeroMemory(&tr, sizeof(TEXTRANGE));
+
+ cr.cpMin = start;
+ cr.cpMax = end;
+ tr.chrg = cr;
+ tr.lpstrText = (TCHAR *)pszWord;
+ iRes = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_GETTEXTRANGE, 0, (LPARAM) & tr);
+
+ if (iRes > 0) {
+ int iLen = lstrlen(pszWord) - 1;
+ while (iLen >= 0 && strchr(szTrimString, pszWord[iLen])) {
+ pszWord[iLen] = '\0';
+ iLen--;
+ }
+ }
+ }
+ }
+
+ uID = CreateGCMenu(hwndDlg, &hMenu, 1, pt, si, NULL, pszWord);
+
+ if ((uID > 800 && uID < 1400) || uID == CP_UTF8 || uID == 20866) {
+ dat->codePage = uID;
+ M->WriteDword(dat->hContact, SRMSGMOD_T, "ANSIcodepage", dat->codePage);
+ } else if (uID == 500) {
+ dat->codePage = CP_ACP;
+ DBDeleteContactSetting(dat->hContact, SRMSGMOD_T, "ANSIcodepage");
+ } else {
+ switch (uID) {
+ case 0:
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ break;
+
+ case ID_COPYALL:
+ SendMessage(pNmhdr->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel);
+ SendMessage(pNmhdr->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all);
+ SendMessage(pNmhdr->hwndFrom, WM_COPY, 0, 0);
+ SendMessage(pNmhdr->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel);
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ break;
+
+ case ID_CLEARLOG:
+ ClearLog(dat);
+ break;
+
+ case ID_SEARCH_GOOGLE: {
+ char szURL[4096];
+ if (pszWord[0]) {
+ mir_snprintf(szURL, sizeof(szURL), "http://www.google.com/search?q=" TCHAR_STR_PARAM, pszWord);
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) szURL);
+ }
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ }
+ break;
+
+ case ID_SEARCH_WIKIPEDIA: {
+ char szURL[4096];
+ if (pszWord[0]) {
+ mir_snprintf(szURL, sizeof(szURL), "http://en.wikipedia.org/wiki/" TCHAR_STR_PARAM, pszWord);
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) szURL);
+ }
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ }
+ break;
+
+ default:
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_LOGMENU, NULL, NULL, (LPARAM)uID);
+ break;
+ }
+ }
+ if (si->iType != GCW_SERVER && !(si->dwFlags & GC_UNICODE)) {
+ pos = GetMenuItemCount(hMenu);
+ RemoveMenu(hMenu, pos - 1, MF_BYPOSITION);
+ RemoveMenu(PluginConfig.g_hMenuEncoding, 1, MF_BYPOSITION);
+ }
+ DestroyGCMenu(&hMenu, 5);
+ }
+ break;
+ }
+
+ case EN_REQUESTRESIZE: {
+ if(pNmhdr->idFrom == IDC_CHAT_MESSAGE) {
+ REQRESIZE *rr = (REQRESIZE *)lParam;
+ DM_HandleAutoSizeRequest(dat, rr);
+ }
+ break;
+ }
+
+ case EN_LINK:
+ if (pNmhdr->idFrom == IDC_CHAT_LOG) {
+ switch (((ENLINK *) lParam)->msg) {
+ case WM_SETCURSOR:
+
+ if (g_Settings.ClickableNicks) {
+ if (!hCurHyperlinkHand)
+ hCurHyperlinkHand = LoadCursor(NULL, IDC_HAND);
+ if (hCurHyperlinkHand != GetCursor())
+ SetCursor(hCurHyperlinkHand);
+ return TRUE;
+ }
+ break;
+
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_LBUTTONDBLCLK: {
+ TEXTRANGE tr;
+ CHARRANGE sel;
+ BOOL isLink = FALSE;
+ UINT msg = ((ENLINK *) lParam)->msg;
+
+ dat->pContainer->MenuBar->Cancel();
+
+ tr.lpstrText = NULL;
+ SendMessage(pNmhdr->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin != sel.cpMax)
+ break;
+ tr.chrg = ((ENLINK *) lParam)->chrg;
+ tr.lpstrText = (TCHAR *)mir_alloc(sizeof(TCHAR) * (tr.chrg.cpMax - tr.chrg.cpMin + 2));
+ SendMessage(pNmhdr->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM) & tr);
+
+ isLink = IsStringValidLink(tr.lpstrText);
+
+ if (isLink) {
+ char* pszUrl = t2a(tr.lpstrText, 0);
+ if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN) {
+ HMENU hSubMenu;
+ POINT pt;
+
+ hSubMenu = GetSubMenu(g_hMenu, 2);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hSubMenu, 0);
+ 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:
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) pszUrl);
+ break;
+ case ID_CURR:
+ CallService(MS_UTILS_OPENURL, 0, (LPARAM) pszUrl);
+ break;
+ case ID_COPY: {
+ HGLOBAL hData;
+ if (!OpenClipboard(hwndDlg))
+ break;
+ EmptyClipboard();
+ hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR) * (lstrlen(tr.lpstrText) + 1));
+ lstrcpy((TCHAR*)GlobalLock(hData), tr.lpstrText);
+ GlobalUnlock(hData);
+ SetClipboardData(CF_UNICODETEXT, hData);
+ }
+ CloseClipboard();
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ break;
+ }
+ mir_free(tr.lpstrText);
+ mir_free(pszUrl);
+ return TRUE;
+ } else if (((ENLINK *) lParam)->msg == WM_LBUTTONUP) {
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM) pszUrl);
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ mir_free(tr.lpstrText);
+ mir_free(pszUrl);
+ return TRUE;
+ }
+ } else if (g_Settings.ClickableNicks) { // clicked a nick name
+ CHARRANGE chr;
+ TEXTRANGE tr2;
+ TCHAR tszAplTmpl[] = _T("%s:"),
+ *tszAppeal, *tszTmp;
+ size_t st;
+
+ if (msg == WM_RBUTTONDOWN) {
+ USERINFO *ui = si->pUsers;
+ HMENU hMenu = 0;
+ USERINFO uiNew;
+ while (ui) {
+ if (!lstrcmp(ui->pszNick, tr.lpstrText)) {
+ POINT pt;
+ UINT uID;
+
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+ CopyMemory(&uiNew, ui, sizeof(USERINFO));
+ uID = CreateGCMenu(hwndDlg, &hMenu, 0, pt, si, uiNew.pszUID, NULL);
+ switch (uID) {
+ case 0:
+ break;
+
+ case ID_MESS:
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ break;
+
+ default:
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_NICKLISTMENU, ui->pszUID, NULL, (LPARAM)uID);
+ break;
+ }
+ DestroyGCMenu(&hMenu, 1);
+ return TRUE;
+ }
+ ui = ui->next;
+ }
+ return TRUE;
+ }
+ else if (msg == WM_LBUTTONUP) {
+ USERINFO *ui = si->pUsers;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_EXGETSEL, 0, (LPARAM) &chr);
+ tszTmp = tszAppeal = (TCHAR *) malloc((lstrlen(tr.lpstrText) + lstrlen(tszAplTmpl) + 3) * sizeof(TCHAR));
+ tr2.lpstrText = (LPTSTR) malloc(sizeof(TCHAR) * 2);
+ if (chr.cpMin) {
+ /* prepend nick with space if needed */
+ tr2.chrg.cpMin = chr.cpMin - 1;
+ tr2.chrg.cpMax = chr.cpMin;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_GETTEXTRANGE, 0, (LPARAM) &tr2);
+ if (! _istspace(*tr2.lpstrText))
+ *tszTmp++ = _T(' ');
+ _tcscpy(tszTmp, tr.lpstrText);
+ }
+ else
+ /* in the beginning of the message window */
+ _stprintf(tszAppeal, tszAplTmpl, tr.lpstrText);
+ st = lstrlen(tszAppeal);
+ if (chr.cpMax != -1) {
+ tr2.chrg.cpMin = chr.cpMax;
+ tr2.chrg.cpMax = chr.cpMax + 1;
+ /* if there is no space after selection,
+ or there is nothing after selection at all... */
+ if (! SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_GETTEXTRANGE, 0, (LPARAM) &tr2) || ! _istspace(*tr2.lpstrText)) {
+ tszAppeal[st++] = _T(' ');
+ tszAppeal[st++] = _T('\0');
+ }
+ }
+ else {
+ tszAppeal[st++] = _T(' ');
+ tszAppeal[st++] = _T('\0');
+ }
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_REPLACESEL, FALSE, (LPARAM)tszAppeal);
+ free((void *) tr2.lpstrText);
+ free((void *) tszAppeal);
+ }
+ }
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ mir_free(tr.lpstrText);
+ return TRUE;
+ }
+ }
+ return TRUE;
+ }
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_LBUTTONDOWN: {
+ POINT tmp; //+ Protogenes
+ POINTS cur; //+ Protogenes
+ GetCursorPos(&tmp); //+ Protogenes
+ if(!dat->Panel->isHovered()) {
+ cur.x = (SHORT)tmp.x; //+ Protogenes
+ cur.y = (SHORT)tmp.y; //+ Protogenes
+ SendMessage(dat->pContainer->hwnd, WM_NCLBUTTONDOWN, HTCAPTION, *((LPARAM*)(&cur))); //+ Protogenes
+ }
+ break;
+ }
+
+ case WM_LBUTTONUP: {
+ POINT tmp; //+ Protogenes
+ POINTS cur; //+ Protogenes
+ GetCursorPos(&tmp); //+ Protogenes
+ if(dat->Panel->isHovered())
+ dat->Panel->handleClick(tmp);
+ else {
+ cur.x = (SHORT)tmp.x; //+ Protogenes
+ cur.y = (SHORT)tmp.y; //+ Protogenes
+ SendMessage(dat->pContainer->hwnd, WM_NCLBUTTONUP, HTCAPTION, *((LPARAM*)(&cur))); //+ Protogenes
+ }
+ break;
+ }
+
+ case WM_MOUSEMOVE: {
+ POINT pt;
+ GetCursorPos(&pt);
+ DM_DismissTip(dat, pt);
+ dat->Panel->trackMouse(pt);
+ break;
+ }
+ case WM_APPCOMMAND: {
+ DWORD cmd = GET_APPCOMMAND_LPARAM(lParam);
+ if (cmd == APPCOMMAND_BROWSER_BACKWARD || cmd == APPCOMMAND_BROWSER_FORWARD) {
+ SendMessage(dat->pContainer->hwnd, DM_SELECTTAB, cmd == APPCOMMAND_BROWSER_BACKWARD ? DM_SELECT_PREV : DM_SELECT_NEXT, 0);
+ return 1;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ //mad
+ if(LOWORD(wParam)>=MIN_CBUTTONID&&LOWORD(wParam)<=MAX_CBUTTONID){
+ BB_CustomButtonClick(dat,LOWORD(wParam) ,GetDlgItem(hwndDlg,LOWORD(wParam)),0);
+ break;
+ }
+ //
+ switch (LOWORD(wParam)) {
+ case IDC_LIST:
+ if (HIWORD(wParam) == LBN_DBLCLK) {
+ TVHITTESTINFO hti;
+ int item;
+ USERINFO * ui;
+
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(GetDlgItem(hwndDlg, IDC_LIST), &hti.pt);
+
+ item = LOWORD(SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y)));
+ ui = UM_FindUserFromIndex(si->pUsers, item);
+ //ui = SM_GetUserFromIndex(si->pszID, si->pszModule, item);
+ if (ui) {
+ if (g_Settings.DoubleClick4Privat ? GetKeyState(VK_SHIFT) & 0x8000 : !(GetKeyState(VK_SHIFT) & 0x8000)) {
+ LRESULT lResult = (LRESULT)SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_GETSEL, (WPARAM)NULL, (LPARAM)NULL);
+ int start = LOWORD(lResult);
+ TCHAR* pszName = (TCHAR*)alloca(sizeof(TCHAR) * (lstrlen(ui->pszUID) + 3));
+ if (start == 0)
+ mir_sntprintf(pszName, lstrlen(ui->pszUID) + 3, _T("%s: "), ui->pszUID);
+ else
+ mir_sntprintf(pszName, lstrlen(ui->pszUID) + 2, _T("%s "), ui->pszUID);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_REPLACESEL, FALSE, (LPARAM) pszName);
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ } else DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ }
+
+ return TRUE;
+ } else if (HIWORD(wParam) == LBN_KILLFOCUS)
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_LIST), NULL, NULL, RDW_INVALIDATE);
+ break;
+
+ case IDC_CHAT_TOGGLESIDEBAR:
+ SendMessage(dat->pContainer->hwnd, WM_COMMAND, IDC_TOGGLESIDEBAR, 0);
+ break;
+
+ case IDCANCEL:
+ ShowWindow(dat->pContainer->hwnd, SW_MINIMIZE);
+ return FALSE;
+
+ case IDOK: {
+ char* pszRtf;
+ TCHAR* ptszText/*, *p1*/;
+ MODULEINFO* mi;
+ bool fSound = true;
+
+ if (GetSendButtonState(hwndDlg) == PBS_DISABLED)
+ break;
+
+ mi = MM_FindModule(si->pszModule);
+
+ pszRtf = Chat_Message_GetFromStream(hwndDlg, si);
+ SM_AddCommand(si->ptszID, si->pszModule, pszRtf);
+ ptszText = Chat_DoRtfToTags(pszRtf, si);
+ DoTrimMessage(ptszText);
+
+ if(mi && mi->bAckMsg) {
+ Utils::enableDlgControl(hwndDlg, IDC_CHAT_MESSAGE, FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETREADONLY, TRUE, 0);
+ } else SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, WM_SETTEXT, 0, (LPARAM)_T(""));
+
+ Utils::enableDlgControl(hwndDlg, IDOK, FALSE);
+
+ if(ptszText[0] == '/' || si->iType == GCW_SERVER)
+ fSound = false;
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, ptszText, (LPARAM)NULL);
+ mi->idleTimeStamp = time(0);
+ mi->lastIdleCheck = 0;
+ SM_BroadcastMessage(si->pszModule, GC_UPDATESTATUSBAR, 0, 1, TRUE);
+ if (dat && dat->pContainer) {
+ if (fSound && !nen_options.iNoSounds && !(dat->pContainer->dwFlags & CNT_NOSOUND))
+ SkinPlaySound("ChatSent");
+ }
+ mir_free(pszRtf);
+ mir_free(ptszText);
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ }
+ break;
+
+ case IDC_SHOWNICKLIST:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST)))
+ break;
+ if (si->iType == GCW_SERVER)
+ break;
+
+ si->bNicklistEnabled = !si->bNicklistEnabled;
+
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ if (CSkin::m_skinEnabled)
+ InvalidateRect(hwndDlg, NULL, TRUE);
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+ break;
+
+ case IDC_CHAT_MESSAGE:
+ if (g_Settings.MathMod)
+ MTH_updateMathWindow(dat);
+
+ if (HIWORD(wParam) == EN_CHANGE) {
+ if (dat->pContainer->hwndActive == hwndDlg)
+ UpdateReadChars(dat);
+ dat->dwLastActivity = GetTickCount();
+ dat->pContainer->dwLastActivity = dat->dwLastActivity;
+ SendDlgItemMessage(hwndDlg, IDOK, BUTTONSETASFLATBTN + 14, GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE)) != 0, 0);
+ Utils::enableDlgControl(hwndDlg, IDOK, GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE)) != 0);
+ }
+ break;
+
+ case IDC_SMILEY:
+ case IDC_SMILEYBTN: {
+ SMADD_SHOWSEL3 smaddInfo = {0};
+ RECT rc;
+
+ if (lParam == 0)
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_SMILEYBTN), &rc);
+ else
+ GetWindowRect((HWND)lParam, &rc);
+ smaddInfo.cbSize = sizeof(SMADD_SHOWSEL3);
+ smaddInfo.hwndTarget = GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE);
+ smaddInfo.targetMessage = EM_REPLACESEL;
+ smaddInfo.targetWParam = TRUE;
+ smaddInfo.Protocolname = si->pszModule;
+ smaddInfo.Direction = 0;
+ smaddInfo.xPosition = rc.left;
+ smaddInfo.yPosition = rc.top + 24;
+ smaddInfo.hContact = si->hContact;
+ smaddInfo.hwndParent = dat->pContainer->hwnd;
+ if (PluginConfig.g_SmileyAddAvail)
+ CallService(MS_SMILEYADD_SHOWSELECTION, 0, (LPARAM) &smaddInfo);
+ }
+ break;
+
+ case IDC_CHAT_HISTORY: {
+ MODULEINFO * pInfo = MM_FindModule(si->pszModule);
+
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHAT_HISTORY)))
+ break;
+
+ if (ServiceExists("MSP/HTMLlog/ViewLog") && strstr(si->pszModule, "IRC")) {
+ char szName[MAX_PATH];
+
+ WideCharToMultiByte(CP_ACP, 0, si->ptszName, -1, szName, MAX_PATH, 0, 0);
+ szName[MAX_PATH - 1] = 0;
+ CallService("MSP/HTMLlog/ViewLog", (WPARAM)si->pszModule, (LPARAM)szName);
+ } else if (pInfo)
+ ShellExecute(hwndDlg, NULL, GetChatLogsFilename(si, 0), NULL, NULL, SW_SHOW);
+ }
+ break;
+
+ case IDC_CHAT_CLOSE:
+ SendMessage(hwndDlg, WM_CLOSE, 0, 1);
+ break;
+
+ case IDC_CHANMGR:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHANMGR)))
+ break;
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_CHANMGR, NULL, NULL, (LPARAM)NULL);
+ break;
+
+ case IDC_FILTER:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FILTER)))
+ break;
+
+ if (si->iLogFilterFlags == 0 && !si->bFilterEnabled) {
+ MessageBox(0, CTranslator::get(CTranslator::GEN_MUC_FILTER_ERROR), CTranslator::get(CTranslator::GEN_MUC_FILTER_ERROR_TITLE), MB_OK);
+ si->bFilterEnabled = 0;
+ } else
+ si->bFilterEnabled = !si->bFilterEnabled;
+
+ SendDlgItemMessage(hwndDlg, IDC_FILTER, BUTTONSETOVERLAYICON, 0,
+ (LPARAM)(si->bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled));
+
+ if (si->bFilterEnabled && M->GetByte("Chat", "RightClickFilter", 0) == 0) {
+ SendMessage(hwndDlg, GC_SHOWFILTERMENU, 0, 0);
+ break;
+ }
+ SendMessage(hwndDlg, GC_REDRAWLOG, 0, 0);
+ SendMessage(hwndDlg, GC_UPDATETITLE, 0, 0);
+ M->WriteByte(si->hContact, "Chat", "FilterEnabled", (BYTE)si->bFilterEnabled);
+ break;
+
+ case IDC_BKGCOLOR: {
+ CHARFORMAT2 cf;
+
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwEffects = 0;
+
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BKGCOLOR)))
+ break;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_BKGCOLOR)) {
+ if (M->GetByte("Chat", "RightClickFilter", 0) == 0)
+ SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_BKGCOLOR);
+ else if (si->bBGSet) {
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = MM_FindModule(si->pszModule)->crColors[si->iBG];
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } else {
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = (COLORREF)M->GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ break;
+
+ case IDC_COLOR: {
+ CHARFORMAT2 cf;
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwEffects = 0;
+
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_COLOR)))
+ break;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_COLOR)) {
+ if (M->GetByte("Chat", "RightClickFilter", 0) == 0)
+ SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_COLOR);
+ else if (si->bFGSet) {
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = MM_FindModule(si->pszModule)->crColors[si->iFG];
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } else {
+ COLORREF cr;
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &cr, FONTMODULE);
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = cr;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ break;
+
+ case IDC_CHAT_BOLD:
+ case IDC_ITALICS:
+ case IDC_CHAT_UNDERLINE: {
+ CHARFORMAT2 cf;
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE;
+ cf.dwEffects = 0;
+
+ if (LOWORD(wParam) == IDC_CHAT_BOLD && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHAT_BOLD)))
+ break;
+ if (LOWORD(wParam) == IDC_ITALICS && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_ITALICS)))
+ break;
+ if (LOWORD(wParam) == IDC_CHAT_UNDERLINE && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHAT_UNDERLINE)))
+ break;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_BOLD))
+ cf.dwEffects |= CFE_BOLD;
+ if (IsDlgButtonChecked(hwndDlg, IDC_ITALICS))
+ cf.dwEffects |= CFE_ITALIC;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_UNDERLINE))
+ cf.dwEffects |= CFE_UNDERLINE;
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ break;
+
+ case WM_KEYDOWN:
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ break;
+
+ case WM_MOVE:
+ break;
+
+ case WM_ERASEBKGND: {
+ HDC hdc = (HDC)wParam;
+ RECT rcClient, rcWindow, rc;
+ CSkinItem *item;
+ POINT pt;
+ UINT item_ids[3] = {ID_EXTBKUSERLIST, ID_EXTBKHISTORY, ID_EXTBKINPUTAREA};
+ UINT ctl_ids[3] = {IDC_LIST, IDC_CHAT_LOG, IDC_CHAT_MESSAGE};
+ int i;
+ bool fAero = M->isAero();
+ bool fInfoPanel = dat->Panel->isActive();
+ HANDLE hbp = 0;
+ HDC hdcMem = 0;
+ HBITMAP hbm, hbmOld;
+
+ GetClientRect(hwndDlg, &rcClient);
+ LONG cx = rcClient.right - rcClient.left;
+ LONG cy = rcClient.bottom - rcClient.top;
+
+ if(CMimAPI::m_haveBufferedPaint)
+ hbp = CSkin::InitiateBufferedPaint(hdc, rcClient, hdcMem);
+ else {
+ hdcMem = CreateCompatibleDC(hdc);
+ hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc);
+ hbmOld = (HBITMAP)SelectObject(hdcMem, hbm);
+ }
+
+ if(CSkin::m_skinEnabled && !fAero) {
+ CSkin::SkinDrawBG(hwndDlg, dat->pContainer->hwnd, dat->pContainer, &rcClient, hdcMem);
+ for (i = 0; i < 3; i++) {
+ item = &SkinItems[item_ids[i]];
+ if (!item->IGNORED) {
+
+ GetWindowRect(GetDlgItem(hwndDlg, ctl_ids[i]), &rcWindow);
+ pt.x = rcWindow.left;
+ pt.y = rcWindow.top;
+ ScreenToClient(hwndDlg, &pt);
+ rc.left = pt.x - item->MARGIN_LEFT;
+ rc.top = pt.y - item->MARGIN_TOP;
+ rc.right = rc.left + item->MARGIN_RIGHT + (rcWindow.right - rcWindow.left) + item->MARGIN_LEFT;
+ rc.bottom = rc.top + item->MARGIN_BOTTOM + (rcWindow.bottom - rcWindow.top) + item->MARGIN_TOP;
+ CSkin::DrawItem(hdcMem, &rc, item);
+ }
+ }
+ }
+ else {
+ CSkin::FillBack(hdcMem, &rcClient);
+
+ if(M->isAero()) {
+ LONG temp = rcClient.bottom;
+ rcClient.bottom = dat->Panel->isActive() ? dat->Panel->getHeight() + 5 : 5;
+ FillRect(hdcMem, &rcClient, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ rcClient.bottom = temp;
+ }
+ }
+
+ GetClientRect(hwndDlg, &rc);
+ dat->Panel->renderBG(hdcMem, rc, &SkinItems[ID_EXTBKINFOPANELBG], fAero);
+
+
+ dat->Panel->renderContent(hdcMem);
+
+ if(!CSkin::m_skinEnabled)
+ CSkin::RenderToolbarBG(dat, hdcMem, rcClient);
+
+ if(hbp)
+ CSkin::FinalizeBufferedPaint(hbp, &rcClient);
+ else {
+ BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY);
+ SelectObject(hdcMem, hbmOld);
+ DeleteObject(hbm);
+ DeleteDC(hdcMem);
+ }
+ if(!dat->fLimitedUpdate)
+ SetAeroMargins(dat->pContainer);
+ return(1);
+ }
+
+ case WM_NCPAINT:
+ if (CSkin::m_skinEnabled)
+ return 0;
+ break;
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwndDlg, &ps);
+ EndPaint(hwndDlg, &ps);
+ return 0;
+ }
+
+ case DM_SETINFOPANEL:
+ CInfoPanel::setPanelHandler(dat, wParam, lParam);
+ return(0);
+
+ case DM_INVALIDATEPANEL:
+ if(dat->Panel)
+ dat->Panel->Invalidate(true);
+ return(0);
+
+ case WM_RBUTTONUP: {
+ POINT pt;
+ int iSelection;
+ HMENU subMenu;
+ int isHandled;
+ int menuID = 0;
+
+ GetCursorPos(&pt);
+
+ if(dat->Panel->invokeConfigDialog(pt))
+ break;
+
+ subMenu = GetSubMenu(dat->pContainer->hMenuContext, 0);
+
+ MsgWindowUpdateMenu(dat, subMenu, MENU_TABCONTEXT);
+
+ iSelection = TrackPopupMenu(subMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+ if (iSelection >= IDM_CONTAINERMENU) {
+ DBVARIANT dbv = {0};
+ char szIndex[10];
+ char *szKey = "TAB_ContainersW";
+ _snprintf(szIndex, 8, "%d", iSelection - IDM_CONTAINERMENU);
+ if (iSelection - IDM_CONTAINERMENU >= 0) {
+ if (!M->GetTString(NULL, szKey, szIndex, &dbv)) {
+ SendMessage(hwndDlg, DM_CONTAINERSELECTED, 0, (LPARAM)dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ break;
+ }
+ isHandled = MsgWindowMenuHandler(dat, iSelection, MENU_TABCONTEXT);
+ break;
+ }
+
+ case WM_LBUTTONDBLCLK: {
+ if (LOWORD(lParam) < 30)
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+ break;
+ }
+
+ case WM_CLOSE:
+ if (wParam == 0 && lParam == 0) {
+ if(PluginConfig.m_EscapeCloses == 1) {
+ SendMessage(dat->pContainer->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+ return(TRUE);
+ } else if(PluginConfig.m_HideOnClose && PluginConfig.m_EscapeCloses == 2) {
+ ShowWindow(dat->pContainer->hwnd, SW_HIDE);
+ return(TRUE);
+ }
+ _dlgReturn(hwndDlg, TRUE);
+ }
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 1);
+ break;
+
+ case DM_CONTAINERSELECTED: {
+ struct TContainerData *pNewContainer = 0;
+ TCHAR *szNewName = (TCHAR *)lParam;
+ if(!_tcscmp(szNewName, CTranslator::get(CTranslator::GEN_DEFAULT_CONTAINER_NAME)))
+ szNewName = CGlobals::m_default_container_name;
+ int iOldItems = TabCtrl_GetItemCount(hwndTab);
+ if (!_tcsncmp(dat->pContainer->szName, szNewName, CONTAINER_NAMELEN))
+ break;
+ pNewContainer = FindContainerByName(szNewName);
+ if (pNewContainer == NULL)
+ pNewContainer = CreateContainer(szNewName, FALSE, dat->hContact);
+ M->WriteTString(dat->hContact, SRMSGMOD_T, "containerW", szNewName);
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_DOCREATETAB_CHAT, (WPARAM)pNewContainer, (LPARAM)hwndDlg);
+ if (iOldItems > 1) // there were more than 1 tab, container is still valid
+ SendMessage(dat->pContainer->hwndActive, WM_SIZE, 0, 0);
+ SetForegroundWindow(pNewContainer->hwnd);
+ SetActiveWindow(pNewContainer->hwnd);
+ }
+ break;
+ // container API support functions
+
+ case DM_QUERYCONTAINER: {
+ struct TContainerData **pc = (struct TContainerData **) lParam;
+ if (pc)
+ *pc = dat->pContainer;
+ return 0;
+ }
+
+ case DM_QUERYHCONTACT: {
+ HANDLE *phContact = (HANDLE *) lParam;
+ if (phContact)
+ *phContact = dat->hContact;
+ return 0;
+ }
+
+ case GC_CLOSEWINDOW: {
+ int iTabs, i;
+ TCITEM item = {0};
+ RECT rc;
+ struct TContainerData *pContainer = dat->pContainer;
+ BOOL bForced = (lParam == 2);
+
+ iTabs = TabCtrl_GetItemCount(hwndTab);
+ if (iTabs == 1) {
+ if (/*!bForced && */CMimAPI::m_shutDown == 0) {
+ //DestroyWindow(GetParent(GetParent(hwndDlg)));
+ //PostMessage(hwndDlg, WM_CLOSE, 0, 1);
+ SendMessage(GetParent(GetParent(hwndDlg)), WM_CLOSE, 0, 1);
+ return 1;
+ }
+ }
+
+ dat->pContainer->iChilds--;
+ i = GetTabIndexFromHWND(hwndTab, hwndDlg);
+
+ /*
+ * after closing a tab, we need to activate the tab to the left side of
+ * the previously open tab.
+ * normally, this tab has the same index after the deletion of the formerly active tab
+ * unless, of course, we closed the last (rightmost) tab.
+ */
+ if (!dat->pContainer->bDontSmartClose && iTabs > 1 && !bForced) {
+ if (i == iTabs - 1)
+ i--;
+ else
+ i++;
+ TabCtrl_SetCurSel(hwndTab, i);
+ item.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, i, &item); // retrieve dialog hwnd for the now active tab...
+
+ dat->pContainer->hwndActive = (HWND) item.lParam;
+ SendMessage(dat->pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc);
+ SetWindowPos(dat->pContainer->hwndActive, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), SWP_SHOWWINDOW);
+ ShowWindow((HWND)item.lParam, SW_SHOW);
+ SetForegroundWindow(dat->pContainer->hwndActive);
+ SetFocus(dat->pContainer->hwndActive);
+ SendMessage(dat->pContainer->hwnd, WM_SIZE, 0, 0);
+ }
+ //SM_SetTabbedWindowHwnd(0, 0);
+ //DestroyWindow(hwndDlg);
+ if (iTabs == 1)
+ SendMessage(GetParent(GetParent(hwndDlg)), WM_CLOSE, 0, 1);
+ else {
+ PostMessage(pContainer->hwnd, WM_SIZE, 0, 0);
+ DestroyWindow(hwndDlg);
+ }
+ return 0;
+ }
+
+ case DM_SETLOCALE:
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE)
+ break;
+ if (dat->pContainer->hwndActive == hwndDlg && PluginConfig.m_AutoLocaleSupport && dat->hContact != 0 && dat->pContainer->hwnd == GetForegroundWindow() && dat->pContainer->hwnd == GetActiveWindow()) {
+ if(lParam)
+ dat->hkl = (HKL)lParam;
+
+ if (dat->hkl)
+ ActivateKeyboardLayout(dat->hkl, 0);
+ }
+ return 0;
+
+ case DM_SAVESIZE: {
+ RECT rcClient;
+
+ if (dat->dwFlags & MWF_NEEDCHECKSIZE)
+ lParam = 0;
+
+ dat->dwFlags &= ~MWF_NEEDCHECKSIZE;
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE)
+ dat->dwFlags &= ~MWF_INITMODE;
+
+ SendMessage(dat->pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rcClient);
+ MoveWindow(hwndDlg, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), TRUE);
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE) {
+ POINT pt = {0};;
+
+ dat->dwFlags &= ~MWF_WASBACKGROUNDCREATE;
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETSCROLLPOS, 0, (LPARAM)&pt);
+ if(PluginConfig.m_AutoLocaleSupport) {
+ if(dat->hkl == 0)
+ DM_LoadLocale(dat);
+ else
+ PostMessage(hwndDlg, DM_SETLOCALE, 0, 0);
+ }
+ } else {
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ if (lParam == 0)
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 1, 1);
+ }
+ return 0;
+ }
+
+ case DM_GETWINDOWSTATE: {
+ UINT state = 0;
+
+ state |= MSG_WINDOW_STATE_EXISTS;
+ if (IsWindowVisible(hwndDlg))
+ state |= MSG_WINDOW_STATE_VISIBLE;
+ if (GetForegroundWindow() == dat->pContainer->hwnd)
+ state |= MSG_WINDOW_STATE_FOCUS;
+ if (IsIconic(dat->pContainer->hwnd))
+ state |= MSG_WINDOW_STATE_ICONIC;
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, state);
+ return TRUE;
+ }
+
+ case DM_ADDDIVIDER:
+ if (!(dat->dwFlags & MWF_DIVIDERSET) && g_Settings.UseDividers) {
+ if (GetWindowTextLengthA(GetDlgItem(hwndDlg, IDC_CHAT_LOG)) > 0) {
+ dat->dwFlags |= MWF_DIVIDERWANTED;
+ dat->dwFlags |= MWF_DIVIDERSET;
+ }
+ }
+ return 0;
+
+ case DM_CHECKSIZE:
+ dat->dwFlags |= MWF_NEEDCHECKSIZE;
+ return 0;
+
+ case DM_REFRESHTABINDEX:
+ dat->iTabID = GetTabIndexFromHWND(GetParent(hwndDlg), hwndDlg);
+ return 0;
+
+ case DM_STATUSBARCHANGED:
+ UpdateStatusBar(dat);
+ break;
+
+ //mad: bb-api
+ case DM_BBNEEDUPDATE:{
+ if(lParam)
+ CB_ChangeButton(hwndDlg,dat,(CustomButtonData*)lParam);
+ else
+ BB_InitDlgButtons(dat);
+
+ BB_SetButtonsPos(dat);
+ }break;
+
+ case DM_CBDESTROY:{
+ if(lParam)
+ CB_DestroyButton(hwndDlg,dat,(DWORD)wParam,(DWORD)lParam);
+ else
+ CB_DestroyAllButtons(hwndDlg,dat);
+ }break;
+ //
+
+ case DM_CONFIGURETOOLBAR:
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case DM_SMILEYOPTIONSCHANGED:
+ ConfigureSmileyButton(dat);
+ SendMessage(hwndDlg, GC_REDRAWLOG, 0, 1);
+ break;
+
+ case EM_THEMECHANGED:
+ DM_FreeTheme(dat);
+ return DM_ThemeChanged(dat);
+
+ case WM_DWMCOMPOSITIONCHANGED:
+ BB_RefreshTheme(dat);
+ memset((void *)&dat->pContainer->mOld, -1000, sizeof(MARGINS));
+ CProxyWindow::verify(dat);
+ break;
+
+ case DM_ACTIVATEME:
+ ActivateExistingTab(dat->pContainer, hwndDlg);
+ return 0;
+
+ case DM_ACTIVATETOOLTIP: {
+ if (IsIconic(dat->pContainer->hwnd) || dat->pContainer->hwndActive != hwndDlg)
+ break;
+
+ dat->Panel->showTip(wParam, lParam);
+ break;
+ }
+
+ case DM_SAVEMESSAGELOG:
+ DM_SaveLogAsRTF(dat);
+ return(0);
+
+ case DM_CHECKAUTOHIDE:
+ DM_CheckAutoHide(dat, wParam, lParam);
+ return(0);
+
+ case WM_NCDESTROY:
+ if (dat) {
+ memset((void *)&dat->pContainer->mOld, -1000, sizeof(MARGINS));
+ PostMessage(dat->pContainer->hwnd, WM_SIZE, 0, 1);
+ delete dat->Panel;
+ if(dat->pContainer->dwFlags & CNT_SIDEBAR)
+ dat->pContainer->SideBar->removeSession(dat);
+ free(dat);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ }
+ break;
+
+ case WM_DESTROY: {
+ int i;
+
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+ si->wState &= ~STATE_TALK;
+ si->hWnd = NULL;
+ si->dat = 0;
+ si->pContainer = 0;
+
+ //SetWindowLongPtr(hwndDlg,GWLP_USERDATA,0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTERX), GWLP_WNDPROC, (LONG_PTR)OldSplitterProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTERY), GWLP_WNDPROC, (LONG_PTR)OldSplitterProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LIST), GWLP_WNDPROC, (LONG_PTR)OldNicklistProc);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_UNSUBCLASSED, 0, 0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), GWLP_WNDPROC, (LONG_PTR)OldMessageProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_LOG), GWLP_WNDPROC, (LONG_PTR)OldLogProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_FILTER), GWLP_WNDPROC, (LONG_PTR)OldFilterButtonProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_COLOR), GWLP_WNDPROC, (LONG_PTR)OldFilterButtonProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_BKGCOLOR), GWLP_WNDPROC, (LONG_PTR)OldFilterButtonProc);
+
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING, 0);
+
+ if(!dat->fIsAutosizingInput)
+ DBWriteContactSettingWord(NULL, "Chat", "SplitterX", (WORD)g_Settings.iSplitterX);
+
+ if(dat->pContainer->settings->fPrivate && !IsAutoSplitEnabled(dat))
+ DBWriteContactSettingWord(NULL, "Chat", "splitY", (WORD)g_Settings.iSplitterY);
+
+ DM_FreeTheme(dat);
+
+ UpdateTrayMenuState(dat, FALSE); // remove me from the tray menu (if still there)
+ if (PluginConfig.g_hMenuTrayUnread)
+ DeleteMenu(PluginConfig.g_hMenuTrayUnread, (UINT_PTR)dat->hContact, MF_BYCOMMAND);
+
+ if (dat->hSmileyIcon)
+ DestroyIcon(dat->hSmileyIcon);
+
+ if (dat->hwndTip)
+ DestroyWindow(dat->hwndTip);
+
+ if (hCurHyperlinkHand)
+ DestroyCursor(hCurHyperlinkHand);
+
+ i = GetTabIndexFromHWND(hwndTab, hwndDlg);
+ if (i >= 0) {
+ SendMessage(hwndTab, WM_USER + 100, 0, 0); // clean up tooltip
+ TabCtrl_DeleteItem(hwndTab, i);
+ BroadCastContainer(dat->pContainer, DM_REFRESHTABINDEX, 0, 0);
+ dat->iTabID = -1;
+ }
+ if(dat->pWnd) {
+ delete dat->pWnd;
+ dat->pWnd = 0;
+ }
+ //MAD
+ M->RemoveWindow(hwndDlg);
+
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE, 0);
+ break;
+ }
+ }
+ return(FALSE);
+}