From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/plugins/clist/clc.h | 83 ++ miranda-wine/plugins/clist/clcopts.c | 923 +++++++++++++ miranda-wine/plugins/clist/clcpaint.c | 590 +++++++++ miranda-wine/plugins/clist/clist.h | 30 + miranda-wine/plugins/clist/clistmenus.c | 947 ++++++++++++++ miranda-wine/plugins/clist/clistopts.c | 353 +++++ miranda-wine/plugins/clist/cluiopts.c | 346 +++++ miranda-wine/plugins/clist/commonheaders.c | 1 + miranda-wine/plugins/clist/commonheaders.h | 96 ++ miranda-wine/plugins/clist/forkthread.c | 94 ++ miranda-wine/plugins/clist/forkthread.h | 63 + miranda-wine/plugins/clist/init.c | 175 +++ miranda-wine/plugins/clist/res/blank.ico | Bin 0 -> 318 bytes miranda-wine/plugins/clist/res/delete.ico | Bin 0 -> 1406 bytes miranda-wine/plugins/clist/res/dragcopy.cur | Bin 0 -> 326 bytes miranda-wine/plugins/clist/res/dropuser.cur | Bin 0 -> 1086 bytes miranda-wine/plugins/clist/res/hyperlin.cur | Bin 0 -> 326 bytes miranda-wine/plugins/clist/res/rename.ico | Bin 0 -> 1406 bytes miranda-wine/plugins/clist/resource.h | 554 ++++++++ miranda-wine/plugins/clist/resource.rc | 706 ++++++++++ miranda-wine/plugins/db3x/Makefile | 53 + miranda-wine/plugins/db3x/commonheaders.c | 1 + miranda-wine/plugins/db3x/commonheaders.h | 66 + miranda-wine/plugins/db3x/database.c | 186 +++ miranda-wine/plugins/db3x/database.h | 218 ++++ miranda-wine/plugins/db3x/dbcache.c | 229 ++++ miranda-wine/plugins/db3x/dbcontacts.c | 270 ++++ miranda-wine/plugins/db3x/dbevents.c | 436 +++++++ miranda-wine/plugins/db3x/dbheaders.c | 78 ++ miranda-wine/plugins/db3x/dbmodulechain.c | 132 ++ miranda-wine/plugins/db3x/dbsettings.c | 957 ++++++++++++++ miranda-wine/plugins/db3x/dbtime.c | 163 +++ miranda-wine/plugins/db3x/encrypt.c | 67 + miranda-wine/plugins/db3x/encryption.h | 23 + miranda-wine/plugins/db3x/init.c | 193 +++ miranda-wine/plugins/db3x/resource.h | 30 + miranda-wine/plugins/db3x/resource.rc | 169 +++ miranda-wine/plugins/db3x/utf.c | 166 +++ miranda-wine/plugins/png2dib/m_png.h | 64 + miranda-wine/plugins/png2dib/png2dib.c | 411 ++++++ miranda-wine/plugins/png2dib/version.h | 3 + miranda-wine/plugins/png2dib/version.rc | 36 + miranda-wine/plugins/srmm/cmdlist.c | 124 ++ miranda-wine/plugins/srmm/cmdlist.h | 48 + miranda-wine/plugins/srmm/commonheaders.h | 57 + miranda-wine/plugins/srmm/globals.c | 107 ++ miranda-wine/plugins/srmm/globals.h | 59 + miranda-wine/plugins/srmm/msgdialog.c | 1859 +++++++++++++++++++++++++++ miranda-wine/plugins/srmm/msglog.c | 549 ++++++++ miranda-wine/plugins/srmm/msgoptions.c | 723 +++++++++++ miranda-wine/plugins/srmm/msgs.c | 587 +++++++++ miranda-wine/plugins/srmm/msgs.h | 211 +++ miranda-wine/plugins/srmm/msgtimedout.c | 71 + miranda-wine/plugins/srmm/res/add.ico | Bin 0 -> 2550 bytes miranda-wine/plugins/srmm/res/clock.ico | Bin 0 -> 2550 bytes miranda-wine/plugins/srmm/res/details.ico | Bin 0 -> 2550 bytes miranda-wine/plugins/srmm/res/downarrow.ico | Bin 0 -> 1406 bytes miranda-wine/plugins/srmm/res/history.ico | Bin 0 -> 2550 bytes miranda-wine/plugins/srmm/res/incoming.ico | Bin 0 -> 1246 bytes miranda-wine/plugins/srmm/res/notice.ico | Bin 0 -> 1246 bytes miranda-wine/plugins/srmm/res/outgoing.ico | Bin 0 -> 1246 bytes miranda-wine/plugins/srmm/res/typing.ico | Bin 0 -> 2550 bytes miranda-wine/plugins/srmm/resource.h | 93 ++ miranda-wine/plugins/srmm/resource.rc | 356 +++++ miranda-wine/plugins/srmm/richutil.c | 234 ++++ miranda-wine/plugins/srmm/richutil.h | 55 + miranda-wine/plugins/srmm/srmm.c | 71 + 67 files changed, 14116 insertions(+) create mode 100644 miranda-wine/plugins/clist/clc.h create mode 100644 miranda-wine/plugins/clist/clcopts.c create mode 100644 miranda-wine/plugins/clist/clcpaint.c create mode 100644 miranda-wine/plugins/clist/clist.h create mode 100644 miranda-wine/plugins/clist/clistmenus.c create mode 100644 miranda-wine/plugins/clist/clistopts.c create mode 100644 miranda-wine/plugins/clist/cluiopts.c create mode 100644 miranda-wine/plugins/clist/commonheaders.c create mode 100644 miranda-wine/plugins/clist/commonheaders.h create mode 100644 miranda-wine/plugins/clist/forkthread.c create mode 100644 miranda-wine/plugins/clist/forkthread.h create mode 100644 miranda-wine/plugins/clist/init.c create mode 100644 miranda-wine/plugins/clist/res/blank.ico create mode 100644 miranda-wine/plugins/clist/res/delete.ico create mode 100644 miranda-wine/plugins/clist/res/dragcopy.cur create mode 100644 miranda-wine/plugins/clist/res/dropuser.cur create mode 100644 miranda-wine/plugins/clist/res/hyperlin.cur create mode 100644 miranda-wine/plugins/clist/res/rename.ico create mode 100644 miranda-wine/plugins/clist/resource.h create mode 100644 miranda-wine/plugins/clist/resource.rc create mode 100644 miranda-wine/plugins/db3x/Makefile create mode 100644 miranda-wine/plugins/db3x/commonheaders.c create mode 100644 miranda-wine/plugins/db3x/commonheaders.h create mode 100644 miranda-wine/plugins/db3x/database.c create mode 100644 miranda-wine/plugins/db3x/database.h create mode 100644 miranda-wine/plugins/db3x/dbcache.c create mode 100644 miranda-wine/plugins/db3x/dbcontacts.c create mode 100644 miranda-wine/plugins/db3x/dbevents.c create mode 100644 miranda-wine/plugins/db3x/dbheaders.c create mode 100644 miranda-wine/plugins/db3x/dbmodulechain.c create mode 100644 miranda-wine/plugins/db3x/dbsettings.c create mode 100644 miranda-wine/plugins/db3x/dbtime.c create mode 100644 miranda-wine/plugins/db3x/encrypt.c create mode 100644 miranda-wine/plugins/db3x/encryption.h create mode 100644 miranda-wine/plugins/db3x/init.c create mode 100644 miranda-wine/plugins/db3x/resource.h create mode 100644 miranda-wine/plugins/db3x/resource.rc create mode 100644 miranda-wine/plugins/db3x/utf.c create mode 100644 miranda-wine/plugins/png2dib/m_png.h create mode 100644 miranda-wine/plugins/png2dib/png2dib.c create mode 100644 miranda-wine/plugins/png2dib/version.h create mode 100644 miranda-wine/plugins/png2dib/version.rc create mode 100644 miranda-wine/plugins/srmm/cmdlist.c create mode 100644 miranda-wine/plugins/srmm/cmdlist.h create mode 100644 miranda-wine/plugins/srmm/commonheaders.h create mode 100644 miranda-wine/plugins/srmm/globals.c create mode 100644 miranda-wine/plugins/srmm/globals.h create mode 100644 miranda-wine/plugins/srmm/msgdialog.c create mode 100644 miranda-wine/plugins/srmm/msglog.c create mode 100644 miranda-wine/plugins/srmm/msgoptions.c create mode 100644 miranda-wine/plugins/srmm/msgs.c create mode 100644 miranda-wine/plugins/srmm/msgs.h create mode 100644 miranda-wine/plugins/srmm/msgtimedout.c create mode 100644 miranda-wine/plugins/srmm/res/add.ico create mode 100644 miranda-wine/plugins/srmm/res/clock.ico create mode 100644 miranda-wine/plugins/srmm/res/details.ico create mode 100644 miranda-wine/plugins/srmm/res/downarrow.ico create mode 100644 miranda-wine/plugins/srmm/res/history.ico create mode 100644 miranda-wine/plugins/srmm/res/incoming.ico create mode 100644 miranda-wine/plugins/srmm/res/notice.ico create mode 100644 miranda-wine/plugins/srmm/res/outgoing.ico create mode 100644 miranda-wine/plugins/srmm/res/typing.ico create mode 100644 miranda-wine/plugins/srmm/resource.h create mode 100644 miranda-wine/plugins/srmm/resource.rc create mode 100644 miranda-wine/plugins/srmm/richutil.c create mode 100644 miranda-wine/plugins/srmm/richutil.h create mode 100644 miranda-wine/plugins/srmm/srmm.c (limited to 'miranda-wine/plugins') diff --git a/miranda-wine/plugins/clist/clc.h b/miranda-wine/plugins/clist/clc.h new file mode 100644 index 0000000..7b825dd --- /dev/null +++ b/miranda-wine/plugins/clist/clc.h @@ -0,0 +1,83 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#define FONTID_LAST 7 + +struct ClcContact { + BYTE type; + BYTE flags; + union { + struct { + WORD iImage; + HANDLE hContact; + }; + struct { + WORD groupId; + struct ClcGroup *group; + }; + }; + BYTE iExtraImage[MAXEXTRACOLUMNS]; + TCHAR szText[120-MAXEXTRACOLUMNS]; + char * proto; // MS_PROTO_GETBASEPROTO +}; + +struct ClcData { + struct ClcGroup list; + int rowHeight; + int yScroll; + int selection; + struct ClcFontInfo fontInfo[FONTID_MAX+1]; + int scrollTime; + HIMAGELIST himlHighlight; + int groupIndent; + TCHAR szQuickSearch[128]; + int iconXSpace; + HWND hwndRenameEdit; + COLORREF bkColour,selBkColour,selTextColour,hotTextColour,quickSearchColour; + int iDragItem,iInsertionMark; + int dragStage; + POINT ptDragStart; + int dragAutoScrolling; + int dragAutoScrollHeight; + int leftMargin; + int insertionMarkHitHeight; + HBITMAP hBmpBackground; + int backgroundBmpUse,bkChanged; + int iHotTrack; + int gammaCorrection; + DWORD greyoutFlags; //see m_clc.h + DWORD offlineModes; + DWORD exStyle; + POINT ptInfoTip; + int infoTipTimeout; + HANDLE hInfoTipItem; + HIMAGELIST himlExtraColumns; + int extraColumnsCount; + int extraColumnSpacing; + int checkboxSize; + int showSelAlways; + int showIdle; + int noVScrollbar; + int useWindowsColours; + int needsResort; +}; diff --git a/miranda-wine/plugins/clist/clcopts.c b/miranda-wine/plugins/clist/clcopts.c new file mode 100644 index 0000000..81f4950 --- /dev/null +++ b/miranda-wine/plugins/clist/clcopts.c @@ -0,0 +1,923 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" + +#define DBFONTF_BOLD 1 +#define DBFONTF_ITALIC 2 +#define DBFONTF_UNDERLINE 4 + +struct CheckBoxToStyleEx_t +{ + int id; + DWORD flag; + int not; +} + +static const checkBoxToStyleEx[] = { + {IDC_DISABLEDRAGDROP, CLS_EX_DISABLEDRAGDROP, 0}, + {IDC_NOTEDITLABELS, CLS_EX_EDITLABELS, 1}, + {IDC_SHOWSELALWAYS, CLS_EX_SHOWSELALWAYS, 0}, + {IDC_TRACKSELECT, CLS_EX_TRACKSELECT, 0}, + {IDC_SHOWGROUPCOUNTS, CLS_EX_SHOWGROUPCOUNTS, 0}, + {IDC_HIDECOUNTSWHENEMPTY, CLS_EX_HIDECOUNTSWHENEMPTY, 0}, + {IDC_DIVIDERONOFF, CLS_EX_DIVIDERONOFF, 0}, + {IDC_NOTNOTRANSLUCENTSEL, CLS_EX_NOTRANSLUCENTSEL, 1}, + {IDC_LINEWITHGROUPS, CLS_EX_LINEWITHGROUPS, 0}, + {IDC_QUICKSEARCHVISONLY, CLS_EX_QUICKSEARCHVISONLY, 0}, + {IDC_SORTGROUPSALPHA, CLS_EX_SORTGROUPSALPHA, 0}, + {IDC_NOTNOSMOOTHSCROLLING, CLS_EX_NOSMOOTHSCROLLING, 1} +}; + +struct CheckBoxValues_t +{ + DWORD style; + TCHAR* szDescr; +}; + +static const struct CheckBoxValues_t greyoutValues[] = { + { GREYF_UNFOCUS, _T("Not focused") }, + { MODEF_OFFLINE, _T("Offline") }, + { PF2_ONLINE, _T("Online") }, + { PF2_SHORTAWAY, _T("Away") }, + { PF2_LONGAWAY, _T("NA") }, + { PF2_LIGHTDND, _T("Occupied") }, + { PF2_HEAVYDND, _T("DND") }, + { PF2_FREECHAT, _T("Free for chat") }, + { PF2_INVISIBLE, _T("Invisible") }, + { PF2_OUTTOLUNCH, _T("Out to lunch") }, + { PF2_ONTHEPHONE, _T("On the phone") } +}; + +static const struct CheckBoxValues_t offlineValues[] = { + { MODEF_OFFLINE, _T("Offline") }, + { PF2_ONLINE, _T("Online") }, + { PF2_SHORTAWAY, _T("Away") }, + { PF2_LONGAWAY, _T("NA") }, + { PF2_LIGHTDND, _T("Occupied") }, + { PF2_HEAVYDND, _T("DND") }, + { PF2_FREECHAT, _T("Free for chat") }, + { PF2_INVISIBLE, _T("Invisible") }, + { PF2_OUTTOLUNCH, _T("Out to lunch") }, + { PF2_ONTHEPHONE, _T("On the phone") } +}; + +static void FillCheckBoxTree(HWND hwndTree, const struct CheckBoxValues_t *values, int nValues, DWORD style) +{ + TVINSERTSTRUCT tvis; + int i; + + tvis.hParent = NULL; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE; + for (i = 0; i < nValues; i++) { + tvis.item.lParam = values[i].style; + tvis.item.pszText = TranslateTS( values[i].szDescr ); + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.state = INDEXTOSTATEIMAGEMASK((style & tvis.item.lParam) != 0 ? 2 : 1); + TreeView_InsertItem( hwndTree, &tvis); +} } + +static DWORD MakeCheckBoxTreeFlags(HWND hwndTree) +{ + DWORD flags = 0; + TVITEM tvi; + + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE; + tvi.hItem = TreeView_GetRoot(hwndTree); + while (tvi.hItem) { + TreeView_GetItem(hwndTree, &tvi); + if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2)) + flags |= tvi.lParam; + tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); + } + return flags; +} + +static BOOL CALLBACK DlgProcClcMainOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetWindowLong(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), GWL_STYLE, + GetWindowLong(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); + SetWindowLong(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), GWL_STYLE, + GetWindowLong(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); + { + int i; + DWORD exStyle = DBGetContactSettingDword(NULL, "CLC", "ExStyle", pcli->pfnGetDefaultExStyle()); + for (i = 0; i < SIZEOF(checkBoxToStyleEx); i++) + CheckDlgButton(hwndDlg, checkBoxToStyleEx[i].id, + (exStyle & checkBoxToStyleEx[i].flag) ^ (checkBoxToStyleEx[i].flag * + checkBoxToStyleEx[i].not) ? BST_CHECKED : BST_UNCHECKED); + } + { + UDACCEL accel[2] = { {0, 10} , {2, 50} }; + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETRANGE, 0, MAKELONG(999, 0)); + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETACCEL, SIZEOF(accel), (LPARAM) & accel); + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingWord(NULL, "CLC", "ScrollTime", CLCDEFAULT_SCROLLTIME), 0)); + } + CheckDlgButton(hwndDlg, IDC_IDLE, DBGetContactSettingByte(NULL, "CLC", "ShowIdle", CLCDEFAULT_SHOWIDLE) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_SETRANGE, 0, MAKELONG(64, 0)); + SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingByte(NULL, "CLC", "LeftMargin", CLCDEFAULT_LEFTMARGIN), 0)); + SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_SETRANGE, 0, MAKELONG(50, 0)); + SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingByte(NULL, "CLC", "GroupIndent", CLCDEFAULT_GROUPINDENT), 0)); + CheckDlgButton(hwndDlg, IDC_GREYOUT, + DBGetContactSettingDword(NULL, "CLC", "GreyoutFlags", CLCDEFAULT_GREYOUTFLAGS) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_SMOOTHTIME), IsDlgButtonChecked(hwndDlg, IDC_NOTNOSMOOTHSCROLLING)); + EnableWindow(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)); + FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), greyoutValues, SIZEOF(greyoutValues), + DBGetContactSettingDword(NULL, "CLC", "FullGreyoutFlags", CLCDEFAULT_FULLGREYOUTFLAGS)); + FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), offlineValues, SIZEOF(offlineValues), + DBGetContactSettingDword(NULL, "CLC", "OfflineModes", CLCDEFAULT_OFFLINEMODES)); + CheckDlgButton(hwndDlg, IDC_NOSCROLLBAR, DBGetContactSettingByte(NULL, "CLC", "NoVScrollBar", 0) ? BST_CHECKED : BST_UNCHECKED); + return TRUE; + case WM_VSCROLL: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_NOTNOSMOOTHSCROLLING) + EnableWindow(GetDlgItem(hwndDlg, IDC_SMOOTHTIME), IsDlgButtonChecked(hwndDlg, IDC_NOTNOSMOOTHSCROLLING)); + if (LOWORD(wParam) == IDC_GREYOUT) + EnableWindow(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)); + if ((LOWORD(wParam) == IDC_LEFTMARGIN || LOWORD(wParam) == IDC_SMOOTHTIME || LOWORD(wParam) == IDC_GROUPINDENT) + && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_GREYOUTOPTS: + case IDC_HIDEOFFLINEOPTS: + if (((LPNMHDR) lParam)->code == NM_CLICK) { + TVHITTESTINFO hti; + hti.pt.x = (short) LOWORD(GetMessagePos()); + hti.pt.y = (short) HIWORD(GetMessagePos()); + ScreenToClient(((LPNMHDR) lParam)->hwndFrom, &hti.pt); + if (TreeView_HitTest(((LPNMHDR) lParam)->hwndFrom, &hti)) + if (hti.flags & TVHT_ONITEMSTATEICON) { + TVITEM tvi; + tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.hItem = hti.hItem; + TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1; + TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + case 0: + if (((LPNMHDR) lParam)->code == PSN_APPLY ) { + int i; + DWORD exStyle = 0; + for (i = 0; i < SIZEOF(checkBoxToStyleEx); i++) + if ((IsDlgButtonChecked(hwndDlg, checkBoxToStyleEx[i].id) == 0) == checkBoxToStyleEx[i].not) + exStyle |= checkBoxToStyleEx[i].flag; + + DBWriteContactSettingDword(NULL, "CLC", "ExStyle", exStyle); + { + DWORD fullGreyoutFlags = MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS)); + DBWriteContactSettingDword(NULL, "CLC", "FullGreyoutFlags", fullGreyoutFlags); + if (IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)) + DBWriteContactSettingDword(NULL, "CLC", "GreyoutFlags", fullGreyoutFlags); + else + DBWriteContactSettingDword(NULL, "CLC", "GreyoutFlags", 0); + } + DBWriteContactSettingByte(NULL, "CLC", "ShowIdle", (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_IDLE) ? 1 : 0)); + DBWriteContactSettingDword(NULL, "CLC", "OfflineModes", MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS))); + DBWriteContactSettingByte(NULL, "CLC", "LeftMargin", + (BYTE) SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingWord(NULL, "CLC", "ScrollTime", + (WORD) SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CLC", "GroupIndent", + (BYTE) SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CLC", "NoVScrollBar", (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_NOSCROLLBAR) ? 1 : 0)); + pcli->pfnClcOptionsChanged(); + return TRUE; + } + break; + } + break; + case WM_DESTROY: + ImageList_Destroy(TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), TVSIL_NORMAL)); + break; + } + return FALSE; +} + +static BOOL CALLBACK DlgProcClcBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_BITMAP, + DBGetContactSettingByte(NULL, "CLC", "UseBitmap", CLCDEFAULT_USEBITMAP) ? BST_CHECKED : BST_UNCHECKED); + SendMessage(hwndDlg, WM_USER + 10, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_BKCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, "CLC", "BkColour", CLCDEFAULT_BKCOLOUR)); + SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_SELBKCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETCOLOUR, 0, + DBGetContactSettingDword(NULL, "CLC", "SelBkColour", CLCDEFAULT_SELBKCOLOUR)); + CheckDlgButton(hwndDlg, IDC_WINCOLOUR, DBGetContactSettingByte(NULL, "CLC", "UseWinColours", 0)); + SendMessage(hwndDlg, WM_USER + 11, 0, 0); + { + DBVARIANT dbv; + if (!DBGetContactSetting(NULL, "CLC", "BkBitmap", &dbv)) { + SetDlgItemTextA(hwndDlg, IDC_FILENAME, dbv.pszVal); + if (ServiceExists(MS_UTILS_PATHTOABSOLUTE)) { + char szPath[MAX_PATH]; + + if (CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM) dbv.pszVal, (LPARAM) szPath)) + SetDlgItemTextA(hwndDlg, IDC_FILENAME, szPath); + } + else + mir_free(dbv.pszVal); + } + } + { + WORD bmpUse = DBGetContactSettingWord(NULL, "CLC", "BkBmpUse", CLCDEFAULT_BKBMPUSE); + CheckDlgButton(hwndDlg, IDC_STRETCHH, bmpUse & CLB_STRETCHH ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_STRETCHV, bmpUse & CLB_STRETCHV ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TILEH, bmpUse & CLBF_TILEH ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TILEV, bmpUse & CLBF_TILEV ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SCROLL, bmpUse & CLBF_SCROLL ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROPORTIONAL, bmpUse & CLBF_PROPORTIONAL ? BST_CHECKED : BST_UNCHECKED); + } + { + HRESULT(STDAPICALLTYPE * MySHAutoComplete) (HWND, DWORD); + MySHAutoComplete = (HRESULT(STDAPICALLTYPE *) (HWND, DWORD)) GetProcAddress(GetModuleHandleA("shlwapi"), "SHAutoComplete"); + if (MySHAutoComplete) + MySHAutoComplete(GetDlgItem(hwndDlg, IDC_FILENAME), 1); + } + return TRUE; + case WM_USER + 10: + EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAME), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRETCHH), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRETCHV), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TILEH), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TILEV), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SCROLL), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROPORTIONAL), IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + break; + case WM_USER + 11: + { + BOOL b = IsDlgButtonChecked(hwndDlg, IDC_WINCOLOUR); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKGCOLOUR), !b); + EnableWindow(GetDlgItem(hwndDlg, IDC_SELCOLOUR), !b); + break; + } + case WM_COMMAND: + if (LOWORD(wParam) == IDC_BROWSE) { + char str[MAX_PATH]; + OPENFILENAMEA ofn = { 0 }; + char filter[512]; + + GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, SIZEOF(str)); + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwndDlg; + ofn.hInstance = NULL; + CallService(MS_UTILS_GETBITMAPFILTERSTRINGS, SIZEOF(filter), (LPARAM) filter); + ofn.lpstrFilter = filter; + ofn.lpstrFile = str; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.nMaxFile = SIZEOF(str); + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = "bmp"; + if (!GetOpenFileNameA(&ofn)) + break; + SetDlgItemTextA(hwndDlg, IDC_FILENAME, str); + } + else if (LOWORD(wParam) == IDC_FILENAME && HIWORD(wParam) != EN_CHANGE) + break; + if (LOWORD(wParam) == IDC_BITMAP) + SendMessage(hwndDlg, WM_USER + 10, 0, 0); + if (LOWORD(wParam) == IDC_WINCOLOUR) + SendMessage(hwndDlg, WM_USER + 11, 0, 0); + if (LOWORD(wParam) == IDC_FILENAME && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + DBWriteContactSettingByte(NULL, "CLC", "UseBitmap", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + { + COLORREF col; + col = SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0); + if (col == CLCDEFAULT_BKCOLOUR) + DBDeleteContactSetting(NULL, "CLC", "BkColour"); + else + DBWriteContactSettingDword(NULL, "CLC", "BkColour", col); + col = SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_GETCOLOUR, 0, 0); + if (col == CLCDEFAULT_SELBKCOLOUR) + DBDeleteContactSetting(NULL, "CLC", "SelBkColour"); + else + DBWriteContactSettingDword(NULL, "CLC", "SelBkColour", col); + DBWriteContactSettingByte(NULL, "CLC", "UseWinColours", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_WINCOLOUR))); + } + { + char str[MAX_PATH], strrel[MAX_PATH]; + GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, SIZEOF(str)); + if (ServiceExists(MS_UTILS_PATHTORELATIVE)) { + if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM) str, (LPARAM) strrel)) + DBWriteContactSettingString(NULL, "CLC", "BkBitmap", strrel); + else + DBWriteContactSettingString(NULL, "CLC", "BkBitmap", str); + } + else + DBWriteContactSettingString(NULL, "CLC", "BkBitmap", str); + } + { + WORD flags = 0; + if (IsDlgButtonChecked(hwndDlg, IDC_STRETCHH)) + flags |= CLB_STRETCHH; + if (IsDlgButtonChecked(hwndDlg, IDC_STRETCHV)) + flags |= CLB_STRETCHV; + if (IsDlgButtonChecked(hwndDlg, IDC_TILEH)) + flags |= CLBF_TILEH; + if (IsDlgButtonChecked(hwndDlg, IDC_TILEV)) + flags |= CLBF_TILEV; + if (IsDlgButtonChecked(hwndDlg, IDC_SCROLL)) + flags |= CLBF_SCROLL; + if (IsDlgButtonChecked(hwndDlg, IDC_PROPORTIONAL)) + flags |= CLBF_PROPORTIONAL; + DBWriteContactSettingWord(NULL, "CLC", "BkBmpUse", flags); + } + pcli->pfnClcOptionsChanged(); + return TRUE; + } + break; + } + break; + } + return FALSE; +} + +static const TCHAR* szFontIdDescr[FONTID_LAST + 1] = +{ + _T("Standard contacts"), + _T("Online contacts to whom you have a different visibility"), + _T("Offline contacts"), + _T("Contacts which are 'not on list'"), + _T("Groups"), + _T("Group member counts"), + _T("Dividers"), + _T("Offline contacts to whom you have a different visibility") +}; + +#define SAMEASF_FACE 1 +#define SAMEASF_SIZE 2 +#define SAMEASF_STYLE 4 +#define SAMEASF_COLOUR 8 +#include +struct +{ + BYTE sameAsFlags, sameAs; + COLORREF colour; + char size; + BYTE style; + BYTE charset; + TCHAR szFace[LF_FACESIZE]; +} +static fontSettings[FONTID_LAST + 1]; +#include +static WORD fontSameAsDefault[FONTID_LAST + 1] = { 0x00FF, 0x0B00, 0x0F00, 0x0700, 0x0B00, 0x0104, 0x0D00, 0x0B02 }; +static char *fontSizes[] = { "7", "8", "10", "14", "16", "18", "20", "24", "28" }; +static int fontListOrder[FONTID_LAST + 1] = +{ FONTID_CONTACTS, FONTID_INVIS, FONTID_OFFLINE, FONTID_OFFINVIS, FONTID_NOTONLIST, FONTID_GROUPS, FONTID_GROUPCOUNTS, FONTID_DIVIDERS }; + +#define M_REBUILDFONTGROUP (WM_USER+10) +#define M_REMAKESAMPLE (WM_USER+11) +#define M_RECALCONEFONT (WM_USER+12) +#define M_RECALCOTHERFONTS (WM_USER+13) +#define M_SAVEFONT (WM_USER+14) +#define M_REFRESHSAMEASBOXES (WM_USER+15) +#define M_FILLSCRIPTCOMBO (WM_USER+16) +#define M_REDOROWHEIGHT (WM_USER+17) +#define M_LOADFONT (WM_USER+18) +#define M_GUESSSAMEASBOXES (WM_USER+19) +#define M_SETSAMEASBOXES (WM_USER+20) + +static int CALLBACK EnumFontsProc(ENUMLOGFONTEX * lpelfe, NEWTEXTMETRICEX * lpntme, int FontType, LPARAM lParam) +{ + if (!IsWindow((HWND) lParam)) + return FALSE; + if (SendMessage((HWND) lParam, CB_FINDSTRINGEXACT, -1, (LPARAM) lpelfe->elfLogFont.lfFaceName) == CB_ERR) + SendMessage((HWND) lParam, CB_ADDSTRING, 0, (LPARAM) lpelfe->elfLogFont.lfFaceName); + return TRUE; +} + +void FillFontListThread(HWND hwndDlg) +{ + LOGFONT lf = { 0 }; + HDC hdc = GetDC(hwndDlg); + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfFaceName[0] = 0; + lf.lfPitchAndFamily = 0; + EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC) EnumFontsProc, (LPARAM) GetDlgItem(hwndDlg, IDC_TYPEFACE), 0); + ReleaseDC(hwndDlg, hdc); + return; +} + +static int CALLBACK EnumFontScriptsProc(ENUMLOGFONTEX * lpelfe, NEWTEXTMETRICEX * lpntme, int FontType, LPARAM lParam) +{ + if (SendMessage((HWND) lParam, CB_FINDSTRINGEXACT, -1, (LPARAM) lpelfe->elfScript) == CB_ERR) { + int i = SendMessage((HWND) lParam, CB_ADDSTRING, 0, (LPARAM) lpelfe->elfScript); + SendMessage((HWND) lParam, CB_SETITEMDATA, i, lpelfe->elfLogFont.lfCharSet); + } + return TRUE; +} + +static int TextOptsDlgResizer(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL * urc) +{ + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; +} + +static void SwitchTextDlgToMode(HWND hwndDlg, int expert) +{ + ShowWindow(GetDlgItem(hwndDlg, IDC_GAMMACORRECT), expert ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_STSAMETEXT), expert ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SAMETYPE), expert ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SAMESIZE), expert ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SAMESTYLE), expert ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SAMECOLOUR), expert ? SW_SHOW : SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_STSIZETEXT), expert ? SW_HIDE : SW_SHOW); + ShowWindow(GetDlgItem(hwndDlg, IDC_STCOLOURTEXT), expert ? SW_HIDE : SW_SHOW); + SetDlgItemText(hwndDlg, IDC_STASTEXT, TranslateTS(expert ? _T("as:") : _T("based on:"))); + { + UTILRESIZEDIALOG urd = { 0 }; + urd.cbSize = sizeof(urd); + urd.hwndDlg = hwndDlg; + urd.hInstance = g_hInst; + urd.lpTemplate = MAKEINTRESOURCEA(expert ? IDD_OPT_CLCTEXT : IDD_OPT_CLCTEXTSIMPLE); + urd.pfnResizer = TextOptsDlgResizer; + CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) & urd); + } + //resizer breaks the sizing of the edit box + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETBUDDY, (WPARAM) GetDlgItem(hwndDlg, IDC_ROWHEIGHT), 0); + SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, + SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETCURSEL, 0, 0), 0), 0); +} + +static BOOL CALLBACK DlgProcClcTextOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HFONT hFontSample; + + switch (msg) { + case WM_INITDIALOG: + hFontSample = NULL; + SetDlgItemTextA(hwndDlg, IDC_SAMPLE, "Sample"); + TranslateDialogDefault(hwndDlg); + if (!SendMessage(GetParent(hwndDlg), PSM_ISEXPERT, 0, 0)) + SwitchTextDlgToMode(hwndDlg, 0); + forkthread(FillFontListThread, 0, hwndDlg); + { + int i, itemId, fontId; + LOGFONT lf; + COLORREF colour; + WORD sameAs; + char str[32]; + + for (i = 0; i <= FONTID_LAST; i++) { + fontId = fontListOrder[i]; + pcli->pfnGetFontSetting(fontId, &lf, &colour); + wsprintfA(str, "Font%dAs", fontId); + sameAs = DBGetContactSettingWord(NULL, "CLC", str, fontSameAsDefault[fontId]); + fontSettings[fontId].sameAsFlags = HIBYTE(sameAs); + fontSettings[fontId].sameAs = LOBYTE(sameAs); + fontSettings[fontId].style = + (lf.lfWeight == FW_NORMAL ? 0 : DBFONTF_BOLD) | (lf.lfItalic ? DBFONTF_ITALIC : 0) | (lf.lfUnderline ? DBFONTF_UNDERLINE : 0); + if (lf.lfHeight < 0) { + HDC hdc; + SIZE size; + HFONT hFont = CreateFontIndirect(&lf); + hdc = GetDC(hwndDlg); + SelectObject(hdc, hFont); + GetTextExtentPoint32A(hdc, "_W", 2, &size); + ReleaseDC(hwndDlg, hdc); + DeleteObject(hFont); + fontSettings[fontId].size = (char) size.cy; + } + else fontSettings[fontId].size = (char) lf.lfHeight; + fontSettings[fontId].charset = lf.lfCharSet; + fontSettings[fontId].colour = colour; + lstrcpy(fontSettings[fontId].szFace, lf.lfFaceName); + itemId = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_ADDSTRING, 0, (LPARAM) TranslateTS( szFontIdDescr[fontId] )); + SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_SETITEMDATA, itemId, fontId); + } + SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_SETCURSEL, 0, 0); + for (i = 0; i < SIZEOF(fontSizes); i++) + SendDlgItemMessageA(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM) fontSizes[i]); + } + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETRANGE, 0, MAKELONG(255, 0)); + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETPOS, 0, MAKELONG(DBGetContactSettingByte(NULL, "CLC", "RowHeight", CLCDEFAULT_ROWHEIGHT), 0)); + SendMessage(hwndDlg, M_REBUILDFONTGROUP, 0, 0); + SendMessage(hwndDlg, M_SAVEFONT, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_HOTCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_HOTTEXTCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_HOTCOLOUR, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, "CLC", "HotTextColour", CLCDEFAULT_HOTTEXTCOLOUR)); + CheckDlgButton(hwndDlg, IDC_GAMMACORRECT, DBGetContactSettingByte(NULL, "CLC", "GammaCorrect", CLCDEFAULT_GAMMACORRECT) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_SELTEXTCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, "CLC", "SelTextColour", CLCDEFAULT_SELTEXTCOLOUR)); + SendDlgItemMessage(hwndDlg, IDC_QUICKCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_QUICKSEARCHCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_QUICKCOLOUR, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, "CLC", "QuickSearchColour", CLCDEFAULT_QUICKSEARCHCOLOUR)); + return TRUE; + case M_REBUILDFONTGROUP: //remake all the needed controls when the user changes the font selector at the top + { + int i = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETCURSEL, 0, 0), 0); + SendMessage(hwndDlg, M_SETSAMEASBOXES, i, 0); + { + int j, id, itemId; + char szText[256]; + SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_RESETCONTENT, 0, 0); + itemId = SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_ADDSTRING, 0, (LPARAM) TranslateT("")); + SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETITEMDATA, itemId, 0xFF); + if (0xFF == fontSettings[i].sameAs) + SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, itemId, 0); + for (j = 0; j <= FONTID_LAST; j++) { + SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETLBTEXT, j, (LPARAM) szText); + id = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETITEMDATA, j, 0); + if (id == i) + continue; + itemId = SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_ADDSTRING, 0, (LPARAM) szText); + SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETITEMDATA, itemId, id); + if (id == fontSettings[i].sameAs) + SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, itemId, 0); + } + } + SendMessage(hwndDlg, M_LOADFONT, i, 0); + SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, i, 0); + SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0); + break; + } + case M_SETSAMEASBOXES: //set the check mark in the 'same as' boxes to the right value for fontid wParam + CheckDlgButton(hwndDlg, IDC_SAMETYPE, fontSettings[wParam].sameAsFlags & SAMEASF_FACE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SAMESIZE, fontSettings[wParam].sameAsFlags & SAMEASF_SIZE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SAMESTYLE, fontSettings[wParam].sameAsFlags & SAMEASF_STYLE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SAMECOLOUR, fontSettings[wParam].sameAsFlags & SAMEASF_COLOUR ? BST_CHECKED : BST_UNCHECKED); + break; + case M_FILLSCRIPTCOMBO: //fill the script combo box and set the selection to the value for fontid wParam + { + LOGFONT lf = { 0 }; + int i; + HDC hdc = GetDC(hwndDlg); + lf.lfCharSet = DEFAULT_CHARSET; + GetDlgItemText(hwndDlg, IDC_TYPEFACE, lf.lfFaceName, LF_FACESIZE ); + lf.lfPitchAndFamily = 0; + SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_RESETCONTENT, 0, 0); + EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC) EnumFontScriptsProc, (LPARAM) GetDlgItem(hwndDlg, IDC_SCRIPT), 0); + ReleaseDC(hwndDlg, hdc); + for (i = SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCOUNT, 0, 0) - 1; i >= 0; i--) { + if (SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETITEMDATA, i, 0) == fontSettings[wParam].charset) { + SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_SETCURSEL, i, 0); + break; + } + } + if (i < 0) + SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_SETCURSEL, 0, 0); + break; + } + case WM_CTLCOLORSTATIC: + if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SAMPLE)) { + SetTextColor((HDC) wParam, SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_GETCOLOUR, 0, 0)); + SetBkColor((HDC) wParam, GetSysColor(COLOR_3DFACE)); + return (BOOL) GetSysColorBrush(COLOR_3DFACE); + } + break; + case M_REFRESHSAMEASBOXES: //set the disabled flag on the 'same as' checkboxes to the values for fontid wParam + EnableWindow(GetDlgItem(hwndDlg, IDC_SAMETYPE), fontSettings[wParam].sameAs != 0xFF); + EnableWindow(GetDlgItem(hwndDlg, IDC_SAMESIZE), fontSettings[wParam].sameAs != 0xFF); + EnableWindow(GetDlgItem(hwndDlg, IDC_SAMESTYLE), fontSettings[wParam].sameAs != 0xFF); + EnableWindow(GetDlgItem(hwndDlg, IDC_SAMECOLOUR), fontSettings[wParam].sameAs != 0xFF); + if (SendMessage(GetParent(hwndDlg), PSM_ISEXPERT, 0, 0)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEFACE), fontSettings[wParam].sameAs == 0xFF + || !(fontSettings[wParam].sameAsFlags & SAMEASF_FACE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SCRIPT), fontSettings[wParam].sameAs == 0xFF + || !(fontSettings[wParam].sameAsFlags & SAMEASF_FACE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_FONTSIZE), fontSettings[wParam].sameAs == 0xFF + || !(fontSettings[wParam].sameAsFlags & SAMEASF_SIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOLD), fontSettings[wParam].sameAs == 0xFF + || !(fontSettings[wParam].sameAsFlags & SAMEASF_STYLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_ITALIC), fontSettings[wParam].sameAs == 0xFF + || !(fontSettings[wParam].sameAsFlags & SAMEASF_STYLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_UNDERLINE), fontSettings[wParam].sameAs == 0xFF + || !(fontSettings[wParam].sameAsFlags & SAMEASF_STYLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_COLOUR), fontSettings[wParam].sameAs == 0xFF + || !(fontSettings[wParam].sameAsFlags & SAMEASF_COLOUR)); + } + else { + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEFACE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SCRIPT), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_FONTSIZE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOLD), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ITALIC), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_UNDERLINE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_COLOUR), TRUE); + } + break; + case M_REMAKESAMPLE: //remake the sample edit box font based on the settings in the controls + { + LOGFONTA lf; + if (hFontSample) { + SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDC_FONTID, WM_GETFONT, 0, 0), 0); + DeleteObject(hFontSample); + } + lf.lfHeight = GetDlgItemInt(hwndDlg, IDC_FONTSIZE, NULL, FALSE); + { + HDC hdc = GetDC(NULL); + lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); + ReleaseDC(NULL, hdc); + } + lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0; + lf.lfWeight = IsDlgButtonChecked(hwndDlg, IDC_BOLD) ? FW_BOLD : FW_NORMAL; + lf.lfItalic = IsDlgButtonChecked(hwndDlg, IDC_ITALIC); + lf.lfUnderline = IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE); + lf.lfStrikeOut = 0; + lf.lfCharSet = (BYTE) SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCURSEL, 0, 0), 0); + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = DEFAULT_QUALITY; + lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + GetDlgItemTextA(hwndDlg, IDC_TYPEFACE, lf.lfFaceName, SIZEOF(lf.lfFaceName)); + hFontSample = CreateFontIndirectA(&lf); + SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, (WPARAM) hFontSample, TRUE); + break; + } + case M_RECALCONEFONT: //copy the 'same as' settings for fontid wParam from their sources + if (fontSettings[wParam].sameAs == 0xFF) + break; + if (fontSettings[wParam].sameAsFlags & SAMEASF_FACE) { + lstrcpy(fontSettings[wParam].szFace, fontSettings[fontSettings[wParam].sameAs].szFace); + fontSettings[wParam].charset = fontSettings[fontSettings[wParam].sameAs].charset; + } + if (fontSettings[wParam].sameAsFlags & SAMEASF_SIZE) + fontSettings[wParam].size = fontSettings[fontSettings[wParam].sameAs].size; + if (fontSettings[wParam].sameAsFlags & SAMEASF_STYLE) + fontSettings[wParam].style = fontSettings[fontSettings[wParam].sameAs].style; + if (fontSettings[wParam].sameAsFlags & SAMEASF_COLOUR) + fontSettings[wParam].colour = fontSettings[fontSettings[wParam].sameAs].colour; + break; + case M_RECALCOTHERFONTS: //recalculate the 'same as' settings for all fonts but wParam + { + int i; + for (i = 0; i <= FONTID_LAST; i++) { + if (i == (int) wParam) + continue; + SendMessage(hwndDlg, M_RECALCONEFONT, i, 0); + } + break; + } + case M_SAVEFONT: //save the font settings from the controls to font wParam + fontSettings[wParam].sameAsFlags = + (IsDlgButtonChecked(hwndDlg, IDC_SAMETYPE) ? SAMEASF_FACE : 0) | (IsDlgButtonChecked(hwndDlg, IDC_SAMESIZE) ? SAMEASF_SIZE : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SAMESTYLE) ? SAMEASF_STYLE : 0) | (IsDlgButtonChecked(hwndDlg, IDC_SAMECOLOUR) ? SAMEASF_COLOUR : 0); + fontSettings[wParam].sameAs = + (BYTE) SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_GETCURSEL, 0, 0), 0); + GetDlgItemText(hwndDlg, IDC_TYPEFACE, fontSettings[wParam].szFace, SIZEOF( fontSettings[wParam].szFace )); + fontSettings[wParam].charset = + (BYTE) SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCURSEL, 0, 0), 0); + fontSettings[wParam].size = (char) GetDlgItemInt(hwndDlg, IDC_FONTSIZE, NULL, FALSE); + fontSettings[wParam].style = + (IsDlgButtonChecked(hwndDlg, IDC_BOLD) ? DBFONTF_BOLD : 0) | (IsDlgButtonChecked(hwndDlg, IDC_ITALIC) ? DBFONTF_ITALIC : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE) ? DBFONTF_UNDERLINE : 0); + fontSettings[wParam].colour = SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_GETCOLOUR, 0, 0); + SendMessage(hwndDlg, M_REDOROWHEIGHT, 0, 0); + break; + case M_REDOROWHEIGHT: //recalculate the minimum feasible row height + { + int i; + int minHeight = GetSystemMetrics(SM_CYSMICON); + for (i = 0; i <= FONTID_LAST; i++) + if (fontSettings[i].size > minHeight) + minHeight = fontSettings[i].size; + i = SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_GETPOS, 0, 0); + if (i < minHeight) + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETPOS, 0, MAKELONG(minHeight, 0)); + break; + } + case M_LOADFONT: //load font wParam into the controls + SetDlgItemText(hwndDlg, IDC_TYPEFACE, fontSettings[wParam].szFace); + SendMessage(hwndDlg, M_FILLSCRIPTCOMBO, wParam, 0); + SetDlgItemInt(hwndDlg, IDC_FONTSIZE, fontSettings[wParam].size, FALSE); + CheckDlgButton(hwndDlg, IDC_BOLD, fontSettings[wParam].style & DBFONTF_BOLD ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ITALIC, fontSettings[wParam].style & DBFONTF_ITALIC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_UNDERLINE, fontSettings[wParam].style & DBFONTF_UNDERLINE ? BST_CHECKED : BST_UNCHECKED); + { + LOGFONT lf; + COLORREF colour; + pcli->pfnGetDefaultFontSetting(wParam, &lf, &colour); + SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_SETDEFAULTCOLOUR, 0, colour); + } + SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_SETCOLOUR, 0, fontSettings[wParam].colour); + break; + case M_GUESSSAMEASBOXES: //guess suitable values for the 'same as' checkboxes for fontId wParam + fontSettings[wParam].sameAsFlags = 0; + if (fontSettings[wParam].sameAs == 0xFF) + break; + if (!lstrcmp(fontSettings[wParam].szFace, fontSettings[fontSettings[wParam].sameAs].szFace) && + fontSettings[wParam].charset == fontSettings[fontSettings[wParam].sameAs].charset) + fontSettings[wParam].sameAsFlags |= SAMEASF_FACE; + if (fontSettings[wParam].size == fontSettings[fontSettings[wParam].sameAs].size) + fontSettings[wParam].sameAsFlags |= SAMEASF_SIZE; + if (fontSettings[wParam].style == fontSettings[fontSettings[wParam].sameAs].style) + fontSettings[wParam].sameAsFlags |= SAMEASF_STYLE; + if (fontSettings[wParam].colour == fontSettings[fontSettings[wParam].sameAs].colour) + fontSettings[wParam].sameAsFlags |= SAMEASF_COLOUR; + SendMessage(hwndDlg, M_SETSAMEASBOXES, wParam, 0); + break; + case WM_VSCROLL: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_COMMAND: + { + int fontId = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETCURSEL, 0, 0), 0); + switch (LOWORD(wParam)) { + case IDC_FONTID: + if (HIWORD(wParam) != CBN_SELCHANGE) + return FALSE; + SendMessage(hwndDlg, M_REBUILDFONTGROUP, 0, 0); + return 0; + case IDC_SAMETYPE: + case IDC_SAMESIZE: + case IDC_SAMESTYLE: + case IDC_SAMECOLOUR: + SendMessage(hwndDlg, M_SAVEFONT, fontId, 0); + SendMessage(hwndDlg, M_RECALCONEFONT, fontId, 0); + SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0); + SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, fontId, 0); + break; + case IDC_SAMEAS: + if (HIWORD(wParam) != CBN_SELCHANGE) + return FALSE; + if (SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_GETCURSEL, 0, 0), 0) == + fontId) + SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, 0, 0); + if (!SendMessage(GetParent(hwndDlg), PSM_ISEXPERT, 0, 0)) { + int sameAs = + SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_GETCURSEL, 0, 0), 0); + if (sameAs != 0xFF) + SendMessage(hwndDlg, M_LOADFONT, sameAs, 0); + SendMessage(hwndDlg, M_SAVEFONT, fontId, 0); + SendMessage(hwndDlg, M_GUESSSAMEASBOXES, fontId, 0); + } + else + SendMessage(hwndDlg, M_SAVEFONT, fontId, 0); + SendMessage(hwndDlg, M_RECALCONEFONT, fontId, 0); + SendMessage(hwndDlg, M_FILLSCRIPTCOMBO, fontId, 0); + SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0); + SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, fontId, 0); + break; + case IDC_TYPEFACE: + case IDC_SCRIPT: + case IDC_FONTSIZE: + if (HIWORD(wParam) != CBN_EDITCHANGE && HIWORD(wParam) != CBN_SELCHANGE) + return FALSE; + if (HIWORD(wParam) == CBN_SELCHANGE) { + SendDlgItemMessage(hwndDlg, LOWORD(wParam), CB_SETCURSEL, SendDlgItemMessage(hwndDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0), 0); + } + if (LOWORD(wParam) == IDC_TYPEFACE) + SendMessage(hwndDlg, M_FILLSCRIPTCOMBO, fontId, 0); + //fall through + case IDC_BOLD: + case IDC_ITALIC: + case IDC_UNDERLINE: + case IDC_COLOUR: + SendMessage(hwndDlg, M_SAVEFONT, fontId, 0); + if (!SendMessage(GetParent(hwndDlg), PSM_ISEXPERT, 0, 0)) { + SendMessage(hwndDlg, M_GUESSSAMEASBOXES, fontId, 0); + SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, fontId, 0); + } + SendMessage(hwndDlg, M_RECALCOTHERFONTS, fontId, 0); + SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0); + SendMessage(hwndDlg, M_REDOROWHEIGHT, 0, 0); + break; + case IDC_SAMPLE: + return 0; + case IDC_ROWHEIGHT: + if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return 0; + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + int i; + char str[20]; + + // Force min height calculation + // This prevents users from setting the row height to be too low + SendMessage(hwndDlg, M_REDOROWHEIGHT, 0, 0); + for (i = 0; i <= FONTID_LAST; i++) { + wsprintfA(str, "Font%dName", i); + DBWriteContactSettingTString(NULL, "CLC", str, fontSettings[i].szFace); + wsprintfA(str, "Font%dSet", i); + DBWriteContactSettingByte(NULL, "CLC", str, fontSettings[i].charset); + wsprintfA(str, "Font%dSize", i); + DBWriteContactSettingByte(NULL, "CLC", str, fontSettings[i].size); + wsprintfA(str, "Font%dSty", i); + DBWriteContactSettingByte(NULL, "CLC", str, fontSettings[i].style); + wsprintfA(str, "Font%dCol", i); + DBWriteContactSettingDword(NULL, "CLC", str, fontSettings[i].colour); + wsprintfA(str, "Font%dAs", i); + DBWriteContactSettingWord(NULL, "CLC", str, (WORD) ((fontSettings[i].sameAsFlags << 8) | fontSettings[i].sameAs)); + } + } + { + COLORREF col; + col = SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_GETCOLOUR, 0, 0); + if (col == CLCDEFAULT_SELTEXTCOLOUR) + DBDeleteContactSetting(NULL, "CLC", "SelTextColour"); + else + DBWriteContactSettingDword(NULL, "CLC", "SelTextColour", col); + col = SendDlgItemMessage(hwndDlg, IDC_HOTCOLOUR, CPM_GETCOLOUR, 0, 0); + if (col == CLCDEFAULT_HOTTEXTCOLOUR) + DBDeleteContactSetting(NULL, "CLC", "HotTextColour"); + else + DBWriteContactSettingDword(NULL, "CLC", "HotTextColour", col); + col = SendDlgItemMessage(hwndDlg, IDC_QUICKCOLOUR, CPM_GETCOLOUR, 0, 0); + if (col == CLCDEFAULT_QUICKSEARCHCOLOUR) + DBDeleteContactSetting(NULL, "CLC", "QuickSearchColour"); + else + DBWriteContactSettingDword(NULL, "CLC", "QuickSearchColour", col); + } + DBWriteContactSettingByte(NULL, "CLC", "RowHeight", (BYTE) SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CLC", "GammaCorrect", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_GAMMACORRECT)); + pcli->pfnClcOptionsChanged(); + return TRUE; + case PSN_EXPERTCHANGED: + SwitchTextDlgToMode(hwndDlg, ((PSHNOTIFY *) lParam)->lParam); + break; + } + break; + } + break; + case WM_DESTROY: + if (hFontSample) { + SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDC_FONTID, WM_GETFONT, 0, 0), 0); + DeleteObject(hFontSample); + } + break; + } + return FALSE; +} + +/****************************************************************************************/ + +int ClcOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 0; + odp.hInstance = g_hInst; + odp.pszGroup = "Contact List"; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLC); + odp.pszTitle = "List"; + odp.pfnDlgProc = DlgProcClcMainOpts; + odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLCBKG); + odp.pszTitle = "List Background"; + odp.pfnDlgProc = DlgProcClcBkgOpts; + odp.flags = ODPF_BOLDGROUPS; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLCTEXT); + odp.pszTitle = "List Text"; + odp.pfnDlgProc = DlgProcClcTextOpts; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + return 0; +} diff --git a/miranda-wine/plugins/clist/clcpaint.c b/miranda-wine/plugins/clist/clcpaint.c new file mode 100644 index 0000000..d244c88 --- /dev/null +++ b/miranda-wine/plugins/clist/clcpaint.c @@ -0,0 +1,590 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ +#include "commonheaders.h" + +extern HIMAGELIST himlCListClc; +static BYTE divide3[765] = { 255 }; + +static void ChangeToFont(HDC hdc, struct ClcData *dat, int id, int *fontHeight) +{ + SelectObject(hdc, dat->fontInfo[id].hFont); + SetTextColor(hdc, dat->fontInfo[id].colour); + if (fontHeight) + *fontHeight = dat->fontInfo[id].fontHeight; +} + +static void __inline SetHotTrackColour(HDC hdc, struct ClcData *dat) +{ + if (dat->gammaCorrection) { + COLORREF oldCol, newCol; + int oldLum, newLum; + + oldCol = GetTextColor(hdc); + oldLum = (GetRValue(oldCol) * 30 + GetGValue(oldCol) * 59 + GetBValue(oldCol) * 11) / 100; + newLum = (GetRValue(dat->hotTextColour) * 30 + GetGValue(dat->hotTextColour) * 59 + GetBValue(dat->hotTextColour) * 11) / 100; + if (newLum == 0) { + SetTextColor(hdc, dat->hotTextColour); + return; + } + if (newLum >= oldLum + 20) { + oldLum += 20; + newCol = + RGB(GetRValue(dat->hotTextColour) * oldLum / newLum, GetGValue(dat->hotTextColour) * oldLum / newLum, + GetBValue(dat->hotTextColour) * oldLum / newLum); + } + else if (newLum <= oldLum) { + int r, g, b; + r = GetRValue(dat->hotTextColour) * oldLum / newLum; + g = GetGValue(dat->hotTextColour) * oldLum / newLum; + b = GetBValue(dat->hotTextColour) * oldLum / newLum; + if (r > 255) { + g += (r - 255) * 3 / 7; + b += (r - 255) * 3 / 7; + r = 255; + } + if (g > 255) { + r += (g - 255) * 59 / 41; + if (r > 255) + r = 255; + b += (g - 255) * 59 / 41; + g = 255; + } + if (b > 255) { + r += (b - 255) * 11 / 89; + if (r > 255) + r = 255; + g += (b - 255) * 11 / 89; + if (g > 255) + g = 255; + b = 255; + } + newCol = RGB(r, g, b); + } + else + newCol = dat->hotTextColour; + SetTextColor(hdc, newCol); + } + else + SetTextColor(hdc, dat->hotTextColour); +} + +static int GetStatusOnlineness(int status) +{ + switch (status) { + case ID_STATUS_FREECHAT: return 110; + case ID_STATUS_ONLINE: return 100; + case ID_STATUS_OCCUPIED: return 60; + case ID_STATUS_ONTHEPHONE: return 50; + case ID_STATUS_DND: return 40; + case ID_STATUS_AWAY: return 30; + case ID_STATUS_OUTTOLUNCH: return 20; + case ID_STATUS_NA: return 10; + case ID_STATUS_INVISIBLE: return 5; + } + return 0; +} + +static int GetGeneralisedStatus(void) +{ + int i, status, thisStatus, statusOnlineness, thisOnlineness; + + status = ID_STATUS_OFFLINE; + statusOnlineness = 0; + + for (i = 0; i < pcli->hClcProtoCount; i++) { + thisStatus = pcli->clcProto[i].dwStatus; + if (thisStatus == ID_STATUS_INVISIBLE) + return ID_STATUS_INVISIBLE; + thisOnlineness = GetStatusOnlineness(thisStatus); + if (thisOnlineness > statusOnlineness) { + status = thisStatus; + statusOnlineness = thisOnlineness; + } + } + return status; +} + +static int GetRealStatus(struct ClcContact *contact, int status) +{ + int i; + char *szProto = contact->proto; + if (!szProto) + return status; + for (i = 0; i < pcli->hClcProtoCount; i++) { + if (!lstrcmpA(pcli->clcProto[i].szProto, szProto)) { + return pcli->clcProto[i].dwStatus; + } + } + return status; +} + +static HMODULE themeAPIHandle = NULL; // handle to uxtheme.dll +static HANDLE(WINAPI * MyOpenThemeData) (HWND, LPCWSTR); +static HRESULT(WINAPI * MyCloseThemeData) (HANDLE); +static HRESULT(WINAPI * MyDrawThemeBackground) (HANDLE, HDC, int, int, const RECT *, const RECT *); + +#define MGPROC(x) GetProcAddress(themeAPIHandle,x) +void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT * rcPaint) +{ + HDC hdcMem; + RECT clRect; + int y, indent, index, fontHeight; + struct ClcGroup *group; + HBITMAP hBmpOsb, hOldBitmap; + HFONT hOldFont; + DWORD style = GetWindowLong(hwnd, GWL_STYLE); + int status = GetGeneralisedStatus(); + int grey = 0, groupCountsFontTopShift; + HBRUSH hBrushAlternateGrey = NULL; + // yes I know about GetSysColorBrush() + COLORREF tmpbkcolour = style & CLS_CONTACTLIST ? (dat->useWindowsColours ? GetSysColor(COLOR_3DFACE) : dat->bkColour) : dat->bkColour; + + if (dat->greyoutFlags & pcli->pfnClcStatusToPf2(status) || style & WS_DISABLED) + grey = 1; + else if (GetFocus() != hwnd && dat->greyoutFlags & GREYF_UNFOCUS) + grey = 1; + GetClientRect(hwnd, &clRect); + if (rcPaint == NULL) + rcPaint = &clRect; + if (IsRectEmpty(rcPaint)) + return; + y = -dat->yScroll; + hdcMem = CreateCompatibleDC(hdc); + hBmpOsb = CreateBitmap(clRect.right, clRect.bottom, 1, GetDeviceCaps(hdc, BITSPIXEL), NULL); + hOldBitmap = SelectObject(hdcMem, hBmpOsb); + { + TEXTMETRIC tm; + hOldFont = SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPS].hFont); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift = tm.tmAscent; + SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift -= tm.tmAscent; + } + if (style & CLS_GREYALTERNATE) + hBrushAlternateGrey = + CreateSolidBrush(GetNearestColor(hdcMem, RGB(GetRValue(tmpbkcolour) - 10, GetGValue(tmpbkcolour) - 10, GetBValue(tmpbkcolour) - 10))); + + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + SetBkMode(hdcMem, TRANSPARENT); + { + HBRUSH hBrush, hoBrush; + + hBrush = CreateSolidBrush(tmpbkcolour); + hoBrush = (HBRUSH) SelectObject(hdcMem, hBrush); + FillRect(hdcMem, rcPaint, hBrush); + SelectObject(hdcMem, hoBrush); + DeleteObject(hBrush); + if (dat->hBmpBackground) { + BITMAP bmp; + HDC hdcBmp; + int x, y; + int maxx, maxy; + int destw, desth; + + // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98. + SetStretchBltMode(hdcMem, HALFTONE); + + GetObject(dat->hBmpBackground, sizeof(bmp), &bmp); + hdcBmp = CreateCompatibleDC(hdcMem); + SelectObject(hdcBmp, dat->hBmpBackground); + y = dat->backgroundBmpUse & CLBF_SCROLL ? -dat->yScroll : 0; + maxx = dat->backgroundBmpUse & CLBF_TILEH ? clRect.right : 1; + maxy = dat->backgroundBmpUse & CLBF_TILEV ? maxy = rcPaint->bottom : y + 1; + switch (dat->backgroundBmpUse & CLBM_TYPE) { + case CLB_STRETCH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + if (clRect.right * bmp.bmHeight < clRect.bottom * bmp.bmWidth) { + desth = clRect.bottom; + destw = desth * bmp.bmWidth / bmp.bmHeight; + } + else { + destw = clRect.right; + desth = destw * bmp.bmHeight / bmp.bmWidth; + } + } + else { + destw = clRect.right; + desth = clRect.bottom; + } + break; + case CLB_STRETCHH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + destw = clRect.right; + desth = destw * bmp.bmHeight / bmp.bmWidth; + } + else { + destw = clRect.right; + desth = bmp.bmHeight; + } + break; + case CLB_STRETCHV: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + desth = clRect.bottom; + destw = desth * bmp.bmWidth / bmp.bmHeight; + } + else { + destw = bmp.bmWidth; + desth = clRect.bottom; + } + break; + default: //clb_topleft + destw = bmp.bmWidth; + desth = bmp.bmHeight; + break; + } + for (; y < maxy; y += desth) { + if (y < rcPaint->top - desth) + continue; + for (x = 0; x < maxx; x += destw) + StretchBlt(hdcMem, x, y, destw, desth, hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); + } + DeleteDC(hdcBmp); + } + } + group = &dat->list; + group->scanIndex = 0; + indent = 0; + for (index = 0; y < rcPaint->bottom;) { + if (group->scanIndex == group->cl.count) { + group = group->parent; + indent--; + if (group == NULL) + break; + group->scanIndex++; + continue; + } + if (y > rcPaint->top - dat->rowHeight) { + int iImage = -1; + int selected = index == dat->selection && (dat->showSelAlways || dat->exStyle & CLS_EX_SHOWSELALWAYS || GetFocus() == hwnd) + && group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER; + int hottrack = dat->exStyle & CLS_EX_TRACKSELECT && group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER && dat->iHotTrack == index; + SIZE textSize, countsSize, spaceSize; + int width, checkboxWidth; + char *szCounts; + + //alternating grey + if (style & CLS_GREYALTERNATE && index & 1) { + RECT rc; + rc.top = y; + rc.bottom = rc.top + dat->rowHeight; + rc.left = 0; + rc.right = clRect.right; + FillRect(hdcMem, &rc, hBrushAlternateGrey); + } + + //setup + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + else if (group->cl.items[group->scanIndex]->type == CLCIT_INFO) { + if (group->cl.items[group->scanIndex]->flags & CLCIIF_GROUPFONT) + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + else + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_DIVIDER) + ChangeToFont(hdcMem, dat, FONTID_DIVIDERS, &fontHeight); + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) + ChangeToFont(hdcMem, dat, FONTID_NOTONLIST, &fontHeight); + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && + ((group->cl.items[group->scanIndex]->flags & CONTACTF_INVISTO + && GetRealStatus(group->cl.items[group->scanIndex], status) != ID_STATUS_INVISIBLE) + || (group->cl.items[group->scanIndex]->flags & CONTACTF_VISTO + && GetRealStatus(group->cl.items[group->scanIndex], status) == ID_STATUS_INVISIBLE) + ) + ) { + // the contact is in the always visible list and the proto is invisible + // the contact is in the always invisible and the proto is in any other mode + ChangeToFont(hdcMem, dat, group->cl.items[group->scanIndex]->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS, &fontHeight); + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && !(group->cl.items[group->scanIndex]->flags & CONTACTF_ONLINE)) + ChangeToFont(hdcMem, dat, FONTID_OFFLINE, &fontHeight); + else + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + GetTextExtentPoint32(hdcMem, group->cl.items[group->scanIndex]->szText, lstrlen(group->cl.items[group->scanIndex]->szText), &textSize); + width = textSize.cx; + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { + szCounts = pcli->pfnGetGroupCountsText(dat, group->cl.items[group->scanIndex]); + if (szCounts[0]) { + GetTextExtentPoint32A(hdcMem, " ", 1, &spaceSize); + ChangeToFont(hdcMem, dat, FONTID_GROUPCOUNTS, &fontHeight); + GetTextExtentPoint32A(hdcMem, szCounts, lstrlenA(szCounts), &countsSize); + width += spaceSize.cx + countsSize.cx; + } + } + + if ((style & CLS_CHECKBOXES && group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) || + (style & CLS_GROUPCHECKBOXES && group->cl.items[group->scanIndex]->type == CLCIT_GROUP) || + (group->cl.items[group->scanIndex]->type == CLCIT_INFO && group->cl.items[group->scanIndex]->flags & CLCIIF_CHECKBOX)) + checkboxWidth = dat->checkboxSize + 2; + else + checkboxWidth = 0; + + //background + if (selected) { + int x = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace - 2; + ImageList_DrawEx(dat->himlHighlight, 0, hdcMem, x, y, min(width + 5, clRect.right - x), dat->rowHeight, CLR_NONE, CLR_NONE, + dat->exStyle & CLS_EX_NOTRANSLUCENTSEL ? ILD_NORMAL : ILD_BLEND25); + SetTextColor(hdcMem, dat->selTextColour); + } + else if (hottrack) + SetHotTrackColour(hdcMem, dat); + + //checkboxes + if (checkboxWidth) { + RECT rc; + HANDLE hTheme = NULL; + + // THEME + if (IsWinVerXPPlus()) { + if (!themeAPIHandle) { + themeAPIHandle = GetModuleHandleA("uxtheme"); + if (themeAPIHandle) { + MyOpenThemeData = (HANDLE(WINAPI *) (HWND, LPCWSTR)) MGPROC("OpenThemeData"); + MyCloseThemeData = (HRESULT(WINAPI *) (HANDLE)) MGPROC("CloseThemeData"); + MyDrawThemeBackground = + (HRESULT(WINAPI *) (HANDLE, HDC, int, int, const RECT *, const RECT *)) MGPROC("DrawThemeBackground"); + } + } + // Make sure all of these methods are valid (i would hope either all or none work) + if (MyOpenThemeData && MyCloseThemeData && MyDrawThemeBackground) { + hTheme = MyOpenThemeData(hwnd, L"BUTTON"); + } + } + rc.left = dat->leftMargin + indent * dat->groupIndent; + rc.right = rc.left + dat->checkboxSize; + rc.top = y + ((dat->rowHeight - dat->checkboxSize) >> 1); + rc.bottom = rc.top + dat->checkboxSize; + if (hTheme) { + MyDrawThemeBackground(hTheme, hdcMem, BP_CHECKBOX, group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED ? (hottrack ? CBS_CHECKEDHOT : CBS_CHECKEDNORMAL) : (hottrack ? CBS_UNCHECKEDHOT : CBS_UNCHECKEDNORMAL), &rc, &rc); + } + else + DrawFrameControl(hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_FLAT | (group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED ? DFCS_CHECKED : 0) | (hottrack ? DFCS_HOT : 0)); + if (hTheme && MyCloseThemeData) { + MyCloseThemeData(hTheme); + hTheme = NULL; + } + } + + //icon + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) + iImage = group->cl.items[group->scanIndex]->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT; + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) + iImage = group->cl.items[group->scanIndex]->iImage; + if (iImage != -1) { + /*COLORREF colourFg=dat->selBkColour; + int mode=ILD_NORMAL; + if(selected) mode=ILD_SELECTED; + else if(hottrack) {mode=ILD_FOCUS; colourFg=dat->hotTextColour;} + else if(group->cl.items[group->scanIndex]->type==CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags&CONTACTF_NOTONLIST) {colourFg=dat->fontInfo[FONTID_NOTONLIST].colour; mode=ILD_BLEND50;} + ImageList_DrawEx(himlCListClc,iImage,hdcMem,dat->leftMargin+indent*dat->groupIndent+checkboxWidth,y+((dat->rowHeight-16)>>1),0,0,CLR_NONE,colourFg,mode); + */ + // this doesnt use CLS_CONTACTLIST since the colour prolly wont match anyway + COLORREF colourFg = dat->selBkColour; + int mode = ILD_NORMAL; + if (hottrack) { + colourFg = dat->hotTextColour; + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; + mode = ILD_BLEND50; + } + if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && dat->showIdle + && (group->cl.items[group->scanIndex]->flags & CONTACTF_IDLE) + && GetRealStatus(group->cl.items[group->scanIndex], ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) + mode = ILD_SELECTED; + ImageList_DrawEx(himlCListClc, iImage, hdcMem, dat->leftMargin + indent * dat->groupIndent + checkboxWidth, + y + ((dat->rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + } + + //text + if (group->cl.items[group->scanIndex]->type == CLCIT_DIVIDER) { + RECT rc; + rc.top = y + (dat->rowHeight >> 1); + rc.bottom = rc.top + 2; + rc.left = dat->leftMargin + indent * dat->groupIndent; + rc.right = rc.left + ((clRect.right - rc.left - textSize.cx) >> 1) - 3; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + TextOut(hdcMem, rc.right + 3, y + ((dat->rowHeight - fontHeight) >> 1), group->cl.items[group->scanIndex]->szText, + lstrlen(group->cl.items[group->scanIndex]->szText)); + rc.left = rc.right + 6 + textSize.cx; + rc.right = clRect.right; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { + RECT rc; + if (szCounts[0]) { + fontHeight = dat->fontInfo[FONTID_GROUPS].fontHeight; + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace; + rc.right = min(clRect.right - countsSize.cx, rc.left + textSize.cx + spaceSize.cx); + rc.top = y + ((dat->rowHeight - fontHeight) >> 1); + rc.bottom = rc.top + textSize.cy; + if (rc.right < rc.left + 4) + rc.right = clRect.right + 1; + else + TextOutA(hdcMem, rc.right, rc.top + groupCountsFontTopShift, szCounts, lstrlenA(szCounts)); + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + if (selected) + SetTextColor(hdcMem, dat->selTextColour); + else if (hottrack) + SetHotTrackColour(hdcMem, dat); + rc.right--; + ExtTextOut(hdcMem, rc.left, rc.top, ETO_CLIPPED, &rc, group->cl.items[group->scanIndex]->szText, + lstrlen(group->cl.items[group->scanIndex]->szText), NULL); + } + else + TextOut(hdcMem, dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace, + y + ((dat->rowHeight - fontHeight) >> 1), group->cl.items[group->scanIndex]->szText, + lstrlen(group->cl.items[group->scanIndex]->szText)); + if (dat->exStyle & CLS_EX_LINEWITHGROUPS) { + rc.top = y + (dat->rowHeight >> 1); + rc.bottom = rc.top + 2; + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 3; + rc.right = clRect.right - 1 - dat->extraColumnSpacing * dat->extraColumnsCount; + if (rc.right - rc.left > 1) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + } + else { + TCHAR *szText = group->cl.items[group->scanIndex]->szText; + RECT rc; + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace; + rc.top = y + ((dat->rowHeight - fontHeight) >> 1); + rc.right = (clRect.right - clRect.left); + rc.bottom = rc.top; + DrawText(hdcMem, szText, lstrlen(szText), &rc, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + if (selected) { + if (group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER) { + TCHAR *szText = group->cl.items[group->scanIndex]->szText; + RECT rc; + int qlen = lstrlen(dat->szQuickSearch); + SetTextColor(hdcMem, dat->quickSearchColour); + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace; + rc.top = y + ((dat->rowHeight - fontHeight) >> 1); + rc.right = (clRect.right - clRect.left); + rc.bottom = rc.top; + if (qlen) + DrawText(hdcMem, szText, qlen, &rc, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + } + + //extra icons + for (iImage = 0; iImage < dat->extraColumnsCount; iImage++) { + COLORREF colourFg = dat->selBkColour; + int mode = ILD_NORMAL; + if (group->cl.items[group->scanIndex]->iExtraImage[iImage] == 0xFF) + continue; + if (selected) + mode = ILD_SELECTED; + else if (hottrack) { + mode = ILD_FOCUS; + colourFg = dat->hotTextColour; + } + else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; + mode = ILD_BLEND50; + } + ImageList_DrawEx(dat->himlExtraColumns, group->cl.items[group->scanIndex]->iExtraImage[iImage], hdcMem, + clRect.right - dat->extraColumnSpacing * (dat->extraColumnsCount - iImage), y + ((dat->rowHeight - 16) >> 1), 0, 0, + CLR_NONE, colourFg, mode); + } + } + index++; + y += dat->rowHeight; + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && group->cl.items[group->scanIndex]->group->expanded) { + group = group->cl.items[group->scanIndex]->group; + indent++; + group->scanIndex = 0; + continue; + } + group->scanIndex++; + } + if (dat->iInsertionMark != -1) { //insertion mark + HBRUSH hBrush, hoBrush; + POINT pts[8]; + HRGN hRgn; + + pts[0].x = dat->leftMargin; + pts[0].y = dat->iInsertionMark * dat->rowHeight - dat->yScroll - 4; + pts[1].x = pts[0].x + 2; + pts[1].y = pts[0].y + 3; + pts[2].x = clRect.right - 4; + pts[2].y = pts[1].y; + pts[3].x = clRect.right - 1; + pts[3].y = pts[0].y - 1; + pts[4].x = pts[3].x; + pts[4].y = pts[0].y + 7; + pts[5].x = pts[2].x + 1; + pts[5].y = pts[1].y + 2; + pts[6].x = pts[1].x; + pts[6].y = pts[5].y; + pts[7].x = pts[0].x; + pts[7].y = pts[4].y; + hRgn = CreatePolygonRgn(pts, SIZEOF(pts), ALTERNATE); + hBrush = CreateSolidBrush(dat->fontInfo[FONTID_CONTACTS].colour); + hoBrush = (HBRUSH) SelectObject(hdcMem, hBrush); + FillRgn(hdcMem, hRgn, hBrush); + SelectObject(hdcMem, hoBrush); + DeleteObject(hBrush); + } + if (!grey) + BitBlt(hdc, rcPaint->left, rcPaint->top, rcPaint->right - rcPaint->left, rcPaint->bottom - rcPaint->top, hdcMem, rcPaint->left, rcPaint->top, + SRCCOPY); + SelectObject(hdcMem,hOldBitmap); + SelectObject(hdcMem,hOldFont); + DeleteDC(hdcMem); + if (hBrushAlternateGrey) + DeleteObject(hBrushAlternateGrey); + if (grey) { + PBYTE bits; + BITMAPINFOHEADER bmih = { 0 }; + int i; + int greyRed, greyGreen, greyBlue; + COLORREF greyColour; + bmih.biBitCount = 32; + bmih.biSize = sizeof(bmih); + bmih.biCompression = BI_RGB; + bmih.biHeight = -clRect.bottom; + bmih.biPlanes = 1; + bmih.biWidth = clRect.right; + bits = (PBYTE) malloc(4 * bmih.biWidth * -bmih.biHeight); + GetDIBits(hdc, hBmpOsb, 0, clRect.bottom, bits, (BITMAPINFO *) & bmih, DIB_RGB_COLORS); + greyColour = GetSysColor(COLOR_3DFACE); + greyRed = GetRValue(greyColour) * 2; + greyGreen = GetGValue(greyColour) * 2; + greyBlue = GetBValue(greyColour) * 2; + if (divide3[0] == 255) { + for (i = 0; i < SIZEOF(divide3); i++) + divide3[i] = (i + 1) / 3; + } + for (i = 4 * clRect.right * clRect.bottom - 4; i >= 0; i -= 4) { + bits[i] = divide3[bits[i] + greyBlue]; + bits[i + 1] = divide3[bits[i + 1] + greyGreen]; + bits[i + 2] = divide3[bits[i + 2] + greyRed]; + } + SetDIBitsToDevice(hdc, 0, 0, clRect.right, clRect.bottom, 0, 0, 0, clRect.bottom, bits, (BITMAPINFO *) & bmih, DIB_RGB_COLORS); + free(bits); + } + DeleteObject(hBmpOsb); +} diff --git a/miranda-wine/plugins/clist/clist.h b/miranda-wine/plugins/clist/clist.h new file mode 100644 index 0000000..4184dbe --- /dev/null +++ b/miranda-wine/plugins/clist/clist.h @@ -0,0 +1,30 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ +void LoadContactTree(void); +int IconFromStatusMode(const char *szProto,int status); +HTREEITEM GetTreeItemByHContact(HANDLE hContact); +void TrayIconUpdateWithImageList(int iImage,const char *szNewTip,char *szPreferredProto); +void SortContacts(void); +void ChangeContactIcon(HANDLE hContact,int iIcon,int add); + +#define NEWSTR_ALLOCA(A) (A==NULL)?NULL:strcpy((char*)alloca(strlen(A)+1),A) diff --git a/miranda-wine/plugins/clist/clistmenus.c b/miranda-wine/plugins/clist/clistmenus.c new file mode 100644 index 0000000..0480afa --- /dev/null +++ b/miranda-wine/plugins/clist/clistmenus.c @@ -0,0 +1,947 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ +#include "commonheaders.h" + +#define FIRSTCUSTOMMENUITEMID 30000 +#define MENU_CUSTOMITEMMAIN 0x80000000 +#define MENU_CUSTOMITEMCONTEXT 0x40000000 +#define SEPARATORPOSITIONINTERVAL 100000 + +struct CListMenuItem +{ + WORD id; + int iconId; + CLISTMENUITEM mi; +}; + +static int nextMenuId; +static struct CListMenuItem *mainMenuItem, *contextMenuItem; +static int mainItemCount, contextItemCount; +static HIMAGELIST hImlMenuIcons; +static HANDLE hPreBuildContactMenuEvent, hAckHook; +static HMENU hMainMenu, hStatusMenu, hRootMenu; +int currentStatusMenuItem, currentDesiredStatusMode; +static int statusModeList[] = +{ + ID_STATUS_OFFLINE, ID_STATUS_ONLINE, ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND, ID_STATUS_FREECHAT, ID_STATUS_INVISIBLE, + ID_STATUS_ONTHEPHONE, ID_STATUS_OUTTOLUNCH +}; + +static int skinIconStatusList[] = +{ + SKINICON_STATUS_OFFLINE, SKINICON_STATUS_ONLINE, SKINICON_STATUS_AWAY, SKINICON_STATUS_NA, SKINICON_STATUS_OCCUPIED, SKINICON_STATUS_DND, + SKINICON_STATUS_FREE4CHAT, SKINICON_STATUS_INVISIBLE, SKINICON_STATUS_ONTHEPHONE, SKINICON_STATUS_OUTTOLUNCH +}; + +static int statusModePf2List[] = +{ 0xFFFFFFFF, PF2_ONLINE, PF2_SHORTAWAY, PF2_LONGAWAY, PF2_LIGHTDND, PF2_HEAVYDND, PF2_FREECHAT, PF2_INVISIBLE, PF2_ONTHEPHONE, PF2_OUTTOLUNCH }; + +extern HANDLE hStatusModeChangeEvent; + +static TCHAR* LangPackPcharToTchar( const char* pszStr ) +{ + if ( pszStr == NULL ) + return NULL; + + #if defined( _UNICODE ) + { int len = strlen( pszStr ); + TCHAR* result = ( TCHAR* )alloca(( len+1 )*sizeof( TCHAR )); + MultiByteToWideChar( CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 ), 0, pszStr, -1, result, len ); + result[len] = 0; + return wcsdup( TranslateW( result )); + } + #else + return _strdup( Translate( pszStr )); + #endif +} + +static void InsertMenuItemWithSeparators(HMENU hMenu, int uItem, BOOL fByPosition, MENUITEMINFO* lpmii) +{ + int thisItemPosition, needSeparator; + MENUITEMINFO mii; + + if (lpmii->fMask & MIIM_SUBMENU) + thisItemPosition = (int) lpmii->dwItemData; + else + thisItemPosition = mainMenuItem[lpmii->dwItemData & ~MENU_CUSTOMITEMMAIN].mi.position; + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = MENUITEMINFO_V4_SIZE; + //check for separator before + if (uItem) { + mii.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_TYPE; + GetMenuItemInfo(hMenu, uItem - 1, TRUE, &mii); + if (mii.fType == MFT_SEPARATOR) + needSeparator = 0; + else if (mii.hSubMenu == NULL && (mii.dwItemData & MENU_CUSTOMITEMMAIN) == 0) + needSeparator = 0; + else if (mii.hSubMenu == NULL) + needSeparator = + ((mainMenuItem[mii.dwItemData & ~MENU_CUSTOMITEMMAIN].mi.position) / SEPARATORPOSITIONINTERVAL) != + thisItemPosition / SEPARATORPOSITIONINTERVAL; + else + needSeparator = ((int) mii.dwItemData) / SEPARATORPOSITIONINTERVAL != thisItemPosition / SEPARATORPOSITIONINTERVAL; + if (needSeparator) { + //but might be supposed to be after the next one instead + mii.fType = 0; + if (uItem < GetMenuItemCount(hMenu)) { + mii.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_TYPE; + GetMenuItemInfo(hMenu, uItem, TRUE, &mii); + } + if (mii.fType != MFT_SEPARATOR) { + mii.fMask = MIIM_TYPE; + mii.fType = MFT_SEPARATOR; + InsertMenuItem(hMenu, uItem, TRUE, &mii); + } + uItem++; + } + } + //check for separator after + if (uItem < GetMenuItemCount(hMenu)) { + mii.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_TYPE; + mii.cch = 0; + GetMenuItemInfo(hMenu, uItem, TRUE, &mii); + if (mii.fType == MFT_SEPARATOR) + needSeparator = 0; + else if (mii.hSubMenu == NULL && (mii.dwItemData & MENU_CUSTOMITEMMAIN) == 0) + needSeparator = 0; + else if (mii.hSubMenu == NULL) + needSeparator = + ((mainMenuItem[mii.dwItemData & ~MENU_CUSTOMITEMMAIN].mi.position) / SEPARATORPOSITIONINTERVAL) != + thisItemPosition / SEPARATORPOSITIONINTERVAL; + else + needSeparator = ((int) mii.dwItemData) / SEPARATORPOSITIONINTERVAL != thisItemPosition / SEPARATORPOSITIONINTERVAL; + if (needSeparator) { + mii.fMask = MIIM_TYPE; + mii.fType = MFT_SEPARATOR; + InsertMenuItem(hMenu, uItem, TRUE, &mii); + } + } + if (uItem == GetMenuItemCount(hMenu) - 1) { + TCHAR str[32]; + mii.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_TYPE; + mii.dwTypeData = str; + mii.cch = SIZEOF(str); + GetMenuItemInfo(hMenu, uItem, TRUE, &mii); + if (mii.fType == MFT_STRING && !_tcscmp(mii.dwTypeData, TranslateT("E&xit"))) { + //make sure we keep the separator before the exit menu item + mii.fMask = MIIM_TYPE; + mii.fType = MFT_SEPARATOR; + InsertMenuItem(hMenu, uItem, TRUE, &mii); + } + } + InsertMenuItem(hMenu, uItem, TRUE, lpmii); +} + +//#define PUTPOSITIONSONMENU +static int AddMainMenuItem(WPARAM wParam, LPARAM lParam) +{ + CLISTMENUITEM *mi = (CLISTMENUITEM *) lParam; + MENUITEMINFO mii; + TCHAR* ptszName; + int i; + HMENU hMenu; + + if (mi==NULL || mi->cbSize != sizeof(CLISTMENUITEM)) + return 0; + mainMenuItem = (struct CListMenuItem *) realloc(mainMenuItem, sizeof(struct CListMenuItem) * (mainItemCount + 1)); + mainMenuItem[mainItemCount].id = nextMenuId++; + mainMenuItem[mainItemCount].mi = *mi; + mainMenuItem[mainItemCount].mi.pszService = strdup(mi->pszService); + mainMenuItem[mainItemCount].mi.pszContactOwner = NULL; + mainMenuItem[mainItemCount].mi.pszName = NULL; + if (mi->hIcon == NULL) + mainMenuItem[mainItemCount].iconId = -1; + else + mainMenuItem[mainItemCount].iconId = ImageList_AddIcon(hImlMenuIcons, mi->hIcon); + hMenu = hMainMenu; + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = MENUITEMINFO_V4_SIZE; + mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA; + if (mi->pszPopupName != NULL) { + TCHAR str[80]; + TCHAR* ptszPopupName = LangPackPcharToTchar( mi->pszPopupName ); + for (i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) { + mii.cch = SIZEOF(str); + mii.dwTypeData = str; + GetMenuItemInfo(hMenu, i, TRUE, &mii); +#ifdef PUTPOSITIONSONMENU + if (mii.hSubMenu != NULL && !_tcsnicmp(str, ptszPopupName, _tcslen(ptszPopupName))) + break; +#else + if (mii.hSubMenu != NULL && !_tcsicmp(str, ptszPopupName)) + break; +#endif + } + if (i < 0) { + mii.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_TYPE; + for (i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) { + mii.cch = SIZEOF(str); + mii.dwTypeData = str; + GetMenuItemInfo(hMenu, i, TRUE, &mii); + if (mii.fType == MFT_SEPARATOR) + continue; + if (mii.hSubMenu == NULL && (mii.dwItemData & MENU_CUSTOMITEMMAIN) == 0) + continue; + if (mii.hSubMenu == NULL) { + if (mainMenuItem[mii.dwItemData & ~MENU_CUSTOMITEMMAIN].mi.position <= mainMenuItem[mainItemCount].mi.popupPosition) + break; + } + else { + if ((int) mii.dwItemData <= mainMenuItem[mainItemCount].mi.popupPosition) + break; + } } + + i++; + mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU; + mii.fType = MFT_STRING; + mii.dwItemData = (DWORD) mi->popupPosition; + mii.hSubMenu = CreatePopupMenu(); +#ifdef PUTPOSITIONSONMENU + { + TCHAR str[256]; + mir_sntprintf(str, SIZEOF(str), "%s (%d)", ptszPopupName, mi->popupPosition); + mii.dwTypeData = str; + InsertMenuItemWithSeparators(hMenu, i, TRUE, &mii); + } +#else + mii.dwTypeData = ptszPopupName; + InsertMenuItemWithSeparators(hMenu, i, TRUE, &mii); +#endif + } + free(ptszPopupName); + hMenu = mii.hSubMenu; + } + mii.fMask = MIIM_SUBMENU | MIIM_DATA; + for (i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) { + GetMenuItemInfo(hMenu, i, TRUE, &mii); + if (mii.fType == MFT_SEPARATOR) + continue; + if (mii.hSubMenu == NULL && (mii.dwItemData & MENU_CUSTOMITEMMAIN) == 0) + continue; + if (mii.hSubMenu == NULL) { + if (mainMenuItem[mii.dwItemData & ~MENU_CUSTOMITEMMAIN].mi.position <= mainMenuItem[mainItemCount].mi.position) + break; + } + else { + if ((int) mii.dwItemData <= mainMenuItem[mainItemCount].mi.position) + break; + } + } + i++; + if (!IsWinVer98Plus()) { + mii.cbSize = MENUITEMINFO_V4_SIZE; + mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID; + } + else { + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA | MIIM_ID | MIIM_STRING; + if (mainMenuItem[mainItemCount].iconId != -1) + mii.fMask |= MIIM_BITMAP; + } + ptszName = LangPackPcharToTchar( mi->pszName ); + + mii.fType = MFT_STRING; + mii.wID = mainMenuItem[mainItemCount].id; + mii.dwItemData = mainItemCount | MENU_CUSTOMITEMMAIN; + mii.hbmpItem = HBMMENU_CALLBACK; +#ifdef PUTPOSITIONSONMENU + { + TCHAR str[256]; + mir_sntprintf(str, SIZEOF(str), "%s (%d)", ptszName, mi->position); + mii.dwTypeData = str; + InsertMenuItemWithSeparators(hMenu, i, TRUE, &mii); + } +#else + mii.dwTypeData = ptszName; + InsertMenuItemWithSeparators(hMenu, i, TRUE, &mii); +#endif + free( ptszName ); + mainItemCount++; + return MENU_CUSTOMITEMMAIN | (mainItemCount - 1); +} + +static int AddContactMenuItem(WPARAM wParam, LPARAM lParam) +{ + CLISTMENUITEM *mi = (CLISTMENUITEM *) lParam; + + if (mi==NULL || mi->cbSize != sizeof(CLISTMENUITEM)) + return 0; + contextMenuItem = (struct CListMenuItem *) realloc(contextMenuItem, sizeof(struct CListMenuItem) * (contextItemCount + 1)); + contextMenuItem[contextItemCount].id = nextMenuId++; + contextMenuItem[contextItemCount].mi = *mi; + contextMenuItem[contextItemCount].mi.pszService = strdup(mi->pszService); + contextMenuItem[contextItemCount].mi.ptszName = LangPackPcharToTchar(mi->pszName); + if (mi->pszContactOwner != NULL) + contextMenuItem[contextItemCount].mi.pszContactOwner = strdup(mi->pszContactOwner); + if (mi->hIcon == NULL) + contextMenuItem[contextItemCount].iconId = -1; + else + contextMenuItem[contextItemCount].iconId = ImageList_AddIcon(hImlMenuIcons, mi->hIcon); + contextItemCount++; + return MENU_CUSTOMITEMCONTEXT | (contextItemCount - 1); +} + +static int ModifyCustomMenuItem(WPARAM wParam, LPARAM lParam) +{ + struct CListMenuItem *clmi; + CLISTMENUITEM *mi = (CLISTMENUITEM *) lParam; + MENUITEMINFO mii; + + if (mi==NULL || mi->cbSize != sizeof(CLISTMENUITEM)) + return 1; + if (wParam & MENU_CUSTOMITEMMAIN) { + if ((int) (wParam & ~MENU_CUSTOMITEMMAIN) >= mainItemCount) + return 1; + clmi = mainMenuItem + (wParam & ~MENU_CUSTOMITEMMAIN); + } + else if (wParam & MENU_CUSTOMITEMCONTEXT) { + if ((int) (wParam & ~MENU_CUSTOMITEMCONTEXT) >= contextItemCount) + return 1; + clmi = contextMenuItem + (wParam & ~MENU_CUSTOMITEMCONTEXT); + } + else + return 1; + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = MENUITEMINFO_V4_SIZE; + if (mi->flags & CMIM_NAME) { + if (clmi->mi.pszName != NULL) + free(clmi->mi.pszName); + clmi->mi.ptszName = LangPackPcharToTchar(mi->pszName); + if (wParam & MENU_CUSTOMITEMMAIN) { + mii.fMask = IsWinVer98Plus()? MIIM_STRING : MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = clmi->mi.ptszName; + SetMenuItemInfo(hMainMenu, clmi->id, FALSE, &mii); + } + } + if (mi->flags & CMIM_FLAGS) { + clmi->mi.flags = mi->flags & ~CMIM_ALL; + if (wParam & MENU_CUSTOMITEMMAIN) { + mii.fMask = MIIM_STATE; + mii.fState = ((clmi->mi.flags & CMIF_GRAYED) ? MFS_GRAYED : 0) | ((clmi->mi.flags & CMIF_CHECKED) ? MFS_CHECKED : 0); + SetMenuItemInfo(hMainMenu, clmi->id, FALSE, &mii); + } + } + if (mi->flags & CMIM_ICON) { + clmi->mi.hIcon = mi->hIcon; + if (mi->hIcon != NULL) + clmi->iconId = ImageList_ReplaceIcon(hImlMenuIcons, clmi->iconId, mi->hIcon); + else + clmi->iconId = -1; //fixme, should remove old icon & shuffle all iconIds + } + if (mi->flags & CMIM_HOTKEY) { + clmi->mi.hotKey = mi->hotKey; + } + return 0; +} + +int MenuProcessCommand(WPARAM wParam, LPARAM lParam) +{ + int i; + PROTOCOLDESCRIPTOR **proto; + int protoCount; + + if (HIWORD(wParam) & MPCF_MAINMENU) { + int newStatus, protoIndex; + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM) & protoCount, (LPARAM) & proto); + if (LOWORD(wParam) >= ID_STATUS_OFFLINE + SIZEOF(statusModeList) + && LOWORD(wParam) < ID_STATUS_OFFLINE + (protoCount + 1) * SIZEOF(statusModeList)) { + // one of the protocol-specific status menus + protoIndex = (LOWORD(wParam) - ID_STATUS_OFFLINE) / SIZEOF(statusModeList) - 1; + newStatus = (LOWORD(wParam) - ID_STATUS_OFFLINE) % SIZEOF(statusModeList) + ID_STATUS_OFFLINE; + // let the world know, this need's the translated ID_STATUS_* NOT LOWORD(wParam) + // which is offseted by some degree depending on protocol used + CallProtoService(proto[protoIndex]->szName, PS_SETSTATUS, newStatus, 0); + NotifyEventHooks(hStatusModeChangeEvent, newStatus, (LPARAM) proto[protoIndex]->szName); + } + switch (LOWORD(wParam)) { + case ID_STATUS_OFFLINE: + case ID_STATUS_ONLINE: + case ID_STATUS_AWAY: + case ID_STATUS_DND: + case ID_STATUS_NA: + case ID_STATUS_OCCUPIED: + case ID_STATUS_FREECHAT: + case ID_STATUS_INVISIBLE: + case ID_STATUS_OUTTOLUNCH: + case ID_STATUS_ONTHEPHONE: + currentDesiredStatusMode = LOWORD(wParam); + for (i = 0; i < protoCount; i++) + CallProtoService(proto[i]->szName, PS_SETSTATUS, LOWORD(wParam), 0); + DBWriteContactSettingWord(NULL, "CList", "Status", (WORD) currentDesiredStatusMode); + NotifyEventHooks(hStatusModeChangeEvent, LOWORD(wParam), 0); + return 1; + } + for (i = 0; i < mainItemCount; i++) { + if (LOWORD(wParam) == mainMenuItem[i].id) { + CallService(mainMenuItem[i].mi.pszService, 0, (LPARAM) NULL); + return 1; + } + } + } + if (HIWORD(wParam) & MPCF_CONTACTMENU) { + for (i = 0; i < contextItemCount; i++) { + if (LOWORD(wParam) == contextMenuItem[i].id) { + if ((HANDLE) lParam != NULL) + CallService(contextMenuItem[i].mi.pszService, lParam, (LPARAM) (HWND) NULL); + return 1; + } + } + } + return 0; +} + +static int MenuProcessHotkey(WPARAM vKey, LPARAM lParam) +{ + int i; + + if (lParam & MPCF_MAINMENU) { + if (vKey >= '0' && vKey <= '9' && GetKeyState(VK_CONTROL) & 0x8000 && !(GetKeyState(VK_MENU) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000)) { + MenuProcessCommand(MAKEWPARAM(statusModeList[vKey - '0'], MPCF_MAINMENU), 0); + return 1; + } + for (i = 0; i < mainItemCount; i++) { + if (mainMenuItem[i].mi.hotKey == 0) + continue; + if (HIWORD(mainMenuItem[i].mi.hotKey) != vKey) + continue; + if (!(LOWORD(mainMenuItem[i].mi.hotKey) & MOD_ALT) != !(GetKeyState(VK_MENU) & 0x8000)) + continue; + if (!(LOWORD(mainMenuItem[i].mi.hotKey) & MOD_CONTROL) != !(GetKeyState(VK_CONTROL) & 0x8000)) + continue; + if (!(LOWORD(mainMenuItem[i].mi.hotKey) & MOD_SHIFT) != !(GetKeyState(VK_SHIFT) & 0x8000)) + continue; + CallService(mainMenuItem[i].mi.pszService, 0, (LPARAM) NULL); + return 1; + } + } + return 0; +} + +//straight subtraction is not possible because I was getting overflows +static int MenuSortProc(int *item1, int *item2) +{ + if (contextMenuItem[*item2].mi.position > contextMenuItem[*item1].mi.position) + return 1; + if (contextMenuItem[*item2].mi.position < contextMenuItem[*item1].mi.position) + return -1; + return 0; +} + +static int BuildContactMenu(WPARAM wParam, LPARAM lParam) +{ + HMENU hMenu; + MENUITEMINFO mii; + int i; + int *itemOrder, itemCount; + int isOnline, isOnList; + HANDLE hContact = (HANDLE) wParam; + int prevPosition; + int chatRoom; + DWORD miim_bitmap_verSpecific; + char *szProto; + + NotifyEventHooks(hPreBuildContactMenuEvent, (WPARAM) hContact, 0); + + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + isOnList = 0 == DBGetContactSettingByte(hContact, "CList", "NotOnList", 0); + isOnline = szProto != NULL && ID_STATUS_OFFLINE != DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE); + chatRoom = szProto?DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0):0; + if ( contextItemCount ) { + itemOrder = (int *) malloc(sizeof(int) * contextItemCount); + ZeroMemory(itemOrder, sizeof(int) * contextItemCount); + } else { + itemOrder = (int *) malloc(sizeof(int) * 1); + ZeroMemory(itemOrder, sizeof(int) * 1); + } + itemCount = 0; + for (i = 0; i < contextItemCount; i++) { + if (contextMenuItem[i].id == 0) + continue; + if (szProto == NULL) + continue; + // Begin Ugly hack to hide chat room menus + if (chatRoom) { + if (!strcmp(contextMenuItem[i].mi.pszName,Translate("&Message"))) + continue; + if (!strcmp(contextMenuItem[i].mi.pszName,Translate("&File"))) + continue; + if (!strcmp(contextMenuItem[i].mi.pszName,Translate("User &Details"))) + continue; + if (!strcmp(contextMenuItem[i].mi.pszName,Translate("View &History"))) + continue; + } + // End ugly hack + if (contextMenuItem[i].mi.pszContactOwner != NULL) { + if (strcmp(contextMenuItem[i].mi.pszContactOwner, szProto)) + continue; + } + if (contextMenuItem[i].mi.flags & CMIF_HIDDEN) + continue; + if (contextMenuItem[i].mi.flags & CMIF_NOTONLIST && isOnList) + continue; + if (contextMenuItem[i].mi.flags & CMIF_NOTOFFLIST && !isOnList) + continue; + if (contextMenuItem[i].mi.flags & CMIF_NOTONLINE && isOnline) + continue; + if (contextMenuItem[i].mi.flags & CMIF_NOTOFFLINE && !isOnline) + continue; + itemOrder[itemCount] = i; + itemCount++; + } + //sorts in reverse order since it's easiest to add items bottom to top + qsort(itemOrder, itemCount, sizeof(int), (int (*)(const void *, const void *)) MenuSortProc); + hMenu = CreatePopupMenu(); + ZeroMemory(&mii, sizeof(mii)); + if (!IsWinVer98Plus()) { + mii.cbSize = MENUITEMINFO_V4_SIZE; + mii.fMask = MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_TYPE; + miim_bitmap_verSpecific = 0; + } + else { + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_STRING; + miim_bitmap_verSpecific = MIIM_BITMAP; + } + mii.fType = MFT_STRING; + mii.hbmpItem = HBMMENU_CALLBACK; + prevPosition = contextMenuItem[itemOrder[0]].mi.position; + for (i = 0; i < itemCount; i++) { + if (prevPosition / SEPARATORPOSITIONINTERVAL != contextMenuItem[itemOrder[i]].mi.position / SEPARATORPOSITIONINTERVAL) { + UINT oldMask = mii.fMask; + mii.fMask = MIIM_TYPE; + mii.fType = MFT_SEPARATOR; + InsertMenuItem(hMenu, 0, TRUE, &mii); + mii.fMask = oldMask; + mii.fType = MFT_STRING; + } + prevPosition = contextMenuItem[itemOrder[i]].mi.position; + if (contextMenuItem[itemOrder[i]].iconId == -1) + mii.fMask &= ~miim_bitmap_verSpecific; + else + mii.fMask |= miim_bitmap_verSpecific; + mii.dwItemData = itemOrder[i] | MENU_CUSTOMITEMCONTEXT; + mii.fState = + ((contextMenuItem[itemOrder[i]].mi.flags & CMIF_GRAYED) ? MFS_GRAYED : MFS_ENABLED) | ((contextMenuItem[itemOrder[i]].mi. + flags & CMIF_CHECKED) ? MFS_CHECKED : + MFS_UNCHECKED); + mii.wID = contextMenuItem[itemOrder[i]].id; + mii.dwTypeData = contextMenuItem[itemOrder[i]].mi.ptszName; +#ifdef _DEBUG + if (GetKeyState(VK_CONTROL) & 0x8000) { + TCHAR str[256]; + wsprintf(str, _T("%s (%d)"), contextMenuItem[itemOrder[i]].mi.pszName, contextMenuItem[itemOrder[i]].mi.position); + mii.dwTypeData = str; + InsertMenuItem(hMenu, 0, TRUE, &mii); + } + else InsertMenuItem(hMenu, 0, TRUE, &mii); +#else + InsertMenuItem(hMenu, 0, TRUE, &mii); +#endif + } + free(itemOrder); + return (int) hMenu; +} + +static int MenuIconsChanged(WPARAM wParam, LPARAM lParam) +{ + int i, protoCount, networkProtoCount, j; + PROTOCOLDESCRIPTOR **proto; + DWORD flags; + MENUITEMINFO mii; + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA; + + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM) & protoCount, (LPARAM) & proto); + networkProtoCount = 0; + for (i = 0; i < protoCount; i++) + if (proto[i]->type == PROTOTYPE_PROTOCOL) + networkProtoCount++; + if (networkProtoCount > 1) { + for (i = 0; i < protoCount; i++) { + if (proto[i]->type != PROTOTYPE_PROTOCOL) + continue; + flags = CallProtoService(proto[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0); + for (j = 0; j < SIZEOF(statusModeList); j++) { + if (!(flags & statusModePf2List[j])) + continue; + if (!GetMenuItemInfo(hStatusMenu, (i + 1) * SIZEOF(statusModeList) + statusModeList[j], FALSE, &mii)) + continue; + if ((mii.dwItemData & MENU_CUSTOMITEMMAIN) != MENU_CUSTOMITEMMAIN) + continue; + ImageList_ReplaceIcon(hImlMenuIcons, mainMenuItem[mii.dwItemData & ~MENU_CUSTOMITEMMAIN].iconId, + LoadSkinnedProtoIcon(proto[i]->szName, statusModeList[j])); + } } } + + for (i = 0; i < SIZEOF(statusModeList); i++) { + if (!GetMenuItemInfo(hStatusMenu, statusModeList[i], FALSE, &mii)) + continue; + if ((mii.dwItemData & MENU_CUSTOMITEMMAIN) != MENU_CUSTOMITEMMAIN) + continue; + ImageList_ReplaceIcon(hImlMenuIcons, mainMenuItem[mii.dwItemData & ~MENU_CUSTOMITEMMAIN].iconId, + LoadSkinnedProtoIcon(NULL, statusModeList[i])); + } + return 0; +} + +static void GiveExistingItemAnIcon(UINT id, HICON hIcon) +{ + MENUITEMINFO mii; + + mainMenuItem = (struct CListMenuItem *) realloc(mainMenuItem, sizeof(struct CListMenuItem) * (mainItemCount + 1)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_BITMAP | MIIM_DATA; + mii.dwItemData = MENU_CUSTOMITEMMAIN | mainItemCount; + mii.hbmpItem = HBMMENU_CALLBACK; + mainMenuItem[mainItemCount].iconId = ImageList_AddIcon(hImlMenuIcons, hIcon); + mainMenuItem[mainItemCount].id = 0xFFFF; + mainMenuItem[mainItemCount].mi.hotKey = 0; + mainMenuItem[mainItemCount].mi.pszName = NULL; + mainMenuItem[mainItemCount].mi.pszService = NULL; + SetMenuItemInfo(hStatusMenu, id, FALSE, &mii); + mainItemCount++; +} + +static int MeasureMenuItem(WPARAM wParam, LPARAM lParam) +{ + struct CListMenuItem *clmi = NULL; + LPMEASUREITEMSTRUCT mis = (LPMEASUREITEMSTRUCT) lParam; + if (mis->itemData & MENU_CUSTOMITEMCONTEXT) + clmi = &contextMenuItem[mis->itemData & ~MENU_CUSTOMITEMCONTEXT]; + else if (mis->itemData & MENU_CUSTOMITEMMAIN) + clmi = &mainMenuItem[mis->itemData & ~MENU_CUSTOMITEMMAIN]; + if (clmi == NULL) + return FALSE; + if (clmi->iconId == -1) + return FALSE; + + mis->itemWidth = max(0, GetSystemMetrics(SM_CXSMICON) - GetSystemMetrics(SM_CXMENUCHECK) + 4); + mis->itemHeight = GetSystemMetrics(SM_CYSMICON) + 2; + return TRUE; +} + +static int DrawMenuItem(WPARAM wParam, LPARAM lParam) +{ + struct CListMenuItem *clmi = NULL; + int y; + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; + + if (dis->itemData & MENU_CUSTOMITEMCONTEXT) + clmi = &contextMenuItem[dis->itemData & ~MENU_CUSTOMITEMCONTEXT]; + else if (dis->itemData & MENU_CUSTOMITEMMAIN) + clmi = &mainMenuItem[dis->itemData & ~MENU_CUSTOMITEMMAIN]; + if (clmi == NULL) + return FALSE; + if (clmi->iconId == -1) + return FALSE; + + y = (dis->rcItem.bottom - dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2 + 1; + if (dis->itemState & ODS_SELECTED) { + if (dis->itemState & ODS_CHECKED) { + RECT rc; + rc.left = 2; + rc.right = GetSystemMetrics(SM_CXSMICON) + 2; + rc.top = y; + rc.bottom = rc.top + GetSystemMetrics(SM_CYSMICON) + 2; + FillRect(dis->hDC, &rc, GetSysColorBrush(COLOR_HIGHLIGHT)); + ImageList_DrawEx(hImlMenuIcons, clmi->iconId, dis->hDC, 2, y, 0, 0, CLR_NONE, CLR_DEFAULT, ILD_SELECTED); + } + else + ImageList_DrawEx(hImlMenuIcons, clmi->iconId, dis->hDC, 2, y, 0, 0, CLR_NONE, CLR_DEFAULT, ILD_FOCUS); + } + else { + if (dis->itemState & ODS_CHECKED) { + HBRUSH hBrush; + RECT rc; + COLORREF menuCol, hiliteCol; + rc.left = 0; + rc.right = GetSystemMetrics(SM_CXSMICON) + 4; + rc.top = y - 2; + rc.bottom = rc.top + GetSystemMetrics(SM_CYSMICON) + 4; + DrawEdge(dis->hDC, &rc, BDR_SUNKENOUTER, BF_RECT); + InflateRect(&rc, -1, -1); + menuCol = GetSysColor(COLOR_MENU); + hiliteCol = GetSysColor(COLOR_3DHIGHLIGHT); + hBrush = + CreateSolidBrush(RGB + ((GetRValue(menuCol) + GetRValue(hiliteCol)) / 2, (GetGValue(menuCol) + GetGValue(hiliteCol)) / 2, + (GetBValue(menuCol) + GetBValue(hiliteCol)) / 2)); + FillRect(dis->hDC, &rc, hBrush); + DeleteObject(hBrush); + ImageList_DrawEx(hImlMenuIcons, clmi->iconId, dis->hDC, 2, y, 0, 0, CLR_NONE, GetSysColor(COLOR_MENU), ILD_BLEND25); + } + else ImageList_DrawEx(hImlMenuIcons, clmi->iconId, dis->hDC, 2, y, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + } + return TRUE; +} + +static int MenuGetMain(WPARAM wParam, LPARAM lParam) +{ + return (int) hMainMenu; +} + +static int MenuGetStatus(WPARAM wParam, LPARAM lParam) +{ + return (int) hStatusMenu; +} + +static int MenuModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + int i, protoCount, networkProtoCount; + char *szProto = NULL; + char *szLastProto = NULL; + PROTOCOLDESCRIPTOR **proto; + DWORD statusFlags = 0, flags, moreflags = 0; + + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM) & protoCount, (LPARAM) & proto); + networkProtoCount = 0; + for (i = 0; i < protoCount; i++) /* look for valid protocols */ + if (proto[i]->type == PROTOTYPE_PROTOCOL && CallProtoService(proto[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0) != 0) { + networkProtoCount++; + szLastProto = proto[i]->szName; /* remember the protocol name, since it maybe the last */ + } //if + + if (IsWinVer98Plus()) { + /* if a single network protocol is used, load the iconset for the global menu by name */ + if (networkProtoCount == 1) + szProto = szLastProto; + for (i = 0; i < SIZEOF(statusModeList); i++) { + GiveExistingItemAnIcon(statusModeList[i], LoadSkinnedProtoIcon(szProto, statusModeList[i])); + } + HookEvent(ME_SKIN_ICONSCHANGED, MenuIconsChanged); + } + + if (networkProtoCount > 1) { + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = MENUITEMINFO_V4_SIZE; + mii.fMask = MIIM_TYPE; + mii.fType = MFT_SEPARATOR; + mii.dwTypeData = _T(""); + InsertMenuItem(hStatusMenu, 0, TRUE, &mii); + } + for (i = 0; i < protoCount; i++) { + if (proto[i]->type != PROTOTYPE_PROTOCOL || CallProtoService(proto[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0) == 0) + continue; + flags = CallProtoService(proto[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0); + moreflags = CallProtoService(proto[i]->szName, PS_GETCAPS, PFLAGNUM_5, 0); + if (networkProtoCount > 1) { + MENUITEMINFO mii; + char protoName[128]; + int j; + HMENU hMenu = GetSubMenu(LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CLISTMENU)), 1); + ZeroMemory(&mii, sizeof(mii)); + for (j = 0; j < SIZEOF(statusModeList); j++) { + if (!(flags & statusModePf2List[j])) + DeleteMenu(hMenu, statusModeList[j], MF_BYCOMMAND); + else if (moreflags & statusModePf2List[j] && j > 0) + DeleteMenu(hMenu, statusModeList[j], MF_BYCOMMAND); + else { + TCHAR text[128], *ptab; + mii.cbSize = MENUITEMINFO_V4_SIZE; + mii.fMask = MIIM_TYPE; + mii.cch = SIZEOF(text); + mii.dwTypeData = text; + GetMenuItemInfo(hMenu, statusModeList[j], FALSE, &mii); + _tcscpy(text, TranslateTS(text)); + ptab = _tcschr(text, '\t'); + if (ptab != NULL) + *ptab = '\0'; + if (IsWinVer98Plus()) { + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_BITMAP | MIIM_DATA | MIIM_STRING; + mainMenuItem = (struct CListMenuItem *)realloc(mainMenuItem, sizeof(struct CListMenuItem) * (mainItemCount + 1)); + mainMenuItem[mainItemCount].iconId = + ImageList_AddIcon(hImlMenuIcons, LoadSkinnedProtoIcon(proto[i]->szName, statusModeList[j])); + mainMenuItem[mainItemCount].id = 0xFFFF; + mainMenuItem[mainItemCount].mi.hotKey = 0; + mainMenuItem[mainItemCount].mi.pszName = NULL; + mainMenuItem[mainItemCount].mi.pszService = NULL; + mii.dwItemData = MENU_CUSTOMITEMMAIN | mainItemCount; + mii.hbmpItem = HBMMENU_CALLBACK; + mainItemCount++; + } + else + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.wID = statusModeList[j] + (i + 1) * SIZEOF(statusModeList); + SetMenuItemInfo(hMenu, statusModeList[j], FALSE, &mii); + } + } + if (IsWinVer98Plus()) { + HICON hIcon; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU | MIIM_BITMAP | MIIM_DATA | MIIM_STRING; + mainMenuItem = (struct CListMenuItem *) realloc(mainMenuItem, sizeof(struct CListMenuItem) * (mainItemCount + 1)); + hIcon = (HICON) CallProtoService(proto[i]->szName, PS_LOADICON, PLI_PROTOCOL | PLIF_SMALL, 0); + mainMenuItem[mainItemCount].iconId = ImageList_AddIcon(hImlMenuIcons, hIcon); + DestroyIcon(hIcon); + mainMenuItem[mainItemCount].id = 0xFFFF; + mainMenuItem[mainItemCount].mi.hotKey = 0; + mainMenuItem[mainItemCount].mi.pszName = NULL; + mainMenuItem[mainItemCount].mi.pszService = NULL; + mii.dwItemData = MENU_CUSTOMITEMMAIN | mainItemCount; + mii.hbmpItem = HBMMENU_CALLBACK; + mainItemCount++; + } + else { + mii.cbSize = MENUITEMINFO_V4_SIZE; + mii.fMask = MIIM_SUBMENU | MIIM_TYPE; + } + mii.fType = MFT_STRING; + mii.hSubMenu = hMenu; + CallProtoService(proto[i]->szName, PS_GETNAME, SIZEOF(protoName), (LPARAM) protoName); + { TCHAR* ptszProtoName = LangPackPcharToTchar(protoName); + mii.dwTypeData = ptszProtoName; + InsertMenuItem(hStatusMenu, 0, TRUE, &mii); + free(ptszProtoName); + } } + statusFlags |= ( flags & ~moreflags ); + } + for (i = 0; i < SIZEOF(statusModeList); i++) + if (!(statusFlags & statusModePf2List[i])) + DeleteMenu(hStatusMenu, statusModeList[i], MF_BYCOMMAND); + return 0; +} + +static int MenuProtoAck(WPARAM wParam, LPARAM lParam) +{ + int protoCount, i, networkProtoCount; + PROTOCOLDESCRIPTOR **proto; + ACKDATA *ack = (ACKDATA *) lParam; + int overallStatus = 0, thisStatus; + + if (ack->type != ACKTYPE_STATUS) + return 0; + if (ack->result != ACKRESULT_SUCCESS) + return 0; + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM) & protoCount, (LPARAM) & proto); + networkProtoCount = 0; + for (i = 0; i < protoCount; i++) + if (proto[i]->type == PROTOTYPE_PROTOCOL) { + thisStatus = CallProtoService(proto[i]->szName, PS_GETSTATUS, 0, 0); + if (overallStatus == 0) + overallStatus = thisStatus; + else if (overallStatus != thisStatus) + overallStatus = -1; + networkProtoCount++; + } + if (overallStatus > ID_STATUS_CONNECTING) { + CheckMenuItem(hStatusMenu, currentStatusMenuItem, MF_BYCOMMAND | MF_UNCHECKED); + currentStatusMenuItem = overallStatus; + CheckMenuItem(hStatusMenu, currentStatusMenuItem, MF_BYCOMMAND | MF_CHECKED); + SetMenuDefaultItem(hStatusMenu, currentStatusMenuItem, FALSE); + currentDesiredStatusMode = currentStatusMenuItem; + } + else { + CheckMenuItem(hStatusMenu, currentStatusMenuItem, MF_BYCOMMAND | MF_UNCHECKED); + SetMenuDefaultItem(hStatusMenu, -1, FALSE); + currentStatusMenuItem = 0; + } + if (networkProtoCount <= 1) + return 0; + for (i = 0; i < protoCount; i++) + if (!strcmp(proto[i]->szName, ack->szModule)) + break; + //hProcess is previous mode, lParam is new mode + if ((int) ack->hProcess >= ID_STATUS_OFFLINE && (int) ack->hProcess < ID_STATUS_OFFLINE + SIZEOF(statusModeList)) + CheckMenuItem(hStatusMenu, (i + 1) * SIZEOF(statusModeList) + (int) ack->hProcess, MF_BYCOMMAND | MF_UNCHECKED); + if (ack->lParam >= ID_STATUS_OFFLINE && ack->lParam < ID_STATUS_OFFLINE + SIZEOF(statusModeList)) + CheckMenuItem(hStatusMenu, (i + 1) * SIZEOF(statusModeList) + ack->lParam, MF_BYCOMMAND | MF_CHECKED); + return 0; +} + +static int MenuModulesShutdown(WPARAM wParam, LPARAM lParam) +{ + UnhookEvent(hAckHook); + return 0; +} + +int InitCustomMenus(void) +{ + CreateServiceFunction(MS_CLIST_ADDMAINMENUITEM, AddMainMenuItem); + CreateServiceFunction(MS_CLIST_ADDCONTACTMENUITEM, AddContactMenuItem); + CreateServiceFunction(MS_CLIST_MODIFYMENUITEM, ModifyCustomMenuItem); + CreateServiceFunction(MS_CLIST_MENUMEASUREITEM, MeasureMenuItem); + CreateServiceFunction(MS_CLIST_MENUDRAWITEM, DrawMenuItem); + CreateServiceFunction(MS_CLIST_MENUBUILDCONTACT, BuildContactMenu); + CreateServiceFunction(MS_CLIST_MENUGETMAIN, MenuGetMain); + CreateServiceFunction(MS_CLIST_MENUGETSTATUS, MenuGetStatus); + CreateServiceFunction(MS_CLIST_MENUPROCESSCOMMAND, MenuProcessCommand); + CreateServiceFunction(MS_CLIST_MENUPROCESSHOTKEY, MenuProcessHotkey); + hPreBuildContactMenuEvent = CreateHookableEvent(ME_CLIST_PREBUILDCONTACTMENU); + hAckHook = (HANDLE) HookEvent(ME_PROTO_ACK, MenuProtoAck); + hRootMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CLISTMENU)); + hMainMenu = GetSubMenu(hRootMenu, 0); + hStatusMenu = GetSubMenu(hRootMenu, 1); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hMainMenu, 0); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hStatusMenu, 0); + nextMenuId = FIRSTCUSTOMMENUITEMID; + mainMenuItem = contextMenuItem = NULL; + mainItemCount = contextItemCount = 0; + if (IsWinVerXPPlus()) //need 32-bit icons on XP for alpha channels + hImlMenuIcons = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 15, 100); + else //Win2k won't blend icons with imagelist_drawex when color-depth>16-bit. Don't know about WinME, but it certainly doesn't support alpha channels + hImlMenuIcons = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR16 | ILC_MASK, 15, 100); + + currentStatusMenuItem = ID_STATUS_OFFLINE; + currentDesiredStatusMode = ID_STATUS_OFFLINE; + { + MENUITEMINFO mii; + mii.cbSize = MENUITEMINFO_V4_SIZE; + mii.fMask = MIIM_STATE; + mii.fState = MFS_CHECKED | MFS_DEFAULT; + SetMenuItemInfo(hStatusMenu, currentStatusMenuItem, FALSE, &mii); + } + + HookEvent(ME_SYSTEM_MODULESLOADED, MenuModulesLoaded); + HookEvent(ME_SYSTEM_SHUTDOWN, MenuModulesShutdown); + return 0; +} + +void UninitCustomMenus(void) +{ + int i; + + ImageList_Destroy(hImlMenuIcons); + for (i = 0; i < mainItemCount; i++) { + if (mainMenuItem[i].mi.pszName != NULL) + free(mainMenuItem[i].mi.pszName); + if (mainMenuItem[i].mi.pszService != NULL) + free(mainMenuItem[i].mi.pszService); + } + for (i = 0; i < contextItemCount; i++) { + if (contextMenuItem[i].mi.pszName != NULL) + free(contextMenuItem[i].mi.pszName); + if (contextMenuItem[i].mi.pszService != NULL) + free(contextMenuItem[i].mi.pszService); + if (contextMenuItem[i].mi.pszContactOwner != NULL) + free(contextMenuItem[i].mi.pszContactOwner); + } + free(mainMenuItem); + free(contextMenuItem); + DestroyMenu(hStatusMenu); + DestroyMenu(hMainMenu); + DestroyMenu(hRootMenu); +} diff --git a/miranda-wine/plugins/clist/clistopts.c b/miranda-wine/plugins/clist/clistopts.c new file mode 100644 index 0000000..7db1efa --- /dev/null +++ b/miranda-wine/plugins/clist/clistopts.c @@ -0,0 +1,353 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ +#include "commonheaders.h" + +static BOOL CALLBACK DlgProcGenOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_USER + 1: + { + HANDLE hContact = (HANDLE) wParam; + DBCONTACTWRITESETTING *ws = (DBCONTACTWRITESETTING *) lParam; + if (hContact == NULL && ws != NULL && ws->szModule != NULL && ws->szSetting != NULL + && lstrcmpiA(ws->szModule, "CList") == 0 && lstrcmpiA(ws->szSetting, "UseGroups") == 0 && IsWindowVisible(hwndDlg)) { + CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, ws->value.bVal == 0); + } + break; + } + case WM_DESTROY: + { + UnhookEvent((HANDLE) GetWindowLong(hwndDlg, GWL_USERDATA)); + break; + } + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED, hwndDlg, WM_USER + 1)); + CheckDlgButton(hwndDlg, IDC_ONTOP, DBGetContactSettingByte(NULL, "CList", "OnTop", SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_HIDEOFFLINE, + DBGetContactSettingByte(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_HIDEEMPTYGROUPS, + DBGetContactSettingByte(NULL, "CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, + DBGetContactSettingByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT) ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_SORTBYNAME, !DBGetContactSettingByte(NULL, "CList", "SortByStatus", SETTING_SORTBYSTATUS_DEFAULT) + && !DBGetContactSettingByte(NULL, "CList", "SortByProto", SETTING_SORTBYPROTO_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SORTBYSTATUS, + DBGetContactSettingByte(NULL, "CList", "SortByStatus", SETTING_SORTBYSTATUS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SORTBYPROTO, + DBGetContactSettingByte(NULL, "CList", "SortByProto", SETTING_SORTBYPROTO_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CONFIRMDELETE, + DBGetContactSettingByte(NULL, "CList", "ConfirmDelete", SETTING_CONFIRMDELETE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOHIDE, + DBGetContactSettingByte(NULL, "CList", "AutoHide", SETTING_AUTOHIDE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + { + DWORD caps = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS1, 0); + if (!(caps & CLUIF_HIDEEMPTYGROUPS)) + ShowWindow(GetDlgItem(hwndDlg, IDC_HIDEEMPTYGROUPS), SW_HIDE); + if (!(caps & CLUIF_DISABLEGROUPS)) + ShowWindow(GetDlgItem(hwndDlg, IDC_DISABLEGROUPS), SW_HIDE); + if (caps & CLUIF_HASONTOPOPTION) + ShowWindow(GetDlgItem(hwndDlg, IDC_ONTOP), SW_HIDE); + if (caps & CLUIF_HASAUTOHIDEOPTION) { + ShowWindow(GetDlgItem(hwndDlg, IDC_AUTOHIDE), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_STAUTOHIDESECS), SW_HIDE); + } + } + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETRANGE, 0, MAKELONG(900, 1)); + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingWord(NULL, "CList", "HideTime", SETTING_HIDETIME_DEFAULT), 0)); + CheckDlgButton(hwndDlg, IDC_ONECLK, + DBGetContactSettingByte(NULL, "CList", "Tray1Click", SETTING_TRAY1CLICK_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ALWAYSSTATUS, + DBGetContactSettingByte(NULL, "CList", "AlwaysStatus", SETTING_ALWAYSSTATUS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ALWAYSMULTI, + !DBGetContactSettingByte(NULL, "CList", "AlwaysMulti", SETTING_ALWAYSMULTI_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DONTCYCLE, + DBGetContactSettingByte(NULL, "CList", "TrayIcon", + SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_SINGLE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CYCLE, + DBGetContactSettingByte(NULL, "CList", "TrayIcon", + SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_CYCLE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MULTITRAY, + DBGetContactSettingByte(NULL, "CList", "TrayIcon", + SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DISABLEBLINK, + DBGetContactSettingByte(NULL, "CList", "DisableTrayFlash", 0) == 1 ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKTIME), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKSPIN), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STMSDELAY), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + CheckDlgButton(hwndDlg, IDC_ICONBLINK, DBGetContactSettingByte(NULL, "CList", "NoIconBlink", 0) == 1 ? BST_CHECKED : BST_UNCHECKED); + if (IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIMESPIN), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIME), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ALWAYSMULTI), FALSE); + } + if (IsDlgButtonChecked(hwndDlg, IDC_CYCLE)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_PRIMARYSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ALWAYSMULTI), FALSE); + } + if (IsDlgButtonChecked(hwndDlg, IDC_MULTITRAY)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIMESPIN), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIME), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PRIMARYSTATUS), FALSE); + } + SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_SETRANGE, 0, MAKELONG(120, 1)); + SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingWord(NULL, "CList", "CycleTime", SETTING_CYCLETIME_DEFAULT), 0)); + { + int i, count, item; + PROTOCOLDESCRIPTOR **protos; + char szName[64]; + DBVARIANT dbv = { DBVT_DELETED }; + DBGetContactSetting(NULL, "CList", "PrimaryStatus", &dbv); + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM) & count, (LPARAM) & protos); + item = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_ADDSTRING, 0, (LPARAM) TranslateT("Global")); + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETITEMDATA, item, (LPARAM) 0); + for (i = 0; i < count; i++) { + if (protos[i]->type != PROTOTYPE_PROTOCOL || CallProtoService(protos[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0) == 0) + continue; + CallProtoService(protos[i]->szName, PS_GETNAME, SIZEOF(szName), (LPARAM) szName); + item = SendDlgItemMessageA(hwndDlg, IDC_PRIMARYSTATUS, CB_ADDSTRING, 0, (LPARAM) szName); + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETITEMDATA, item, (LPARAM) protos[i]); + if (dbv.type == DBVT_ASCIIZ && !lstrcmpA(dbv.pszVal, protos[i]->szName)) + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETCURSEL, item, 0); + } + DBFreeVariant(&dbv); + } + if (-1 == (int) SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0)) + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETCURSEL, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETBUDDY, (WPARAM) GetDlgItem(hwndDlg, IDC_BLINKTIME), 0); // set buddy + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETRANGE, 0, MAKELONG(0x3FFF, 250)); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETPOS, 0, MAKELONG(DBGetContactSettingWord(NULL, "CList", "IconFlashTime", 550), 0)); + return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_AUTOHIDE) { + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + } + if (LOWORD(wParam) == IDC_DONTCYCLE || LOWORD(wParam) == IDC_CYCLE || LOWORD(wParam) == IDC_MULTITRAY) { + EnableWindow(GetDlgItem(hwndDlg, IDC_PRIMARYSTATUS), IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIME), IsDlgButtonChecked(hwndDlg, IDC_CYCLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CYCLETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_CYCLE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_ALWAYSMULTI), IsDlgButtonChecked(hwndDlg, IDC_MULTITRAY)); + } + if (LOWORD(wParam) == IDC_DISABLEBLINK) { + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKTIME), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKSPIN), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STMSDELAY), !IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + } + if ((LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_CYCLETIME) && HIWORD(wParam) != EN_CHANGE) + break; + if (LOWORD(wParam) == IDC_PRIMARYSTATUS && HIWORD(wParam) != CBN_SELCHANGE) + break; + if ((LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_CYCLETIME) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + if (LOWORD(wParam) == IDC_BLINKTIME && HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return 0; // dont make apply enabled during buddy set crap + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + DBWriteContactSettingByte(NULL, "CList", "HideOffline", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_HIDEOFFLINE)); + { + DWORD caps = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS1, 0); + if (caps & CLUIF_HIDEEMPTYGROUPS) + DBWriteContactSettingByte(NULL, "CList", "HideEmptyGroups", + (BYTE) IsDlgButtonChecked(hwndDlg, IDC_HIDEEMPTYGROUPS)); + if (caps & CLUIF_DISABLEGROUPS) + DBWriteContactSettingByte(NULL, "CList", "UseGroups", (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_DISABLEGROUPS)); + if (!(caps & CLUIF_HASONTOPOPTION)) { + DBWriteContactSettingByte(NULL, "CList", "OnTop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONTOP)); + SetWindowPos((HWND) CallService(MS_CLUI_GETHWND, 0, 0), + IsDlgButtonChecked(hwndDlg, IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE); + } + if (!(caps & CLUIF_HASAUTOHIDEOPTION)) { + DBWriteContactSettingByte(NULL, "CList", "AutoHide", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + DBWriteContactSettingWord(NULL, "CList", "HideTime", + (WORD) SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_GETPOS, 0, 0)); + } + } + DBWriteContactSettingByte(NULL, "CList", "SortByStatus", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SORTBYSTATUS)); + DBWriteContactSettingByte(NULL, "CList", "SortByProto", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SORTBYPROTO)); + DBWriteContactSettingByte(NULL, "CList", "ConfirmDelete", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CONFIRMDELETE)); + DBWriteContactSettingByte(NULL, "CList", "Tray1Click", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONECLK)); + DBWriteContactSettingByte(NULL, "CList", "AlwaysStatus", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ALWAYSSTATUS)); + DBWriteContactSettingByte(NULL, "CList", "AlwaysMulti", (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_ALWAYSMULTI)); + DBWriteContactSettingByte(NULL, "CList", "TrayIcon", + (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE) ? SETTING_TRAYICON_SINGLE + : (IsDlgButtonChecked(hwndDlg, IDC_CYCLE) ? SETTING_TRAYICON_CYCLE : + SETTING_TRAYICON_MULTI))); + DBWriteContactSettingWord(NULL, "CList", "CycleTime", + (WORD) SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingWord(NULL, "CList", "IconFlashTime", + (WORD) SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "DisableTrayFlash", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + DBWriteContactSettingByte(NULL, "CList", "NoIconBlink", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ICONBLINK)); + if (!SendDlgItemMessage + (hwndDlg, IDC_PRIMARYSTATUS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0), 0)) + DBDeleteContactSetting(NULL, "CList", "PrimaryStatus"); + else + DBWriteContactSettingString(NULL, "CList", "PrimaryStatus", + ((PROTOCOLDESCRIPTOR *) + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0), + 0))->szName); + pcli->pfnTrayIconIconsChanged(); + pcli->pfnLoadContactTree(); /* this won't do job properly since it only really works when changes happen */ + pcli->pfnInvalidateDisplayNameCacheEntry( INVALID_HANDLE_VALUE ); /* force reshuffle */ + return TRUE; + } + break; + } + break; + } + return FALSE; +} + +static BOOL CALLBACK DlgProcHotkeyOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + DBVARIANT dbv; + + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_SHOWHIDE, DBGetContactSettingByte(NULL, "CList", "HKEnShowHide", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_READMSG, DBGetContactSettingByte(NULL, "CList", "HKEnReadMsg", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_NETSEARCH, DBGetContactSettingByte(NULL, "CList", "HKEnNetSearch", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWOPTIONS, DBGetContactSettingByte(NULL, "CList", "HKEnShowOptions", 0) ? BST_CHECKED : BST_UNCHECKED); + + EnableWindow(GetDlgItem(hwndDlg, IDC_HKSHOWHIDE), IsDlgButtonChecked(hwndDlg, IDC_SHOWHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HKREADMSG), IsDlgButtonChecked(hwndDlg, IDC_READMSG)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HKSEARCH), IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SEARCHURL), IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SEARCHNEWWND), IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HOTKEYURLSTR), IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HKSHOWOPTIONS), IsDlgButtonChecked(hwndDlg, IDC_SHOWOPTIONS)); + + SendDlgItemMessage(hwndDlg, IDC_HKSHOWHIDE, HKM_SETHOTKEY, + DBGetContactSettingWord(NULL, "CList", "HKShowHide", MAKEWORD('A', HOTKEYF_CONTROL | HOTKEYF_SHIFT)), 0); + SendDlgItemMessage(hwndDlg, IDC_HKREADMSG, HKM_SETHOTKEY, + DBGetContactSettingWord(NULL, "CList", "HKReadMsg", MAKEWORD('I', HOTKEYF_CONTROL | HOTKEYF_SHIFT)), 0); + SendDlgItemMessage(hwndDlg, IDC_HKSEARCH, HKM_SETHOTKEY, + DBGetContactSettingWord(NULL, "CList", "HKNetSearch", MAKEWORD('S', HOTKEYF_CONTROL | HOTKEYF_SHIFT)), 0); + SendDlgItemMessage(hwndDlg, IDC_HKSHOWOPTIONS, HKM_SETHOTKEY, + DBGetContactSettingWord(NULL, "CList", "HKShowOptions", MAKEWORD('O', HOTKEYF_CONTROL | HOTKEYF_SHIFT)), 0); + if (!DBGetContactSetting(NULL, "CList", "SearchUrl", &dbv)) { + SetDlgItemTextA(hwndDlg, IDC_SEARCHURL, dbv.pszVal); + mir_free(dbv.pszVal); + } + else + SetDlgItemTextA(hwndDlg, IDC_SEARCHURL, "http://www.google.com/"); + CheckDlgButton(hwndDlg, IDC_SEARCHNEWWND, DBGetContactSettingByte(NULL, "CList", "HKSearchNewWnd", 0) ? BST_CHECKED : BST_UNCHECKED); + return TRUE; + } + case WM_COMMAND: + if (LOWORD(wParam) == IDC_SEARCHURL && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + switch (LOWORD(wParam)) { + case IDC_SHOWHIDE: + EnableWindow(GetDlgItem(hwndDlg, IDC_HKSHOWHIDE), IsDlgButtonChecked(hwndDlg, IDC_SHOWHIDE)); + break; + case IDC_READMSG: + EnableWindow(GetDlgItem(hwndDlg, IDC_HKREADMSG), IsDlgButtonChecked(hwndDlg, IDC_READMSG)); + break; + case IDC_NETSEARCH: + EnableWindow(GetDlgItem(hwndDlg, IDC_HKSEARCH), IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SEARCHURL), IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SEARCHNEWWND), IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HOTKEYURLSTR), IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + break; + case IDC_SHOWOPTIONS: + EnableWindow(GetDlgItem(hwndDlg, IDC_HKSHOWOPTIONS), IsDlgButtonChecked(hwndDlg, IDC_SHOWOPTIONS)); + break; + } + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + char str[256]; + pcli->pfnHotKeysUnregister((HWND) CallService(MS_CLUI_GETHWND, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "HKEnShowHide", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWHIDE)); + DBWriteContactSettingWord(NULL, "CList", "HKShowHide", (WORD) SendDlgItemMessage(hwndDlg, IDC_HKSHOWHIDE, HKM_GETHOTKEY, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "HKEnReadMsg", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_READMSG)); + DBWriteContactSettingWord(NULL, "CList", "HKReadMsg", (WORD) SendDlgItemMessage(hwndDlg, IDC_HKREADMSG, HKM_GETHOTKEY, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "HKEnNetSearch", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_NETSEARCH)); + DBWriteContactSettingWord(NULL, "CList", "HKNetSearch", (WORD) SendDlgItemMessage(hwndDlg, IDC_HKSEARCH, HKM_GETHOTKEY, 0, 0)); + GetDlgItemTextA(hwndDlg, IDC_SEARCHURL, str, SIZEOF(str)); + DBWriteContactSettingString(NULL, "CList", "SearchUrl", str); + DBWriteContactSettingByte(NULL, "CList", "HKSearchNewWnd", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SEARCHNEWWND)); + DBWriteContactSettingByte(NULL, "CList", "HKEnShowOptions", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWOPTIONS)); + DBWriteContactSettingWord(NULL, "CList", "HKShowOptions", (WORD) SendDlgItemMessage(hwndDlg, IDC_HKSHOWOPTIONS, HKM_GETHOTKEY, 0, 0)); + pcli->pfnHotKeysRegister((HWND) CallService(MS_CLUI_GETHWND, 0, 0)); + return TRUE; + } + } + break; + } + return FALSE; +} + +/****************************************************************************************/ + +static UINT expertOnlyControls[] = { IDC_ALWAYSSTATUS }; + +int CListOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = -1000000000; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLIST); + odp.pszTitle = "Contact List"; + odp.pfnDlgProc = DlgProcGenOpts; + odp.flags = ODPF_BOLDGROUPS; + odp.nIDBottomSimpleControl = IDC_STCLISTGROUP; + odp.expertOnlyControls = expertOnlyControls; + odp.nExpertOnlyControls = SIZEOF(expertOnlyControls); + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + + odp.position = -900000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_HOTKEY); + odp.pszTitle = "Hotkeys"; + odp.pszGroup = "Events"; + odp.pfnDlgProc = DlgProcHotkeyOpts; + odp.nIDBottomSimpleControl = 0; + odp.nExpertOnlyControls = 0; + odp.expertOnlyControls = NULL; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + return 0; +} diff --git a/miranda-wine/plugins/clist/cluiopts.c b/miranda-wine/plugins/clist/cluiopts.c new file mode 100644 index 0000000..588d3b1 --- /dev/null +++ b/miranda-wine/plugins/clist/cluiopts.c @@ -0,0 +1,346 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ +#include "commonheaders.h" + +extern BOOL(WINAPI * MySetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD); + +static BOOL CALLBACK DlgProcCluiOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_BRINGTOFRONT, + DBGetContactSettingByte(NULL, "CList", "BringToFront", SETTING_BRINGTOFRONT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONTOP, DBGetContactSettingByte(NULL, "CList", "OnTop", SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TOOLWND, + DBGetContactSettingByte(NULL, "CList", "ToolWindow", SETTING_TOOLWINDOW_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MIN2TRAY, + DBGetContactSettingByte(NULL, "CList", "Min2Tray", SETTING_MIN2TRAY_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + if (IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)) + EnableWindow(GetDlgItem(hwndDlg, IDC_MIN2TRAY), FALSE); + CheckDlgButton(hwndDlg, IDC_SHOWCAPTION, + DBGetContactSettingByte(NULL, "CLUI", "ShowCaption", SETTING_SHOWCAPTION_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWMAINMENU, + DBGetContactSettingByte(NULL, "CLUI", "ShowMainMenu", SETTING_SHOWMAINMENU_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CLIENTDRAG, + DBGetContactSettingByte(NULL, "CLUI", "ClientAreaDrag", SETTING_CLIENTDRAG_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_MIN2TRAY), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TOOLWND), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TITLETEXT), FALSE); + } + CheckDlgButton(hwndDlg, IDC_FADEINOUT, DBGetContactSettingByte(NULL, "CLUI", "FadeInOut", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOSIZE, DBGetContactSettingByte(NULL, "CLUI", "AutoSize", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DROPSHADOW, DBGetContactSettingByte(NULL, "CList", "WindowShadow", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONDESKTOP, DBGetContactSettingByte(NULL, "CList", "OnDesktop", 0) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_MAXSIZESPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); + SendDlgItemMessage(hwndDlg, IDC_MAXSIZESPIN, UDM_SETPOS, 0, DBGetContactSettingByte(NULL, "CLUI", "MaxSizeHeight", 75)); + CheckDlgButton(hwndDlg, IDC_AUTOSIZEUPWARD, DBGetContactSettingByte(NULL, "CLUI", "AutoSizeUpward", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOHIDE, + DBGetContactSettingByte(NULL, "CList", "AutoHide", SETTING_AUTOHIDE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETRANGE, 0, MAKELONG(900, 1)); + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETPOS, 0, + MAKELONG(DBGetContactSettingWord(NULL, "CList", "HideTime", SETTING_HIDETIME_DEFAULT), 0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC01), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + if (!IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC21), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC22), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZEHEIGHT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZESPIN), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_AUTOSIZEUPWARD), FALSE); + } + + { DBVARIANT dbv; + if ( !DBGetContactSettingTString(NULL, "CList", "TitleText", &dbv)) { + SetDlgItemText(hwndDlg, IDC_TITLETEXT, dbv.ptszVal); + DBFreeVariant( &dbv ); + } + else SetDlgItemTextA(hwndDlg, IDC_TITLETEXT, MIRANDANAME); + } + if (!IsWinVer2000Plus()) { + EnableWindow(GetDlgItem(hwndDlg, IDC_FADEINOUT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSPARENT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DROPSHADOW), FALSE); + } + else + CheckDlgButton(hwndDlg, IDC_TRANSPARENT, + DBGetContactSettingByte(NULL, "CList", "Transparent", SETTING_TRANSPARENT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + + if (!IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC11), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC12), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSACTIVE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSINACTIVE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ACTIVEPERC), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_INACTIVEPERC), FALSE); + } + SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_SETRANGE, FALSE, MAKELONG(1, 255)); + SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_SETRANGE, FALSE, MAKELONG(1, 255)); + SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_SETPOS, TRUE, DBGetContactSettingByte(NULL, "CList", "Alpha", SETTING_ALPHA_DEFAULT)); + SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_SETPOS, TRUE, + DBGetContactSettingByte(NULL, "CList", "AutoAlpha", SETTING_AUTOALPHA_DEFAULT)); + SendMessage(hwndDlg, WM_HSCROLL, 0x12345678, 0); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_AUTOHIDE) { + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIME), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDETIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC01), IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + } + else if (LOWORD(wParam) == IDC_TRANSPARENT) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC11), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC12), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSACTIVE), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSINACTIVE), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_ACTIVEPERC), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_INACTIVEPERC), IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + } + else if (LOWORD(wParam) == IDC_AUTOSIZE) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC21), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC22), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZEHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXSIZESPIN), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_AUTOSIZEUPWARD), IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + } + else if (LOWORD(wParam) == IDC_TOOLWND) { + EnableWindow(GetDlgItem(hwndDlg, IDC_MIN2TRAY), !IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)); + } + else if (LOWORD(wParam) == IDC_SHOWCAPTION) { + EnableWindow(GetDlgItem(hwndDlg, IDC_TOOLWND), IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_MIN2TRAY), !IsDlgButtonChecked(hwndDlg, IDC_TOOLWND) + && IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TITLETEXT), IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)); + } + + if ((LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_TITLETEXT || LOWORD(wParam) == IDC_MAXSIZEHEIGHT) && + (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + + // Enable apply button + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_HSCROLL: + { + char str[10]; + wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0) / 255); + SetDlgItemTextA(hwndDlg, IDC_INACTIVEPERC, str); + wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0) / 255); + SetDlgItemTextA(hwndDlg, IDC_ACTIVEPERC, str); + } + if (wParam != 0x12345678) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + if (((LPNMHDR) lParam)->code == PSN_APPLY) { + DBWriteContactSettingByte(NULL, "CList", "OnTop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONTOP)); + DBWriteContactSettingByte(NULL, "CList", "ToolWindow", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)); + DBWriteContactSettingByte(NULL, "CList", "BringToFront", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_BRINGTOFRONT)); + DBWriteContactSettingByte(NULL, "CLUI", "FadeInOut", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_FADEINOUT)); + DBWriteContactSettingByte(NULL, "CLUI", "AutoSize", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + DBWriteContactSettingByte(NULL, "CLUI", "MaxSizeHeight", (BYTE) GetDlgItemInt(hwndDlg, IDC_MAXSIZEHEIGHT, NULL, FALSE)); + DBWriteContactSettingByte(NULL, "CLUI", "AutoSizeUpward", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZEUPWARD)); + DBWriteContactSettingByte(NULL, "CList", "AutoHide", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + DBWriteContactSettingWord(NULL, "CList", "HideTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "Transparent", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + DBWriteContactSettingByte(NULL, "CList", "Alpha", (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "AutoAlpha", (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, "CList", "WindowShadow", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DROPSHADOW)); + DBWriteContactSettingByte(NULL, "CList", "OnDesktop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONDESKTOP)); + DBWriteContactSettingByte(NULL, "CLUI", "ShowCaption", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)); + DBWriteContactSettingByte(NULL, "CLUI", "ShowMainMenu", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWMAINMENU)); + DBWriteContactSettingByte(NULL, "CLUI", "ClientAreaDrag", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CLIENTDRAG)); + DBWriteContactSettingByte(NULL, "CList", "Min2Tray", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_MIN2TRAY)); + { + TCHAR title[256]; + GetDlgItemText(hwndDlg, IDC_TITLETEXT, title, SIZEOF(title)); + DBWriteContactSettingTString(NULL, "CList", "TitleText", title); + SetWindowText(pcli->hwndContactList, title); + } + pcli->pfnLoadCluiGlobalOpts(); + SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg, IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE); + if (IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)) { + // Window must be hidden to dynamically remove the taskbar button. + // See http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_int/shell_int_programming/taskbar.asp + WINDOWPLACEMENT p; + p.length = sizeof(p); + GetWindowPlacement(pcli->hwndContactList, &p); + ShowWindow(pcli->hwndContactList, SW_HIDE); + SetWindowLong(pcli->hwndContactList, GWL_EXSTYLE, + GetWindowLong(pcli->hwndContactList, GWL_EXSTYLE) | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE); + SetWindowPlacement(pcli->hwndContactList, &p); + } + else SetWindowLong(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLong(pcli->hwndContactList, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW); + + if (IsDlgButtonChecked(hwndDlg, IDC_ONDESKTOP)) { + HWND hProgMan = FindWindowA("Progman", NULL); + if (IsWindow(hProgMan)) + SetParent(pcli->hwndContactList, hProgMan); + } + else SetParent(pcli->hwndContactList, NULL); + + if (IsDlgButtonChecked(hwndDlg, IDC_SHOWCAPTION)) + SetWindowLong(pcli->hwndContactList, GWL_STYLE, + GetWindowLong(pcli->hwndContactList, GWL_STYLE) | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); + else + SetWindowLong(pcli->hwndContactList, GWL_STYLE, + GetWindowLong(pcli->hwndContactList, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)); + if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWMAINMENU)) + SetMenu(pcli->hwndContactList, NULL); + else + SetMenu(pcli->hwndContactList, pcli->hMenuMain); + SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); + if (IsIconic(pcli->hwndContactList) && !IsDlgButtonChecked(hwndDlg, IDC_TOOLWND)) + ShowWindow(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg, IDC_MIN2TRAY) ? SW_HIDE : SW_SHOW); + if (IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)) { + SetWindowLong(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLong(pcli->hwndContactList, GWL_EXSTYLE) | WS_EX_LAYERED); + if (MySetLayeredWindowAttributes) + MySetLayeredWindowAttributes(pcli->hwndContactList, RGB(0, 0, 0), + (BYTE) DBGetContactSettingByte(NULL, "CList", "AutoAlpha", SETTING_AUTOALPHA_DEFAULT), + LWA_ALPHA); + } + else SetWindowLong(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLong(pcli->hwndContactList, GWL_EXSTYLE) & ~WS_EX_LAYERED); + + SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0); //forces it to send a cln_listsizechanged + return TRUE; + } + break; + } + return FALSE; +} + +static BOOL CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_SHOWSBAR, DBGetContactSettingByte(NULL, "CLUI", "ShowSBar", 1) ? BST_CHECKED : BST_UNCHECKED); + { + BYTE showOpts = DBGetContactSettingByte(NULL, "CLUI", "SBarShow", 1); + CheckDlgButton(hwndDlg, IDC_SHOWICON, showOpts & 1 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWPROTO, showOpts & 2 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWSTATUS, showOpts & 4 ? BST_CHECKED : BST_UNCHECKED); + } + CheckDlgButton(hwndDlg, IDC_RIGHTSTATUS, DBGetContactSettingByte(NULL, "CLUI", "SBarRightClk", 0) ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_RIGHTMIRANDA, !IsDlgButtonChecked(hwndDlg, IDC_RIGHTSTATUS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_EQUALSECTIONS, DBGetContactSettingByte(NULL, "CLUI", "EqualSections", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SBPANELBEVEL, DBGetContactSettingByte(NULL, "CLUI", "SBarBevel", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWGRIP, DBGetContactSettingByte(NULL, "CLUI", "ShowGrip", 1) ? BST_CHECKED : BST_UNCHECKED); + if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWICON), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPROTO), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTMIRANDA), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_EQUALSECTIONS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SBPANELBEVEL), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWGRIP), FALSE); + } + return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_SHOWSBAR) { + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWICON), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPROTO), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSTATUS), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTSTATUS), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTMIRANDA), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_EQUALSECTIONS), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SBPANELBEVEL), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWGRIP), IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + if (((LPNMHDR) lParam)->code == PSN_APPLY ) { + DBWriteContactSettingByte(NULL, "CLUI", "ShowSBar", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + DBWriteContactSettingByte(NULL, "CLUI", "SBarShow", + (BYTE) ((IsDlgButtonChecked(hwndDlg, IDC_SHOWICON) ? 1 : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SHOWPROTO) ? 2 : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS) ? 4 : 0))); + DBWriteContactSettingByte(NULL, "CLUI", "SBarRightClk", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_RIGHTMIRANDA)); + DBWriteContactSettingByte(NULL, "CLUI", "EqualSections", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_EQUALSECTIONS)); + DBWriteContactSettingByte(NULL, "CLUI", "SBarBevel", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SBPANELBEVEL)); + pcli->pfnLoadCluiGlobalOpts(); + if (DBGetContactSettingByte(NULL, "CLUI", "ShowGrip", 1) != (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWGRIP)) { + HWND parent = GetParent(pcli->hwndStatus); + int flags = WS_CHILD | CCS_BOTTOM; + DBWriteContactSettingByte(NULL, "CLUI", "ShowGrip", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWGRIP)); + ShowWindow(pcli->hwndStatus, SW_HIDE); + DestroyWindow(pcli->hwndStatus); + flags |= DBGetContactSettingByte(NULL, "CLUI", "ShowSBar", 1) ? WS_VISIBLE : 0; + flags |= DBGetContactSettingByte(NULL, "CLUI", "ShowGrip", 1) ? SBARS_SIZEGRIP : 0; + pcli->hwndStatus = CreateWindow(STATUSCLASSNAME, NULL, flags, 0, 0, 0, 0, parent, NULL, g_hInst, NULL); + } + if (IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)) + ShowWindow(pcli->hwndStatus, SW_SHOW); + else + ShowWindow(pcli->hwndStatus, SW_HIDE); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + return TRUE; + } + break; + } + return FALSE; +} + +/****************************************************************************************/ + +static UINT expertOnlyControls[] = +{ + IDC_BRINGTOFRONT, IDC_AUTOSIZE, IDC_STATIC21, IDC_MAXSIZEHEIGHT, IDC_MAXSIZESPIN, + IDC_STATIC22, IDC_AUTOSIZEUPWARD, IDC_SHOWMAINMENU, IDC_SHOWCAPTION, IDC_CLIENTDRAG +}; + +int CluiOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 0; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLUI); + odp.pszTitle = "Window"; + odp.pszGroup = "Contact List"; + odp.pfnDlgProc = DlgProcCluiOpts; + odp.flags = ODPF_BOLDGROUPS; + odp.nIDBottomSimpleControl = IDC_STWINDOWGROUP; + odp.expertOnlyControls = expertOnlyControls; + odp.nExpertOnlyControls = SIZEOF(expertOnlyControls); + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SBAR); + odp.pszTitle = "Status Bar"; + odp.pfnDlgProc = DlgProcSBarOpts; + odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY; + odp.nIDBottomSimpleControl = 0; + odp.nExpertOnlyControls = 0; + odp.expertOnlyControls = NULL; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + return 0; +} diff --git a/miranda-wine/plugins/clist/commonheaders.c b/miranda-wine/plugins/clist/commonheaders.c new file mode 100644 index 0000000..14f99f7 --- /dev/null +++ b/miranda-wine/plugins/clist/commonheaders.c @@ -0,0 +1 @@ +#include "commonheaders.h" diff --git a/miranda-wine/plugins/clist/commonheaders.h b/miranda-wine/plugins/clist/commonheaders.h new file mode 100644 index 0000000..6a061ff --- /dev/null +++ b/miranda-wine/plugins/clist/commonheaders.h @@ -0,0 +1,96 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2005 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. +*/ + +#if defined(UNICODE) +#define _UNICODE 1 +#endif + +#include +#include + +#ifdef _DEBUG +# define _CRTDBG_MAP_ALLOC +# include +# include +#endif + +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "resource.h" +#include "forkthread.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clc.h" +#include "clist.h" + +// shared vars +extern HINSTANCE g_hInst; + +/* most free()'s are invalid when the code is executed from a dll, so this changes + all the bad free()'s to good ones, however it's still incorrect code. The reasons for not + changing them include: + + * DBFreeVariant has a CallService() lookup + * free() is executed in some large loops to do with clist creation of group data + * easy search and replace + +*/ + +extern struct MM_INTERFACE memoryManagerInterface; + +#define mir_alloc(n) memoryManagerInterface.mmi_malloc(n) +#define mir_free(ptr) memoryManagerInterface.mmi_free(ptr) +#define mir_realloc(ptr,size) memoryManagerInterface.mmi_realloc(ptr,size) + +static __inline char * mir_strdup(const char * src) +{ + char * p = 0; + if ( src == NULL ) return NULL; + p=mir_alloc( strlen(src)+1 ); + strcpy(p, src); + return p; +} diff --git a/miranda-wine/plugins/clist/forkthread.c b/miranda-wine/plugins/clist/forkthread.c new file mode 100644 index 0000000..920fc1f --- /dev/null +++ b/miranda-wine/plugins/clist/forkthread.c @@ -0,0 +1,94 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" + +struct FORK_ARG +{ + HANDLE hEvent; + void (__cdecl * threadcode) (void *); + unsigned (__stdcall * threadcodeex) (void *); + void *arg; +}; + +void __cdecl forkthread_r(struct FORK_ARG *fa) +{ + void (*callercode) (void *) = fa->threadcode; + void *arg = fa->arg; + CallService(MS_SYSTEM_THREAD_PUSH, 0, 0); + SetEvent(fa->hEvent); + __try { + callercode(arg); + } + __finally { + CallService(MS_SYSTEM_THREAD_POP, 0, 0); + } + return; +} + +unsigned long forkthread(void (__cdecl * threadcode) (void *), unsigned long stacksize, void *arg) +{ + unsigned long rc; + struct FORK_ARG fa; + fa.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + fa.threadcode = threadcode; + fa.arg = arg; + rc = _beginthread(forkthread_r, stacksize, &fa); + if ((unsigned long) -1L != rc) { + WaitForSingleObject(fa.hEvent, INFINITE); + } //if + CloseHandle(fa.hEvent); + return rc; +} + +unsigned long __stdcall forkthreadex_r(struct FORK_ARG *fa) +{ + unsigned (__stdcall * threadcode) (void *) = fa->threadcodeex; + void *arg = fa->arg; + unsigned long rc; + + CallService(MS_SYSTEM_THREAD_PUSH, 0, 0); + SetEvent(fa->hEvent); + __try { + rc = threadcode(arg); + } + __finally { + CallService(MS_SYSTEM_THREAD_POP, 0, 0); + } + return rc; +} + +unsigned long forkthreadex(void *sec, unsigned stacksize, unsigned (__stdcall * threadcode) (void *), void *arg, unsigned cf, unsigned *thraddr) +{ + unsigned long rc; + struct FORK_ARG fa; + fa.threadcodeex = threadcode; + fa.arg = arg; + fa.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + rc = _beginthreadex(sec, stacksize, forkthreadex_r, &fa, 0, thraddr); + if (rc) { + WaitForSingleObject(fa.hEvent, INFINITE); + } + CloseHandle(fa.hEvent); + return rc; +} diff --git a/miranda-wine/plugins/clist/forkthread.h b/miranda-wine/plugins/clist/forkthread.h new file mode 100644 index 0000000..9abcf5e --- /dev/null +++ b/miranda-wine/plugins/clist/forkthread.h @@ -0,0 +1,63 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +/* + +Purpose: + + A safe version of _beginthread() + +Description: + + A new thread is created and the source thread is paused until + internal code to call MS_SYSTEM_THREAD_PUSH is made in the context + if the new thread. + + The source thread is then released and then the user supplied + code is called, when that function returns -- MS_SYSTEM_THREAD_POP + is called and then the thread returns. + + This insures that Miranda will not exit whilst new threads + are trying to be born; and the unwind wait stack will unsure + that Miranda will wait for all created threads to return as well. + +Cavets: + + The function must be reimplemented across MT plugins, since thread + creation depends on CRT which can not be shared. + +*/ +unsigned long forkthread ( + void (__cdecl *threadcode)(void*), + unsigned long stacksize, + void *arg +); + +unsigned long forkthreadex( + void *sec, + unsigned stacksize, + unsigned (__stdcall *threadcode)(void*), + void *arg, + unsigned cf, + unsigned *thraddr +); diff --git a/miranda-wine/plugins/clist/init.c b/miranda-wine/plugins/clist/init.c new file mode 100644 index 0000000..843a5bb --- /dev/null +++ b/miranda-wine/plugins/clist/init.c @@ -0,0 +1,175 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2005 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. +*/ + +#include "commonheaders.h" + +HINSTANCE g_hInst = 0; +PLUGINLINK *pluginLink; +CLIST_INTERFACE* pcli = NULL; +HIMAGELIST himlCListClc = NULL; +HANDLE hStatusModeChangeEvent; + +extern int currentDesiredStatusMode; + +struct MM_INTERFACE memoryManagerInterface; +BOOL(WINAPI * MySetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD) = NULL; + +///////////////////////////////////////////////////////////////////////////////////////// +// external functions + +int MenuProcessCommand(WPARAM wParam, LPARAM lParam); +int InitCustomMenus(void); +void UninitCustomMenus(void); + +void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT * rcPaint); + +int ClcOptInit(WPARAM wParam, LPARAM lParam); +int CluiOptInit(WPARAM wParam, LPARAM lParam); +int CListOptInit(WPARAM wParam, LPARAM lParam); + +///////////////////////////////////////////////////////////////////////////////////////// +// dll stub + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved) +{ + g_hInst = hInstDLL; + DisableThreadLibraryCalls(g_hInst); + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// returns the plugin information + +PLUGININFO pluginInfo = { + sizeof(PLUGININFO), + #if defined( _UNICODE ) + "Classic contact list (Unicode)", + #else + "Classic contact list", + #endif + PLUGIN_MAKE_VERSION(0, 5, 1, 1), + + "Display contacts, event notifications, protocol status", + "Miranda IM project", + "ghazan@miranda-im.org", + "Copyright 2000-2006 Miranda IM project", + "http://www.miranda-im.org", + UNICODE_AWARE, + DEFMOD_CLISTALL +}; + +__declspec(dllexport) PLUGININFO *MirandaPluginInfo(DWORD mirandaVersion) +{ + if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 4, 3, 0)) + return NULL; + return &pluginInfo; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// called when all modules got loaded + +static int OnModulesLoaded( WPARAM wParam, LPARAM lParam ) +{ + himlCListClc = (HIMAGELIST) CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// options iniatialization + +static int OnOptsInit(WPARAM wParam, LPARAM lParam) +{ + ClcOptInit(wParam, lParam); + CluiOptInit(wParam, lParam); + CListOptInit(wParam, lParam); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// menu status services + +static int SetStatusMode(WPARAM wParam, LPARAM lParam) +{ + //todo: check wParam is valid so people can't use this to run random menu items + MenuProcessCommand(MAKEWPARAM(LOWORD(wParam), MPCF_MAINMENU), 0); + return 0; +} + +static int GetStatusMode(WPARAM wParam, LPARAM lParam) +{ + return currentDesiredStatusMode; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// main clist initialization routine + +int __declspec(dllexport) CListInitialise(PLUGINLINK * link) +{ + int rc = 0; + pluginLink = link; + #ifdef _DEBUG + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + #endif + + // get the internal malloc/free() + memset(&memoryManagerInterface, 0, sizeof(memoryManagerInterface)); + memoryManagerInterface.cbSize = sizeof(memoryManagerInterface); + CallService(MS_SYSTEM_GET_MMI, 0, (LPARAM) & memoryManagerInterface); + + pcli = ( CLIST_INTERFACE* )CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, (LPARAM)g_hInst); + if ( (int)pcli == CALLSERVICE_NOTFOUND ) { + MessageBoxA( NULL, "This version of plugin requires Miranda IM 0.5 or later", "Fatal error", MB_OK ); + return 1; + } + pcli->pfnPaintClc = PaintClc; + + MySetLayeredWindowAttributes = (BOOL(WINAPI *) (HWND, COLORREF, BYTE, DWORD)) GetProcAddress( + LoadLibraryA("user32.dll"), "SetLayeredWindowAttributes"); + + HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + HookEvent(ME_OPT_INITIALISE, OnOptsInit); + + hStatusModeChangeEvent = CreateHookableEvent(ME_CLIST_STATUSMODECHANGE); + + InitCustomMenus(); + CreateServiceFunction(MS_CLIST_SETSTATUSMODE, SetStatusMode); + CreateServiceFunction(MS_CLIST_GETSTATUSMODE, GetStatusMode); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// a plugin loader aware of CList exports will never call this. + +int __declspec(dllexport) Load(PLUGINLINK * link) +{ + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// a plugin unloader + +int __declspec(dllexport) Unload(void) +{ + UninitCustomMenus(); + return 0; +} diff --git a/miranda-wine/plugins/clist/res/blank.ico b/miranda-wine/plugins/clist/res/blank.ico new file mode 100644 index 0000000..7845f62 Binary files /dev/null and b/miranda-wine/plugins/clist/res/blank.ico differ diff --git a/miranda-wine/plugins/clist/res/delete.ico b/miranda-wine/plugins/clist/res/delete.ico new file mode 100644 index 0000000..9b0f0ff Binary files /dev/null and b/miranda-wine/plugins/clist/res/delete.ico differ diff --git a/miranda-wine/plugins/clist/res/dragcopy.cur b/miranda-wine/plugins/clist/res/dragcopy.cur new file mode 100644 index 0000000..89c7c96 Binary files /dev/null and b/miranda-wine/plugins/clist/res/dragcopy.cur differ diff --git a/miranda-wine/plugins/clist/res/dropuser.cur b/miranda-wine/plugins/clist/res/dropuser.cur new file mode 100644 index 0000000..a84b19e Binary files /dev/null and b/miranda-wine/plugins/clist/res/dropuser.cur differ diff --git a/miranda-wine/plugins/clist/res/hyperlin.cur b/miranda-wine/plugins/clist/res/hyperlin.cur new file mode 100644 index 0000000..f0f548c Binary files /dev/null and b/miranda-wine/plugins/clist/res/hyperlin.cur differ diff --git a/miranda-wine/plugins/clist/res/rename.ico b/miranda-wine/plugins/clist/res/rename.ico new file mode 100644 index 0000000..2c6bc2a Binary files /dev/null and b/miranda-wine/plugins/clist/res/rename.ico differ diff --git a/miranda-wine/plugins/clist/resource.h b/miranda-wine/plugins/clist/resource.h new file mode 100644 index 0000000..d6aeddf --- /dev/null +++ b/miranda-wine/plugins/clist/resource.h @@ -0,0 +1,554 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDC_AUTHICON 1 +#define IDC_NOTOALL 3 +#define IDC_APPLY 3 +#define IDI_MIRANDA 102 +#define IDD_ABOUT 103 +#define IDI_SMS 103 +#define IDI_ONLINE 104 +#define IDI_OFFLINE 105 +#define IDD_GNUPL 110 +#define IDD_ADDED 115 +#define IDD_URLSEND 119 +#define IDD_URLRECV 120 +#define IDD_AUTHREQ 121 +#define IDD_DETAILS 125 +#define IDD_OPT_CLIST 126 +#define IDD_HISTORY 127 +#define IDI_AWAY 128 +#define IDI_FREE4CHAT 129 +#define IDI_INVISIBLE 130 +#define IDI_NA 131 +#define IDD_OPT_SOUND 134 +#define IDI_SENDURL 135 +#define IDI_RECVMSG 136 +#define IDI_SENDMSG 137 +#define IDI_URL 138 +#define IDI_DND 158 +#define IDI_OCCUPIED 159 +#define IDI_USERDETAILS 160 +#define IDI_FINDUSER 161 +#define IDI_HELP 162 +#define IDI_OPTIONS 163 +#define IDI_MIRANDAWEBSITE 172 +#define IDI_RENAME 173 +#define IDI_HISTORY 174 +#define IDI_DELETE 175 +#define IDR_CONTEXT 180 +#define IDC_DROP 183 +#define IDD_OPT_HOTKEY 184 +#define IDD_HISTORY_FIND 192 +#define IDI_SENDEMAIL 193 +#define IDD_FILERECV 194 +#define IDD_PROFILEMANAGER 197 +#define IDD_NEWPROFILE 198 +#define IDR_CLISTMENU 199 +#define IDI_BLANK 200 +#define IDD_FINDADD 201 +#define IDI_USERONLINE 201 +#define IDD_OPT_AUTOAWAY 202 +#define IDI_GROUPSHUT 202 +#define IDD_OPTIONS 203 +#define IDI_GROUPOPEN 203 +#define IDD_PLUGINCONFLICT 204 +#define IDD_FILESEND 205 +#define IDI_NOTICK 205 +#define IDD_OPT_PLUGINS 206 +#define IDI_TICK 206 +#define IDD_OPT_ICONS 207 +#define IDI_FILE 207 +#define IDI_TIMESTAMP 208 +#define IDI_CHANGEFONT 209 +#define IDI_ADDCONTACT 210 +#define IDI_SMALLDOT 211 +#define IDI_FILLEDBLOB 212 +#define IDD_READAWAYMSG 213 +#define IDI_EMPTYBLOB 213 +#define IDD_OPT_IGNORE 214 +#define IDC_HYPERLINKHAND 214 +#define IDD_OPT_VISIBILITY 215 +#define IDC_DROPUSER 215 +#define IDD_SETAWAYMSG 216 +#define IDI_DETAILSLOGO 216 +#define IDD_OPT_AWAYMSG 217 +#define IDD_OPT_CLUI 218 +#define IDD_INFO_SUMMARY 220 +#define IDD_INFO_CONTACT 221 +#define IDD_INFO_BACKGROUND 222 +#define IDD_INFO_NOTES 223 +#define IDD_ADDEMAIL 226 +#define IDD_ICONINDEX 227 +#define IDD_OPT_CLC 228 +#define IDD_OPT_CLCTEXT 229 +#define IDD_OPT_CLCBKG 230 +#define IDD_INFO_LOCATION 231 +#define IDD_INFO_WORK 232 +#define IDD_ADDPHONE 233 +#define IDD_OPT_SBAR 234 +#define IDD_INSTALLINI 235 +#define IDD_WARNINICHANGE 236 +#define IDD_INIIMPORTDONE 237 +#define IDD_OPT_CLCTEXTSIMPLE 239 +#define IDB_SORTCOLUP 239 +#define IDB_SORTCOLDOWN 240 +#define IDD_OPT_NETLIB 246 +#define IDD_NETLIBLOGOPTS 247 +#define IDD_FILETRANSFERINFO 249 +#define IDD_OPT_FILETRANSFER 250 +#define IDD_FILEEXISTS 251 +#define IDD_DELETECONTACT 254 +#define IDD_DENYREASON 256 +#define IDD_ADDCONTACT 257 +#define IDD_OPT_CONTACT 261 +#define IDI_MULTISEND 263 +#define IDI_DOWNARROW 264 +#define IDD_CREDITS 265 +#define IDD_OPT_IDLE 268 +#define IDC_SAVE 1001 +#define IDI_ONTHEPHONE 1002 +#define IDC_MESSAGE 1002 +#define IDI_OUTTOLUNCH 1003 +#define IDC_AUTOCLOSE 1004 +#define IDC_FROM 1005 +#define IDC_AUTOMIN 1005 +#define IDC_DATE 1006 +#define IDC_DUMPRECV 1006 +#define IDC_MSG 1008 +#define IDC_PROXYDNS 1008 +#define IDC_NAME 1009 +#define IDC_PROXYTYPE 1009 +#define IDC_STATIC23 1010 +#define IDC_SPECIFYPORTS 1013 +#define IDC_ST_ENTERMSG 1013 +#define IDC_ST_ENTERURL 1014 +#define IDC_SPECIFYPORTSO 1014 +#define IDC_TEXT 1019 +#define IDC_SHOWNAMES 1024 +#define IDC_ABOUT 1032 +#define IDC_MYNOTES 1033 +#define IDC_URLS 1037 +#define IDC_REPLY 1039 +#define IDC_URL 1041 +#define IDC_REASON 1046 +#define IDC_EMAIL 1048 +#define IDC_NAMENICK 1049 +#define IDC_NAMEFIRST 1050 +#define IDC_NAMELAST 1051 +#define IDC_NICK 1053 +#define IDC_GENDER 1060 +#define IDC_CITY 1061 +#define IDC_STATE 1062 +#define IDC_COUNTRY 1063 +#define IDC_AGE 1064 +#define IDC_ZIP 1064 +#define IDC_PHONE 1065 +#define IDC_STREET 1065 +#define IDC_COMPANY 1066 +#define IDC_LANGUAGE1 1066 +#define IDC_TIMEZONE 1067 +#define IDC_DEPARTMENT 1067 +#define IDC_LOCALTIME 1068 +#define IDC_DETAILS 1069 +#define IDC_POSITION 1069 +#define IDC_LANGUAGE2 1069 +#define IDC_ADD 1070 +#define IDC_LANGUAGE3 1070 +#define IDC_MOREOPTIONS 1071 +#define IDC_USERMENU 1071 +#define IDC_MIN2TRAY 1073 +#define IDC_ONTOP 1074 +#define IDC_SHOWMAINMENU 1075 +#define IDC_CLIENTDRAG 1076 +#define IDC_EDIT 1078 +#define IDC_LIST 1079 +#define IDC_HISTORY 1080 +#define IDC_USESOUND 1085 +#define IDC_TOOLWND 1097 +#define IDC_ONECLK 1098 +#define IDC_SHOWCAPTION 1098 +#define IDC_HIDEOFFLINE 1099 +#define IDC_SHOWHIDE 1100 +#define IDC_HIDEEMPTYGROUPS 1100 +#define IDC_SORTBYSTATUS 1101 +#define IDC_FADEINOUT 1101 +#define IDC_READMSG 1102 +#define IDC_AUTOSIZE 1102 +#define IDC_DISABLEGROUPS 1102 +#define IDC_AUTOSIZEUPWARD 1103 +#define IDC_ALWAYSSTATUS 1103 +#define IDC_NETSEARCH 1104 +#define IDC_CONFIRMDELETE 1104 +#define IDC_SORTBYPROTO 1105 +#define IDC_SHOWOPTIONS 1105 +#define IDC_SEARCHURL 1106 +#define IDC_BUILDTIME 1108 +#define IDC_NUMBER 1113 +#define IDC_UIN 1123 +#define IDC_TRANSPARENT 1124 +#define IDC_TRANSINACTIVE 1126 +#define IDC_TRANSACTIVE 1128 +#define IDC_FINDWHAT 1131 +#define IDC_FIND 1132 +#define IDC_FILE 1133 +#define IDC_PROFILELIST 1134 +#define IDC_NEWPROFILE 1135 +#define IDC_NEWPROFILENAME 1136 +#define IDC_TABS 1141 +#define IDC_RESULTS 1142 +#define IDC_STATUS 1144 +#define IDC_SCREENSAVE 1145 +#define IDC_TIMED 1146 +#define IDC_AWAYTIME 1147 +#define IDC_USEPROXY 1148 +#define IDC_SETNA 1148 +#define IDC_PROXYAUTH 1149 +#define IDC_NATIME 1149 +#define IDC_PROXYHOST 1150 +#define IDC_PROXYPORT 1151 +#define IDC_PROXYUSER 1152 +#define IDC_PROXYPASS 1153 +#define IDC_STATIC11 1154 +#define IDC_STATIC12 1155 +#define IDC_STATIC21 1156 +#define IDC_STATIC22 1157 +#define IDC_STATIC31 1158 +#define IDC_STATIC32 1159 +#define IDC_PROXYAUTHNTLM 1160 +#define IDC_HKSHOWHIDE 1162 +#define IDC_HKREADMSG 1163 +#define IDC_SOUNDLIST 1163 +#define IDC_HKSEARCH 1164 +#define IDC_CHANGE 1164 +#define IDC_PREVIEW 1165 +#define IDC_HKSHOWOPTIONS 1165 +#define IDC_PLUGINLIST 1167 +#define IDC_FEATURENAME 1168 +#define IDC_CHOOSE 1169 +#define IDC_TO 1170 +#define IDC_ABOUTGROUP 1175 +#define IDC_DESCRIPTION 1176 +#define IDC_AUTHOR 1177 +#define IDC_COPYRIGHT 1178 +#define IDC_VERSION 1179 +#define IDC_HOMEPAGE 1181 +#define IDC_RESTARTREQD 1182 +#define IDC_ICONSET 1183 +#define IDC_BROWSE 1184 +#define IDC_RUNATSTARTBROWSE 1185 +#define IDC_PAGETREE 1186 +#define IDC_RUNNOW 1186 +#define IDC_INACTIVEPERC 1187 +#define IDC_ACTIVEPERC 1188 +#define IDC_SEARCHNEWWND 1188 +#define IDC_RETRIEVING 1193 +#define IDC_TITLETEXT 1196 +#define IDC_GETMORE 1200 +#define IDC_VISIBLEICON 1204 +#define IDC_INVISIBLEICON 1205 +#define IDC_FILEICON 1206 +#define IDC_ONLINEICON 1207 +#define IDC_FILENAMES 1208 +#define IDC_ALLICON 1208 +#define IDC_DONTREPLY 1209 +#define IDC_NONEICON 1209 +#define IDC_USEPREVIOUS 1210 +#define IDC_NODIALOG 1211 +#define IDC_USESPECIFIC 1212 +#define IDC_FILEDIR 1213 +#define IDC_ALLFILESPROGRESS 1217 +#define IDC_CURRENTSPEED 1219 +#define IDC_STAWAYTYPE 1220 +#define IDC_WHITERECT 1221 +#define IDC_ALLSPEED 1221 +#define IDC_CURRENTFILEPROGRESS 1222 +#define IDC_CURRENTFILEGROUP 1223 +#define IDC_FIRSTNAME 1224 +#define IDC_LASTNAME 1225 +#define IDC_CURRENTTRANSFERRED 1225 +#define IDC_DOBDAY 1226 +#define IDC_DOBMONTH 1227 +#define IDC_WEBPAGE 1228 +#define IDC_DOBYEAR 1228 +#define IDC_UPDATING 1231 +#define IDC_NAMEORDER 1234 +#define IDC_AUTOHIDE 1235 +#define IDC_HIDETIME 1236 +#define IDC_RECONNECTREQD 1239 +#define IDC_IMPORT 1241 +#define IDC_TOMAIN 1243 +#define IDC_TOPROTO 1244 +#define IDC_PROTOLIST 1245 +#define IDC_TODEFICON 1246 +#define IDC_IMPORTMULTI 1247 +#define IDC_MAXSIZEHEIGHT 1254 +#define IDC_MAXSIZESPIN 1255 +#define IDC_FONTID 1256 +#define IDC_SAMETYPE 1257 +#define IDC_SAMESTYLE 1258 +#define IDC_SAMECOLOUR 1259 +#define IDC_SAMEAS 1260 +#define IDC_TYPEFACE 1261 +#define IDC_BOLD 1262 +#define IDC_ITALIC 1263 +#define IDC_COLOUR 1264 +#define IDC_UNDERLINE 1265 +#define IDC_HOTCOLOUR 1267 +#define IDC_SAMESIZE 1268 +#define IDC_BKGCOLOUR 1269 +#define IDC_FILENAME 1271 +#define IDC_SCROLL 1277 +#define IDC_PROPORTIONAL 1278 +#define IDC_SELCOLOUR 1281 +#define IDC_QUICKCOLOUR 1282 +#define IDC_SMOOTHTIME 1283 +#define IDC_SMOOTHTIMESPIN 1284 +#define IDC_GREYOUT 1285 +#define IDC_ROWHEIGHT 1285 +#define IDC_ROWHEIGHTSPIN 1286 +#define IDC_GREYOUTOPTS 1288 +#define IDC_GROUPINDENT 1289 +#define IDC_GROUPINDENTSPIN 1290 +#define IDC_LEFTMARGIN 1291 +#define IDC_SAMPLE 1292 +#define IDC_LEFTMARGINSPIN 1292 +#define IDC_FONTSIZE 1293 +#define IDC_STRETCHH 1298 +#define IDC_STRETCHV 1299 +#define IDC_TILEH 1300 +#define IDC_SCRIPT 1300 +#define IDC_TILEV 1301 +#define IDC_GAMMACORRECT 1302 +#define IDC_INTERESTS 1305 +#define IDC_EMAILS 1306 +#define IDC_PAST 1307 +#define IDC_HIDEOFFLINEOPTS 1308 +#define IDC_PHONES 1308 +#define IDC_SMS 1310 +#define IDC_AREA 1312 +#define IDC_UPDATE 1313 +#define IDC_DONTCYCLE 1315 +#define IDC_PRIMARYSTATUS 1316 +#define IDC_CYCLE 1317 +#define IDC_CYCLETIME 1318 +#define IDC_CYCLETIMESPIN 1319 +#define IDC_HIDETIMESPIN 1320 +#define IDC_MULTITRAY 1321 +#define IDC_ALWAYSMULTI 1322 +#define IDC_SHOWICON 1323 +#define IDC_SHOWPROTO 1324 +#define IDC_SHOWSTATUS 1325 +#define IDC_EQUALSECTIONS 1326 +#define IDC_SHOWSBAR 1329 +#define IDC_RIGHTMIRANDA 1330 +#define IDC_RIGHTSTATUS 1331 +#define IDC_ININAME 1333 +#define IDC_VIEWINI 1334 +#define IDC_SECURITYINFO 1335 +#define IDC_SETTINGNAME 1336 +#define IDC_NEWVALUE 1337 +#define IDC_WARNNOMORE 1338 +#define IDC_DELETE 1339 +#define IDC_RECYCLE 1340 +#define IDC_NEWNAME 1341 +#define IDC_MOVE 1342 +#define IDC_LEAVE 1343 +#define IDC_EXPERT 1346 +#define IDC_SORTBYNAME 1347 +#define IDC_STAUTOHIDESECS 1349 +#define IDC_STCLISTGROUP 1350 +#define IDC_DISABLEDRAGDROP 1351 +#define IDC_NOTEDITLABELS 1352 +#define IDC_SHOWSELALWAYS 1353 +#define IDC_TRACKSELECT 1354 +#define IDC_SHOWGROUPCOUNTS 1355 +#define IDC_HIDECOUNTSWHENEMPTY 1356 +#define IDC_DIVIDERONOFF 1357 +#define IDC_NOTNOTRANSLUCENTSEL 1358 +#define IDC_LINEWITHGROUPS 1359 +#define IDC_QUICKSEARCHVISONLY 1360 +#define IDC_SORTGROUPSALPHA 1361 +#define IDC_NOTNOSMOOTHSCROLLING 1362 +#define IDC_BITMAP 1363 +#define IDC_STWINDOWGROUP 1364 +#define IDC_STATIC01 1365 +#define IDC_CATEGORYLIST 1366 +#define IDC_LOADICONS 1369 +#define IDC_STICONSGROUP 1371 +#define IDC_MSGICON 1375 +#define IDC_URLICON 1376 +#define IDC_STNOPAGE 1377 +#define IDC_STCHECKMARKS 1380 +#define IDC_STSAMETEXT 1382 +#define IDC_STASTEXT 1383 +#define IDC_STSIZETEXT 1384 +#define IDC_STCOLOURTEXT 1385 +#define IDC_STHORZBAR 1386 +#define IDC_MIRANDA 1388 +#define IDC_STATUSBAR 1389 +#define IDC_PROTOIDGROUP 1392 +#define IDC_BYPROTOID 1393 +#define IDC_PROTOID 1394 +#define IDC_EMAILGROUP 1395 +#define IDC_BYEMAIL 1396 +#define IDC_STNAMENICK 1397 +#define IDC_NAMEGROUP 1398 +#define IDC_BYNAME 1399 +#define IDC_STNAMEFIRST 1400 +#define IDC_STNAMELAST 1401 +#define IDC_ADVANCEDGROUP 1402 +#define IDC_BYADVANCED 1403 +#define IDC_ADVANCED 1404 +#define IDC_STSIMPLERIGHT 1440 +#define IDC_NETLIBUSERS 1443 +#define IDC_STOFTENPORT 1445 +#define IDC_STATIC51 1446 +#define IDC_STATIC52 1447 +#define IDC_STATIC43 1448 +#define IDC_LOGOPTIONS 1449 +#define IDC_PORTSRANGE 1450 +#define IDC_TOCONSOLE 1451 +#define IDC_STATIC53 1451 +#define IDC_SHOWCONSOLEATSTART 1452 +#define IDC_PORTSRANGEO 1452 +#define IDC_STATIC54 1453 +#define IDC_SHOWCONSOLE 1454 +#define IDC_TOOUTPUTDEBUGSTRING 1455 +#define IDC_TOFILE 1456 +#define IDC_CLEARCONSOLE 1457 +#define IDC_RUNATSTART 1458 +#define IDC_DUMPSENT 1464 +#define IDC_DUMPPROXY 1466 +#define IDC_TEXTDUMPS 1467 +#define IDC_AUTODETECTTEXT 1468 +#define IDC_TIMEFORMAT 1469 +#define IDC_FILENAMEBROWSE 1470 +#define IDC_SHOWTHISDLGATSTART 1471 +#define IDC_FILEDIRBROWSE 1475 +#define IDC_ALLFILESGROUP 1476 +#define IDC_SCANCMDLINEBROWSE 1476 +#define IDC_ALLTRANSFERRED 1477 +#define IDC_OPENFOLDER 1478 +#define IDC_OPENFILE 1479 +#define IDC_TOTALSIZE 1480 +#define IDC_APPENDNICKTODIR 1483 +#define IDC_AUTOACCEPT 1484 +#define IDC_SCANCMDLINE 1485 +#define IDC_WARNBEFOREOPENING 1488 +#define IDC_SCANDURINGDL 1489 +#define IDC_SCANAFTERDL 1490 +#define IDC_NOSCANNER 1491 +#define IDC_ST_CMDLINE 1492 +#define IDC_ST_CMDLINEHELP 1493 +#define IDC_PROPERTIES 1496 +#define IDC_RESUME 1497 +#define IDC_EXISTINGICON 1499 +#define IDC_RESUMEALL 1500 +#define IDC_OVERWRITE 1501 +#define IDC_OVERWRITEALL 1502 +#define IDC_SKIP 1503 +#define IDC_EXISTINGSIZE 1506 +#define IDC_EXISTINGDATE 1507 +#define IDC_EXISTINGTYPE 1508 +#define IDC_NEWICON 1509 +#define IDC_NEWSIZE 1510 +#define IDC_NEWDATE 1511 +#define IDC_NEWTYPE 1512 +#define IDC_SAVEAS 1513 +#define IDC_ASK 1516 +#define IDC_RENAME 1519 +#define IDC_VIRUSSCANNERGROUP 1520 +#define IDC_HIDE 1534 +#define IDC_TOPLINE 1535 +#define IDC_GPLBTN 1536 +#define IDC_MAIL 1536 +#define IDC_MYHANDLE 1540 +#define IDC_GROUP 1541 +#define IDC_ADDED 1542 +#define IDC_AUTH 1543 +#define IDC_PLUGINSTATIC1 1559 +#define IDC_DELETEHISTORY 1560 +#define IDC_HOTKEYURLSTR 1567 +#define IDC_SETNASTR 1568 +#define IDC_AAUTHOR 1569 +#define IDC_AHOMEPAGE 1570 +#define IDC_AVERSION 1571 +#define IDC_ACOPYRIGHT 1572 +#define IDC_ADESCRIPTION 1573 +#define IDC_PLUGINENABLE 1574 +#define IDC_AUTHREQ 1577 +#define IDC_AUTHGB 1578 +#define IDC_BRINGTOFRONT 1579 +#define IDC_PROTOCOL 1580 +#define IDC_CONTRIBLINK 1586 +#define IDC_HOMELINK 1587 +#define IDC_SUPPORTLINK 1588 +#define IDC_DEVS 1589 +#define IDC_GPL 1590 +#define IDC_LOGO 1591 +#define IDC_CREDITSTEXT 1595 +#define IDC_WSLOCK 1599 +#define IDC_BLINKTIME 1607 +#define IDC_BLINKSPIN 1608 +#define IDC_DISABLEBLINK 1609 +#define IDC_IDLE 1610 +#define IDC_SBPANELBEVEL 1611 +#define IDC_DROPSHADOW 1612 +#define IDC_SHOWGRIP 1612 +#define IDC_NOSCROLLBAR 1613 +#define IDC_BUTTON1 1633 +#define IDC_IDLECHECK 1636 +#define IDC_IDLEONWINDOWS 1637 +#define IDC_IDLEONMIRANDA 1638 +#define IDC_IDLEUSEGLI 1639 +#define IDC_SCREENSAVER 1642 +#define IDC_LOCKED 1643 +#define IDC_IDLESHORT 1644 +#define IDC_IDLELONG 1645 +#define IDC_IDLE1STTIME 1646 +#define IDC_IDLE2NDTIME 1647 +#define IDC_IDLEPRIVATE 1649 +#define IDC_AASTATUS 1650 +#define IDC_AASHORTIDLE 1651 +#define IDC_AALONGSTATUS 1652 +#define IDC_AALONGIDLE 1656 +#define IDC_ONDESKTOP 1657 +#define IDC_WINCOLOUR 1659 +#define IDC_ICONBLINK 1660 +#define IDC_STMSDELAY 1661 +#define IDI_SEARCHALL 32548 +#define ID_ICQ_EXIT 40001 +#define IDM_COPY 40001 +#define ID_RESET 40002 +#define POPUP_HIDEEMPTYGROUPS 40003 +#define POPUP_NEWSUBGROUP 40004 +#define POPUP_HIDEOFFLINE 40005 +#define POPUP_GROUPHIDEOFFLINE 40006 +#define POPUP_HIDEOFFLINEROOT 40007 +#define POPUP_DISABLEGROUPS 40008 +#define IDC_SENDMESSAGE 40009 +#define IDM_COPYALL 40011 +#define IDM_SELECTALL 40012 +#define IDM_CLEAR 40013 +#define IDM_OPENNEW 40014 +#define IDM_OPENEXISTING 40015 +#define IDM_COPYLINK 40016 +#define POPUP_HIDEMIRANDA 40017 +#define ID_TRAY_HIDE 40038 +#define ID_TRAY_EXIT 40040 +#define POPUP_NEWGROUP 40050 +#define POPUP_RENAMEGROUP 40052 +#define POPUP_DELETEGROUP 40053 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 269 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1662 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/miranda-wine/plugins/clist/resource.rc b/miranda-wine/plugins/clist/resource.rc new file mode 100644 index 0000000..698307c --- /dev/null +++ b/miranda-wine/plugins/clist/resource.rc @@ -0,0 +1,706 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DELETECONTACT DIALOGEX 0, 0, 284, 90 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | + DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Delete Contact" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "No",IDNO,162,38,65,14 + PUSHBUTTON "Yes",IDYES,54,38,65,14 + CONTROL "Hide from list only, in order to keep their history and ignore/visibility settings", + IDC_HIDE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | + WS_TABSTOP,7,65,270,9 + LTEXT "Use Options->Ignore (expert mode) to unhide contacts.", + IDC_STATIC,20,78,257,8 + CONTROL "Are you sure you want to delete %s?",IDC_TOPLINE,"Static", + SS_SIMPLE | SS_NOPREFIX | WS_GROUP,7,7,270,8 + LTEXT "This will erase all history and settings for this contact!", + IDC_STATIC,7,18,239,14 +END + +IDD_OPT_HOTKEY DIALOGEX 0, 0, 238, 136 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Hotkeys",IDC_STATIC,4,4,230,126 + CONTROL "Show/Hide:",IDC_SHOWHIDE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,19,78,9 + CONTROL "HotKey1",IDC_HKSHOWHIDE,"msctls_hotkey32",WS_BORDER | + WS_TABSTOP,92,17,93,12 + CONTROL "Read Msg:",IDC_READMSG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,36,78,9 + CONTROL "HotKey1",IDC_HKREADMSG,"msctls_hotkey32",WS_BORDER | + WS_TABSTOP,92,34,93,12 + CONTROL "Net Search:",IDC_NETSEARCH,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,53,78,9 + CONTROL "HotKey1",IDC_HKSEARCH,"msctls_hotkey32",WS_BORDER | + WS_TABSTOP,92,51,93,12 + LTEXT "URL:",IDC_HOTKEYURLSTR,26,71,22,8 + EDITTEXT IDC_SEARCHURL,92,69,136,12,ES_AUTOHSCROLL + CONTROL "Open in new browser window",IDC_SEARCHNEWWND,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,92,86,136,10 + CONTROL "Show Options",IDC_SHOWOPTIONS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,107,71,9 + CONTROL "HotKey1",IDC_HKSHOWOPTIONS,"msctls_hotkey32",WS_BORDER | + WS_TABSTOP,92,105,93,12 +END + +IDD_OPT_CLIST DIALOGEX 0, 0, 314, 204 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Hide offline users",IDC_HIDEOFFLINE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,17,124,10 + CONTROL "Hide empty groups",IDC_HIDEEMPTYGROUPS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,33,124,10 + CONTROL "Disable groups",IDC_DISABLEGROUPS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,50,124,10 + CONTROL "Ask before deleting contacts",IDC_CONFIRMDELETE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,67,124,10 + CONTROL "Sort contacts by name",IDC_SORTBYNAME,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,153,14,144,10 + CONTROL "Sort contacts by status",IDC_SORTBYSTATUS,"Button", + BS_AUTORADIOBUTTON,153,26,149,10 + CONTROL "Sort contacts by protocol",IDC_SORTBYPROTO,"Button", + BS_AUTORADIOBUTTON,153,38,151,10 + CONTROL "Single click interface",IDC_ONECLK,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,152,68,150,10 + CONTROL "Always show status in tooltip",IDC_ALWAYSSTATUS,"Button", + BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,152, + 81,151,11 + CONTROL "Disable icon blinking",IDC_DISABLEBLINK,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,152,95,86,9 + EDITTEXT IDC_BLINKTIME,153,109,35,12,ES_NUMBER + LTEXT "ms delay",IDC_STMSDELAY,192,110,113,8 + CONTROL "Show",IDC_DONTCYCLE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,10,143,97,10 + COMBOBOX IDC_PRIMARYSTATUS,107,142,78,70,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + LTEXT "icon when statuses differ",IDC_STATIC,189,144,116,8,NOT + WS_GROUP + CONTROL "Cycle icons every",IDC_CYCLE,"Button", + BS_AUTORADIOBUTTON,10,160,97,10 + EDITTEXT IDC_CYCLETIME,107,159,30,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_CYCLETIMESPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,127,158, + 10,14 + LTEXT "seconds, when statuses differ",IDC_STATIC,140,161,165,8, + NOT WS_GROUP + CONTROL "Show multiple icons",IDC_MULTITRAY,"Button", + BS_AUTORADIOBUTTON,10,177,98,10 + CONTROL "Only when statuses differ",IDC_ALWAYSMULTI,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,108,177,198,10 + GROUPBOX "Contact List",IDC_STCLISTGROUP,2,2,135,126 + GROUPBOX "System tray icon",IDC_STATIC,143,57,169,70 + GROUPBOX "System tray icon when using multiple protocols", + IDC_STATIC,2,131,310,66 + GROUPBOX "Contact List Sorting",IDC_STATIC,143,2,169,54,WS_GROUP + CONTROL "Spin5",IDC_BLINKSPIN,"msctls_updown32",UDS_SETBUDDYINT | + UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | + UDS_HOTTRACK,173,97,11,21 + CONTROL "Disable icon blinking",IDC_ICONBLINK,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,84,97,10 +END + +IDD_OPT_CLUI DIALOGEX 0, 0, 313, 245 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Window",IDC_STWINDOWGROUP,4,4,305,154 + CONTROL "Always on top",IDC_ONTOP,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,13,18,128,10 + CONTROL "Tool style main window",IDC_TOOLWND,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,32,128,10 + CONTROL "Minimize to tray",IDC_MIN2TRAY,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,13,46,128,10 + CONTROL "Hide contact list after it has been idle for", + IDC_AUTOHIDE,"Button",BS_AUTOCHECKBOX | BS_TOP | + BS_MULTILINE | WS_TABSTOP,141,18,162,10 + EDITTEXT IDC_HIDETIME,151,33,30,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_HIDETIMESPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,172,32,10, + 14 + LTEXT "seconds",IDC_STATIC01,186,35,56,8 + CONTROL "Automatically resize window to height of list", + IDC_AUTOSIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,141, + 55,162,10 + LTEXT "maximum",IDC_STATIC21,151,71,45,8 + EDITTEXT IDC_MAXSIZEHEIGHT,197,69,31,12,ES_RIGHT | ES_AUTOHSCROLL | + ES_NUMBER + CONTROL "Spin1",IDC_MAXSIZESPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_HOTTRACK,218,68,10,14 + LTEXT "% of screen",IDC_STATIC22,230,71,69,8 + CONTROL "Size upwards",IDC_AUTOSIZEUPWARD,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,151,86,147,10 + LTEXT "Title bar text:",IDC_STATIC,12,106,51,8 + GROUPBOX "Translucency options (Windows 2000/XP only)",IDC_STATIC, + 4,161,305,80 + CONTROL "Fade contact list in/out",IDC_FADEINOUT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,174,163,10 + CONTROL "Transparent contact list",IDC_TRANSPARENT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,191,151,9 + LTEXT "Inactive opacity:",IDC_STATIC11,23,206,89,8 + CONTROL "Slider2",IDC_TRANSINACTIVE,"msctls_trackbar32",TBS_TOP | + TBS_NOTICKS | WS_TABSTOP,112,205,130,11 + LTEXT "Active opacity:",IDC_STATIC12,23,221,89,8 + CONTROL "Slider2",IDC_TRANSACTIVE,"msctls_trackbar32",TBS_TOP | + TBS_NOTICKS | WS_TABSTOP,112,221,130,11 + LTEXT "000%",IDC_INACTIVEPERC,246,206,29,8,SS_NOPREFIX + LTEXT "000%",IDC_ACTIVEPERC,246,222,29,8,SS_NOPREFIX + CONTROL "Show menu bar",IDC_SHOWMAINMENU,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,60,128,10 + CONTROL "Easy move",IDC_CLIENTDRAG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,13,74,128,10 + CONTROL "Show title bar",IDC_SHOWCAPTION,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,88,128,10 + CONTROL "If window is partially covered, bring to front instead of hiding", + IDC_BRINGTOFRONT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | + WS_TABSTOP,141,102,162,16 + EDITTEXT IDC_TITLETEXT,63,104,72,12,ES_AUTOHSCROLL + CONTROL "Show drop shadow (restart required)",IDC_DROPSHADOW, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,122,138,10 + CONTROL "Pin to desktop",IDC_ONDESKTOP,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,13,137,128,10 +END + +IDD_OPT_CLC DIALOGEX 0, 0, 314, 251 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Items",IDC_STATIC,2,2,310,114 + CONTROL "Show divider between online and offline contacts", + IDC_DIVIDERONOFF,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 11,13,179,10 + CONTROL "Hot track items as mouse passes over",IDC_TRACKSELECT, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,28,179,10 + CONTROL "Disable drag and drop of items",IDC_DISABLEDRAGDROP, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,43,179,10 + CONTROL "Disable rename of items by clicking twice", + IDC_NOTEDITLABELS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 11,58,179,10 + CONTROL "Show selection even when list is not focused", + IDC_SHOWSELALWAYS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 11,73,179,10 + CONTROL "Make selection highlight translucent", + IDC_NOTNOTRANSLUCENTSEL,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,11,88,179,10 + LTEXT "'Hide Offline' means to hide:",IDC_STATIC,191,10,112,8 + CONTROL "Tree1",IDC_HIDEOFFLINEOPTS,"SysTreeView32", + TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | WS_BORDER | + WS_TABSTOP | 0x4000,191,20,112,86 + GROUPBOX "Groups",IDC_STATIC,2,120,148,121 + CONTROL "Draw a line alongside group names",IDC_LINEWITHGROUPS, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11, + 129,131,16 + CONTROL "Show counts of number of contacts in a group", + IDC_SHOWGROUPCOUNTS,"Button",BS_AUTOCHECKBOX | + BS_MULTILINE | WS_TABSTOP,11,147,131,16 + CONTROL "Hide group counts when there are none online", + IDC_HIDECOUNTSWHENEMPTY,"Button",BS_AUTOCHECKBOX | + BS_MULTILINE | WS_TABSTOP,11,165,131,16 + CONTROL "Sort groups alphabetically",IDC_SORTGROUPSALPHA,"Button", + BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,183,131, + 16 + CONTROL "Quicksearch in open groups only",IDC_QUICKSEARCHVISONLY, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11, + 201,131,16 + LTEXT "Indent groups by:",IDC_STATIC,11,221,67,8 + EDITTEXT IDC_GROUPINDENT,78,219,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_GROUPINDENTSPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,95,215,10, + 14 + LTEXT "pixels",IDC_STATIC,112,221,36,8 + GROUPBOX "Visual",IDC_STATIC,156,120,156,121 + CONTROL "Scroll list smoothly",IDC_NOTNOSMOOTHSCROLLING,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,164,130,139,10 + LTEXT "Time:",IDC_STATIC11,174,144,42,8 + EDITTEXT IDC_SMOOTHTIME,216,142,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_SMOOTHTIMESPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,237,137, + 10,14 + LTEXT "milliseconds",IDC_STATIC12,250,140,56,8,SS_CENTERIMAGE + LTEXT "Left margin:",IDC_STATIC,165,180,52,8 + EDITTEXT IDC_LEFTMARGIN,215,180,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_LEFTMARGINSPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,240,180, + 10,14 + LTEXT "pixels",IDC_STATIC,250,180,54,8 + CONTROL "Grey out entire list when:",IDC_GREYOUT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,165,195,139,10 + CONTROL "Tree1",IDC_GREYOUTOPTS,"SysTreeView32", + TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | WS_BORDER | + WS_TABSTOP | 0x4000,165,205,139,30 + CONTROL "Dim idle contacts",IDC_IDLE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,11,102,153,10 + CONTROL "Hide vertical scroll bar",IDC_NOSCROLLBAR,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,165,160,140,10 +END + +IDD_OPT_CLCTEXT DIALOGEX 0, 0, 277, 240 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Fonts",IDC_STATIC,4,4,269,125 + COMBOBOX IDC_FONTID,12,17,253,87,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "same",IDC_STSAMETEXT,19,32,45,10,SS_CENTERIMAGE + CONTROL "Typeface",IDC_SAMETYPE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,64,32,52,10 + CONTROL "Size",IDC_SAMESIZE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,117,32,45,10 + CONTROL "Style",IDC_SAMESTYLE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,163,32,48,10 + CONTROL "Colour",IDC_SAMECOLOUR,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,212,32,53,10 + LTEXT "as:",IDC_STASTEXT,19,46,45,10,SS_CENTERIMAGE + COMBOBOX IDC_SAMEAS,64,45,196,88,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + CONTROL "",IDC_STHORZBAR,"Static",SS_ETCHEDHORZ,9,64,259,1 + COMBOBOX IDC_TYPEFACE,12,72,136,182,CBS_DROPDOWN | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_SCRIPT,156,72,60,68,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + COMBOBOX IDC_FONTSIZE,225,72,40,69,CBS_DROPDOWN | WS_VSCROLL | + WS_TABSTOP + CONTROL "Bold",IDC_BOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12, + 88,45,10 + CONTROL "Italic",IDC_ITALIC,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,65,88,52,10 + CONTROL "Underline",IDC_UNDERLINE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,117,88,66,10 + CONTROL "",IDC_COLOUR,"ColourPicker",WS_TABSTOP,206,87,59,12 + EDITTEXT IDC_SAMPLE,63,104,151,16,ES_CENTER | ES_READONLY | NOT + WS_TABSTOP + GROUPBOX "Rows",IDC_STATIC,4,134,269,31 + LTEXT "Row height:",IDC_STATIC,12,148,65,8 + EDITTEXT IDC_ROWHEIGHT,77,146,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_ROWHEIGHTSPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,97,145,10, + 14 + LTEXT "pixels",IDC_STATIC,112,148,62,8 + GROUPBOX "Additional Colours",IDC_STATIC,4,171,269,65 + LTEXT "Selected text:",IDC_STATIC,12,186,65,8 + CONTROL "",IDC_SELCOLOUR,"ColourPicker",WS_TABSTOP,77,184,29,12 + LTEXT "Hottrack text:",IDC_STATIC,12,202,65,8 + CONTROL "",IDC_HOTCOLOUR,"ColourPicker",WS_TABSTOP,77,200,29,12 + CONTROL "Gamma correction",IDC_GAMMACORRECT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,119,201,117,10 + LTEXT "Quicksearch text:",IDC_STATIC,12,218,65,8 + CONTROL "",IDC_QUICKCOLOUR,"ColourPicker",WS_TABSTOP,77,216,29, + 12 + LTEXT "Size:",IDC_STSIZETEXT,231,114,34,8,NOT WS_VISIBLE + LTEXT "Colour:",IDC_STCOLOURTEXT,228,102,37,8,NOT WS_VISIBLE +END + +IDD_OPT_CLCBKG DIALOGEX 0, 0, 235, 154 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Contact List Background",IDC_STATIC,4,4,227,146 + LTEXT "Background colour",IDC_STATIC,59,35,72,8,NOT WS_GROUP + CONTROL "",IDC_BKGCOLOUR,"ColourPicker",WS_TABSTOP,22,35,32,10 + LTEXT "Selection colour",IDC_STATIC,59,51,72,8 + CONTROL "",IDC_SELCOLOUR,"ColourPicker",WS_TABSTOP,22,51,32,10 + CONTROL "Use background image",IDC_BITMAP,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,12,70,161,10 + EDITTEXT IDC_FILENAME,22,88,184,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BROWSE,208,88,15,11 + CONTROL "Stretch to width",IDC_STRETCHH,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,22,105,100,10 + CONTROL "Stretch to height",IDC_STRETCHV,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,122,105,101,10 + CONTROL "Tile horizontally",IDC_TILEH,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,22,118,100,10 + CONTROL "Tile vertically",IDC_TILEV,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,122,118,101,10 + CONTROL "Scroll with text",IDC_SCROLL,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,22,131,100,10 + CONTROL "Stretch proportionally",IDC_PROPORTIONAL,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,122,131,101,10 + CONTROL "Use Windows colours",IDC_WINCOLOUR,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,12,20,156,10 +END + +IDD_OPT_SBAR DIALOGEX 0, 0, 178, 212 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Status Bar",IDC_STATIC,4,4,170,204 + CONTROL "Show status bar",IDC_SHOWSBAR,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,12,17,152,10 + CONTROL "Show icons",IDC_SHOWICON,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,22,33,142,10 + CONTROL "Show protocol names",IDC_SHOWPROTO,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,48,142,10 + CONTROL "Show status text",IDC_SHOWSTATUS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,63,142,10 + CONTROL "Right click opens status menu",IDC_RIGHTSTATUS,"Button", + BS_AUTORADIOBUTTON,22,160,142,10 + CONTROL "Right click opens Miranda IM menu",IDC_RIGHTMIRANDA, + "Button",BS_AUTORADIOBUTTON,22,147,142,10 + CONTROL "Make sections equal width",IDC_EQUALSECTIONS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,78,142,10 + CONTROL "Show bevels on panels",IDC_SBPANELBEVEL,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,94,107,10 + CONTROL "Show resize grip indicator",IDC_SHOWGRIP,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,110,96,10 +END + +IDD_OPT_CLCTEXTSIMPLE DIALOGEX 0, 0, 277, 240 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Fonts",IDC_STATIC,4,4,269,125 + COMBOBOX IDC_FONTID,12,17,253,87,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "as:",IDC_STASTEXT,25,34,52,10,SS_CENTERIMAGE + COMBOBOX IDC_SAMEAS,77,33,163,88,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + CONTROL "",IDC_STHORZBAR,"Static",SS_ETCHEDHORZ,9,51,259,1 + COMBOBOX IDC_TYPEFACE,12,58,172,182,CBS_DROPDOWN | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_SCRIPT,192,58,73,68,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "Size:",IDC_STSIZETEXT,33,76,34,8 + COMBOBOX IDC_FONTSIZE,67,74,54,69,CBS_DROPDOWN | WS_VSCROLL | + WS_TABSTOP + LTEXT "Colour:",IDC_STCOLOURTEXT,147,76,37,8 + CONTROL "",IDC_COLOUR,"ColourPicker",WS_TABSTOP,184,74,59,12 + CONTROL "Bold",IDC_BOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,58, + 90,45,10 + CONTROL "Italic",IDC_ITALIC,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,117,90,52,10 + CONTROL "Underline",IDC_UNDERLINE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,179,90,66,10 + EDITTEXT IDC_SAMPLE,63,104,151,16,ES_CENTER | ES_READONLY | NOT + WS_TABSTOP + GROUPBOX "Rows",IDC_STATIC,4,134,269,31 + LTEXT "Row height:",IDC_STATIC,12,148,65,8 + EDITTEXT IDC_ROWHEIGHT,77,146,31,12,ES_RIGHT | ES_NUMBER + CONTROL "Spin1",IDC_ROWHEIGHTSPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,97,145,10, + 14 + LTEXT "pixels",IDC_STATIC,112,148,62,8 + GROUPBOX "Additional Colours",IDC_STATIC,4,171,269,65 + LTEXT "Selected text:",IDC_STATIC,12,186,65,8 + CONTROL "",IDC_SELCOLOUR,"ColourPicker",WS_TABSTOP,77,184,29,12 + LTEXT "Hottrack text:",IDC_STATIC,12,202,65,8 + CONTROL "",IDC_HOTCOLOUR,"ColourPicker",WS_TABSTOP,77,200,29,12 + LTEXT "Quicksearch text:",IDC_STATIC,12,218,65,8 + CONTROL "",IDC_QUICKCOLOUR,"ColourPicker",WS_TABSTOP,77,216,29, + 12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DELETECONTACT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 277 + TOPMARGIN, 7 + BOTTOMMARGIN, 85 + END + + IDD_OPT_HOTKEY, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 234 + TOPMARGIN, 4 + BOTTOMMARGIN, 132 + HORZGUIDE, 23 + HORZGUIDE, 40 + HORZGUIDE, 57 + END + + IDD_OPT_CLIST, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 312 + VERTGUIDE, 10 + VERTGUIDE, 107 + TOPMARGIN, 2 + BOTTOMMARGIN, 202 + HORZGUIDE, 179 + HORZGUIDE, 196 + END + + IDD_OPT_CLUI, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 309 + VERTGUIDE, 13 + VERTGUIDE, 23 + VERTGUIDE, 112 + VERTGUIDE, 141 + VERTGUIDE, 151 + VERTGUIDE, 175 + VERTGUIDE, 242 + VERTGUIDE, 246 + TOPMARGIN, 4 + BOTTOMMARGIN, 241 + HORZGUIDE, 18 + HORZGUIDE, 39 + HORZGUIDE, 75 + HORZGUIDE, 180 + HORZGUIDE, 196 + END + + IDD_OPT_CLC, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 312 + VERTGUIDE, 11 + VERTGUIDE, 164 + VERTGUIDE, 216 + TOPMARGIN, 2 + BOTTOMMARGIN, 249 + HORZGUIDE, 145 + HORZGUIDE, 163 + HORZGUIDE, 222 + END + + IDD_OPT_CLCTEXT, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 273 + VERTGUIDE, 12 + VERTGUIDE, 19 + VERTGUIDE, 77 + VERTGUIDE, 258 + VERTGUIDE, 265 + TOPMARGIN, 4 + BOTTOMMARGIN, 236 + HORZGUIDE, 37 + HORZGUIDE, 51 + HORZGUIDE, 79 + HORZGUIDE, 94 + HORZGUIDE, 152 + HORZGUIDE, 190 + HORZGUIDE, 206 + HORZGUIDE, 222 + END + + IDD_OPT_CLCBKG, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 231 + VERTGUIDE, 12 + VERTGUIDE, 22 + VERTGUIDE, 122 + TOPMARGIN, 4 + BOTTOMMARGIN, 150 + HORZGUIDE, 24 + HORZGUIDE, 35 + HORZGUIDE, 73 + HORZGUIDE, 89 + HORZGUIDE, 102 + HORZGUIDE, 115 + END + + IDD_OPT_SBAR, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 174 + VERTGUIDE, 12 + VERTGUIDE, 22 + VERTGUIDE, 164 + TOPMARGIN, 4 + BOTTOMMARGIN, 208 + END + + IDD_OPT_CLCTEXTSIMPLE, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 273 + VERTGUIDE, 12 + VERTGUIDE, 19 + VERTGUIDE, 77 + VERTGUIDE, 258 + VERTGUIDE, 265 + TOPMARGIN, 4 + BOTTOMMARGIN, 236 + HORZGUIDE, 37 + HORZGUIDE, 64 + HORZGUIDE, 80 + HORZGUIDE, 95 + HORZGUIDE, 152 + HORZGUIDE, 190 + HORZGUIDE, 206 + HORZGUIDE, 222 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include \r\n" + "#include \r\n" + "#include \r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_RENAME ICON "res\\rename.ico" +IDI_BLANK ICON "res\\blank.ico" +IDI_DELETE ICON "res\\delete.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_HYPERLINKHAND CURSOR "res\\hyperlin.cur" +IDC_DROP CURSOR "res\\dragcopy.cur" +IDC_DROPUSER CURSOR "res\\dropuser.cur" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_CLISTMENU MENU +BEGIN + POPUP "&¤" + BEGIN + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_ICQ_EXIT + END + POPUP "&Status" + BEGIN + MENUITEM "&Offline\tCtrl+0", ID_STATUS_OFFLINE, CHECKED + MENUITEM "On&line\tCtrl+1", ID_STATUS_ONLINE + MENUITEM "&Away\tCtrl+2", ID_STATUS_AWAY + MENUITEM "&NA\tCtrl+3", ID_STATUS_NA + MENUITEM "Occ&upied\tCtrl+4", ID_STATUS_OCCUPIED + MENUITEM "&DND\tCtrl+5", ID_STATUS_DND + MENUITEM "&Free for chat\tCtrl+6", ID_STATUS_FREECHAT + MENUITEM "&Invisible\tCtrl+7", ID_STATUS_INVISIBLE + MENUITEM "On the &Phone\tCtrl+8", ID_STATUS_ONTHEPHONE + MENUITEM "Out to &Lunch\tCtrl+9", ID_STATUS_OUTTOLUNCH + END +END + +IDR_CONTEXT MENU +BEGIN + POPUP "Tray" + BEGIN + MENUITEM "&Hide/Show", ID_TRAY_HIDE + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_TRAY_EXIT + END + POPUP "Nowhere" + BEGIN + MENUITEM "&New Group", POPUP_NEWGROUP + MENUITEM SEPARATOR + MENUITEM "&Hide Offline Users", POPUP_HIDEOFFLINE + MENUITEM "Hide &Offline Users out here", POPUP_HIDEOFFLINEROOT + MENUITEM "Hide &Empty Groups", POPUP_HIDEEMPTYGROUPS + MENUITEM "Disable &Groups", POPUP_DISABLEGROUPS + MENUITEM SEPARATOR + MENUITEM "Hide Miranda", POPUP_HIDEMIRANDA + END + POPUP "Group" + BEGIN + MENUITEM "&New Subgroup", POPUP_NEWSUBGROUP + MENUITEM "&Hide Offline Users in here", POPUP_GROUPHIDEOFFLINE + MENUITEM SEPARATOR + MENUITEM "&Rename Group", POPUP_RENAMEGROUP + MENUITEM "&Delete Group", POPUP_DELETEGROUP + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/miranda-wine/plugins/db3x/Makefile b/miranda-wine/plugins/db3x/Makefile new file mode 100644 index 0000000..5a75630 --- /dev/null +++ b/miranda-wine/plugins/db3x/Makefile @@ -0,0 +1,53 @@ +SRC = commonheaders.c \ + database.c \ + dbcache.c \ + dbcontacts.c \ + dbevents.c \ + dbheaders.c \ + dbini.c \ + dblists.c \ + dbmodulechain.c \ + dbsettings.c \ + dbtime.c \ + encrypt.c \ + init.c +OBJ = $(SRC:.c=.o) +RES = resource.res +LIB = -lgdi32 -lversion -lcomctl32 -lcomdlg32 -lole32 + +CC = gcc +RC = windres +RM = rm + +# Install location +ifdef DEBUG +BIN = ..\..\bin\debug\plugins\dbx_3x.dll +else +BIN = ..\..\bin\release\plugins\dbx_3x.dll +endif + +# Defines +DEFINES = -DWIN32 -D__SEH_NOOP +ifdef DEBUG +DEFINES := $(DEFINES) -D_DEBUG +endif + +# Flags +LFLAGS = -shared +RCFLAGS = --input-format rc --output-format coff +ifdef DEBUG +CFLAGS = -g $(DEFINES) -I../../include +else +CFLAGS = -O1 $(DEFINES) -I../../include +endif + +# Targets +all : $(OBJ) $(RES) + $(CC) $(LFLAGS) $(CFLAGS) -o $(BIN) $(OBJ) $(RES) $(LIB) -Wl + +$(RES) : $(RES:.res=.rc) $(RES:.res=.h) Makefile + $(RC) $(RCFLAGS) -o $(RES) -i $(RES:.res=.rc) + +clean : + $(RM) -f $(OBJ) $(RES) + diff --git a/miranda-wine/plugins/db3x/commonheaders.c b/miranda-wine/plugins/db3x/commonheaders.c new file mode 100644 index 0000000..14f99f7 --- /dev/null +++ b/miranda-wine/plugins/db3x/commonheaders.c @@ -0,0 +1 @@ +#include "commonheaders.h" diff --git a/miranda-wine/plugins/db3x/commonheaders.h b/miranda-wine/plugins/db3x/commonheaders.h new file mode 100644 index 0000000..c0a8146 --- /dev/null +++ b/miranda-wine/plugins/db3x/commonheaders.h @@ -0,0 +1,66 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#define _WIN32_WINNT 0x0501 +#include + +#include + +#ifdef _DEBUG +# define _ALPHA_BASE_ 1 // defined for CVS builds +# define _ALPHA_FUSE_ 1 // defined for fuse powered core +# define _CRTDBG_MAP_ALLOC +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "resource.h" +#include +#include +#include +#include +#include + +extern PLUGINLINK *pluginLink; + +extern struct MM_INTERFACE memoryManagerInterface; +extern struct LIST_INTERFACE li; + +#define mir_alloc(n) memoryManagerInterface.mmi_malloc(n) +#define mir_free(ptr) memoryManagerInterface.mmi_free(ptr) +#define mir_realloc(ptr,size) memoryManagerInterface.mmi_realloc(ptr,size) + +#ifdef __GNUC__ +#define mir_i64(x) (x##LL) +#else +#define mir_i64(x) (x##i64) +#endif diff --git a/miranda-wine/plugins/db3x/database.c b/miranda-wine/plugins/db3x/database.c new file mode 100644 index 0000000..38843a7 --- /dev/null +++ b/miranda-wine/plugins/db3x/database.c @@ -0,0 +1,186 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ +#include "commonheaders.h" +#include "database.h" + +int ProfileManager(char *szDbDest,int cbDbDest); +int ShouldAutoCreate(void); +int CreateDbHeaders(HANDLE hFile); +int InitialiseDbHeaders(void); +int InitSettings(void); +void UninitSettings(void); +int InitContacts(void); +void UninitContacts(void); +int InitEvents(void); +void UninitEvents(void); +int InitCrypt(void); +int InitTime(void); +int InitModuleNames(void); +void UninitModuleNames(void); +int InitCache(void); +void UninitCache(void); +int InitIni(void); +void UninitIni(void); + +HANDLE hDbFile=INVALID_HANDLE_VALUE; +CRITICAL_SECTION csDbAccess; +struct DBHeader dbHeader; +char szDbPath[MAX_PATH]; + +static void UnloadDatabase(void) +{ + CloseHandle(hDbFile); +} + +DWORD CreateNewSpace(int bytes) +{ + DWORD ofsNew; + + ofsNew=dbHeader.ofsFileEnd; + dbHeader.ofsFileEnd+=bytes; + DBWrite(0,&dbHeader,sizeof(dbHeader)); + log2("newspace %d@%08x",bytes,ofsNew); + return ofsNew; +} + +void DeleteSpace(DWORD ofs,int bytes) +{ + PBYTE buf; + log2("deletespace %d@%08x",bytes,ofs); + dbHeader.slackSpace+=bytes; + DBWrite(0,&dbHeader,sizeof(dbHeader)); + buf=(PBYTE)mir_alloc(bytes); + memset(buf,0,bytes); + DBWrite(ofs,buf,bytes); + mir_free(buf); +} + +void UnloadDatabaseModule(void) +{ + //UninitIni(); + UninitEvents(); + UninitSettings(); + UninitContacts(); + UninitModuleNames(); + UninitCache(); + UnloadDatabase(); + DeleteCriticalSection(&csDbAccess); +} + +static int GetProfileName(WPARAM wParam, LPARAM lParam) +{ + char * p = 0; + p = strrchr(szDbPath, '\\'); + if ( p == 0 ) return 1; + p++; + strncpy((char*)lParam, p, (size_t) wParam); + return 0; +} + +static int GetProfilePath(WPARAM wParam, LPARAM lParam) +{ + char * dst = (char*)lParam; + char * p = 0; + strncpy(dst,szDbPath,wParam); + p = strrchr(dst, '\\'); + if ( p == NULL ) return 1; + *p=0; + return 0; +} + +int LoadDatabaseModule(void) +{ + InitializeCriticalSection(&csDbAccess); + log0("DB logging running"); + { + DWORD dummy=0; + hDbFile=CreateFile(szDbPath,GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL); + if ( hDbFile == INVALID_HANDLE_VALUE ) { + return 1; + } + if ( !ReadFile(hDbFile,&dbHeader,sizeof(dbHeader),&dummy,NULL) ) { + CloseHandle(hDbFile); + return 1; + } + } + //if(ParseCommandLine()) return 1; + if(InitCache()) return 1; + if(InitModuleNames()) return 1; + if(InitContacts()) return 1; + if(InitSettings()) return 1; + if(InitEvents()) return 1; + if(InitCrypt()) return 1; + //if(InitTime()) return 1; + //if(InitIni()) return 1; + CreateServiceFunction(MS_DB_GETPROFILENAME,GetProfileName); + CreateServiceFunction(MS_DB_GETPROFILEPATH,GetProfilePath); + return 0; +} + +static DWORD DatabaseCorrupted=0; + +void __cdecl dbpanic(void *arg) +{ + + MessageBox(0,Translate("Miranda has detected corruption in your database. This corruption maybe fixed by DBTool. Please download it from http://www.miranda-im.org. Miranda will now shutdown."),Translate("Database Panic"),MB_SETFOREGROUND|MB_TOPMOST|MB_APPLMODAL|MB_ICONWARNING|MB_OK); + TerminateProcess(GetCurrentProcess(),255); + return; +} + +void DatabaseCorruption(void) +{ + int kill=0; + + EnterCriticalSection(&csDbAccess); + if (DatabaseCorrupted==0) { + DatabaseCorrupted++; + kill++; + } else { + /* db is already corrupted, someone else is dealing with it, wait here + so that we don't do any more damage */ + LeaveCriticalSection(&csDbAccess); + Sleep(INFINITE); + return; + } + LeaveCriticalSection(&csDbAccess); + if (kill) { + _beginthread(dbpanic,0,NULL); + Sleep(INFINITE); + } +} + +#ifdef DBLOGGING +void DBLog(const char *file,int line,const char *fmt,...) +{ + FILE *fp; + va_list vararg; + char str[1024]; + + va_start(vararg,fmt); + mir_vsnprintf(str,sizeof(str),fmt,vararg); + va_end(vararg); + fp=fopen("c:\\mirandadatabase.log.txt","at"); + fprintf(fp,"%u: %s %d: %s\n",GetTickCount(),file,line,str); + fclose(fp); +} +#endif diff --git a/miranda-wine/plugins/db3x/database.h b/miranda-wine/plugins/db3x/database.h new file mode 100644 index 0000000..d2a6a8f --- /dev/null +++ b/miranda-wine/plugins/db3x/database.h @@ -0,0 +1,218 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + + +//all offsets are relative to the start of the file +//offsets are 0 if there is nothing in the chain or this is the last in the +//chain + +/* tree diagram + +DBHeader + |-->end of file (plain offset) + |-->first contact (DBContact) + | |-->next contact (DBContact) + | | \--> ... + | |-->first settings (DBContactSettings) + | | |-->next settings (DBContactSettings) + | | | \--> ... + | | \-->module name (DBModuleName) + | \-->first/last/firstunread event + |-->user contact (DBContact) + | |-->next contact=NULL + | |-->first settings as above + | \-->first/last/firstunread event as above + \-->first module name (DBModuleName) + \-->next module name (DBModuleName) + \--> ... +*/ + +#define DB_RESIZE_GRANULARITY 16384 +#define DB_THIS_VERSION 0x00000700u +#define DB_SETTINGS_RESIZE_GRANULARITY 128 + +#include +struct DBHeader { + BYTE signature[16]; // 'Miranda ICQ DB',0,26 + DWORD version; //as 4 bytes, ie 1.2.3.10=0x0102030a + //this version is 0x00000700 + DWORD ofsFileEnd; //offset of the end of the database - place to write + //new structures + DWORD slackSpace; //a counter of the number of bytes that have been + //wasted so far due to deleting structures and/or + //re-making them at the end. We should compact when + //this gets above a threshold + DWORD contactCount; //number of contacts in the chain,excluding the user + DWORD ofsFirstContact; //offset to first struct DBContact in the chain + DWORD ofsUser; //offset to struct DBContact representing the user + DWORD ofsFirstModuleName; //offset to first struct DBModuleName in the chain +}; + +#define DBCONTACT_SIGNATURE 0x43DECADEu +struct DBContact { + DWORD signature; + DWORD ofsNext; //offset to the next contact in the chain. zero if + //this is the 'user' contact or the last contact + //in the chain + DWORD ofsFirstSettings; //offset to the first DBContactSettings in the + //chain for this contact. + DWORD eventCount; //number of events in the chain for this contact + DWORD ofsFirstEvent,ofsLastEvent; //offsets to the first and last DBEvent in + //the chain for this contact + DWORD ofsFirstUnreadEvent; //offset to the first (chronological) unread event + //in the chain, 0 if all are read + DWORD timestampFirstUnread; //timestamp of the event at ofsFirstUnreadEvent +}; + +#define DBMODULENAME_SIGNATURE 0x4DDECADEu +struct DBModuleName { + DWORD signature; + DWORD ofsNext; //offset to the next module name in the chain + BYTE cbName; //number of characters in this module name + char name[1]; //name, no nul terminator +}; + +#define DBCONTACTSETTINGS_SIGNATURE 0x53DECADEu +struct DBContactSettings { + DWORD signature; + DWORD ofsNext; //offset to the next contactsettings in the chain + DWORD ofsModuleName; //offset to the DBModuleName of the owner of these + //settings + DWORD cbBlob; //size of the blob in bytes. May be larger than the + //actual size for reducing the number of moves + //required using granularity in resizing + BYTE blob[1]; //the blob. a back-to-back sequence of DBSetting + //structs, the last has cbName=0 +}; + +/* not a valid structure, content is figured out on the fly +struct DBSetting { + BYTE cbName; //number of bytes in the name of this setting + //this =0 marks the end + char szName[...]; //setting name, excluding nul + BYTE dataType; //type of data. see m_database.h, db/contact/getsetting + union { //a load of types of data, length is defined by dataType + BYTE bVal; WORD wVal; DWORD dVal; + struct { + WORD cbString; + char szVal[...]; //excludes nul terminator + }; + struct { + WORD cbBlob; + BYTE blobVal[...]; + }; + }; +}; +*/ + +#define DBEVENT_SIGNATURE 0x45DECADEu +struct DBEvent { + DWORD signature; + DWORD ofsPrev,ofsNext; //offset to the previous and next events in the + //chain. Chain is sorted chronologically + DWORD ofsModuleName; //offset to a DBModuleName struct of the name of + //the owner of this event + DWORD timestamp; //seconds since 00:00:00 01/01/1970 + DWORD flags; //see m_database.h, db/event/add + WORD eventType; //module-defined event type + DWORD cbBlob; //number of bytes in the blob + BYTE blob[1]; //the blob. module-defined formatting +}; +#include + +typedef struct +{ + BYTE bIsResident; + char name[1]; +} + DBCachedSettingName; + +typedef struct +{ + char* name; + DBVARIANT value; +} + DBCachedGlobalValue; + +typedef struct DBCachedContactValue_tag +{ + char* name; + DBVARIANT value; + struct DBCachedContactValue_tag* next; +} + DBCachedContactValue; + +typedef struct +{ + HANDLE hContact; + HANDLE hNext; + DBCachedContactValue* first; +} + DBCachedContactValueList; + + +//databasecorruption: called if any signatures are broken. very very fatal +void DatabaseCorruption(void); +PBYTE DBRead(DWORD ofs,int bytesRequired,int *bytesAvail); //any preview result could be invalidated by the next call +void DBWrite(DWORD ofs,PVOID pData,int count); +void DBFlush(int setting); +void DBMoveChunk(DWORD ofsDest,DWORD ofsSource,int bytes); +DWORD CreateNewSpace(int bytes); +void DeleteSpace(DWORD ofs,int bytes); +void GetProfileDirectory(char *szPath,int cbPath); +int GetDefaultProfilePath(char *szPath,int cbPath,int *specified); +int ShouldShowProfileManager(void); +int CheckDbHeaders(struct DBHeader * hdr); +int CreateDbHeaders(HANDLE hFile); +int LoadDatabaseModule(void); +void UnloadDatabaseModule(void); + +void Utf8Decode( char* str, wchar_t** ucs2 ); +char* Utf8Encode( const char* src ); +char* Utf8EncodeUcs2( const wchar_t* src ); + +#ifdef _DEBUG +#define MAXCACHEDREADSIZE 512 +#else +#define MAXCACHEDREADSIZE 2048 //push it to 1K //technically 4096 would work, but I'm not going to push it +#endif + +#ifdef _DEBUG +//#define DBLOGGING +#endif +#ifdef DBLOGGING +void DBLog(const char *file,int line,const char *fmt,...); +#define logg() DBLog(__FILE__,__LINE__,"") +#define log0(s) DBLog(__FILE__,__LINE__,s) +#define log1(s,a) DBLog(__FILE__,__LINE__,s,a) +#define log2(s,a,b) DBLog(__FILE__,__LINE__,s,a,b) +#define log3(s,a,b,c) DBLog(__FILE__,__LINE__,s,a,b,c) +#define log4(s,a,b,c,d) DBLog(__FILE__,__LINE__,s,a,b,c,d) +#else +#define logg() +#define log0(s) +#define log1(s,a) +#define log2(s,a,b) +#define log3(s,a,b,c) +#define log4(s,a,b,c,d) +#endif diff --git a/miranda-wine/plugins/db3x/dbcache.c b/miranda-wine/plugins/db3x/dbcache.c new file mode 100644 index 0000000..dd3bc5a --- /dev/null +++ b/miranda-wine/plugins/db3x/dbcache.c @@ -0,0 +1,229 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" +#include "database.h" + + +#define CACHESECTIONSIZE 4096 +#define CACHESECTIONCOUNT 32 + +extern HANDLE hDbFile; +extern CRITICAL_SECTION csDbAccess; + +static BOOL safetyMode=TRUE; +static PBYTE pDbCache; +static DWORD lastUseCounter; +struct DBCacheSectionInfo { + DWORD ofsBase; + DWORD lastUsed; +} static cacheSectionInfo[CACHESECTIONCOUNT]; + +static __inline int FindSectionForOffset(const DWORD ofs) +{ + int i; + for(i=0;i=cacheSectionInfo[i].ofsBase && ofs=cacheSectionInfo[i].ofsBase && ofs=cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE) //don't finish at end + CopyMemory(pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,CACHESECTIONSIZE); + else CopyMemory(pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,bytes-(cacheSectionInfo[i].ofsBase-ofs)); + } + else { //start at beginning + if(ofs+bytes>=cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE) //don't finish at end + CopyMemory(pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE-ofs); + else CopyMemory(pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,bytes); + } + } + } +} + +void DBMoveChunk(DWORD ofsDest,DWORD ofsSource,int bytes) +{ + DWORD bytesRead; + PBYTE buf; + + log3("move %d %08x->%08x",bytes,ofsSource,ofsDest); + buf=(PBYTE)mir_alloc(bytes); + SetFilePointer(hDbFile,ofsSource,NULL,FILE_BEGIN); + ReadFile(hDbFile,buf,bytes,&bytesRead,NULL); + DBWrite(ofsDest,buf,bytes); + mir_free(buf); + logg(); +} + +static int flushBuffersTimerId; +static VOID CALLBACK DoBufferFlushTimerProc(HWND hwnd,UINT message,UINT idEvent,DWORD dwTime) +{ + KillTimer(NULL,flushBuffersTimerId); + log0("tflush1"); + FlushFileBuffers(hDbFile); + log0("tflush2"); +} + +void DBFlush(int setting) +{ + if(!setting) { + log0("nflush1"); + if(safetyMode) FlushFileBuffers(hDbFile); + log0("nflush2"); + return; + } + KillTimer(NULL,flushBuffersTimerId); + flushBuffersTimerId=SetTimer(NULL,flushBuffersTimerId,50,DoBufferFlushTimerProc); +} + +static int CacheSetSafetyMode(WPARAM wParam,LPARAM lParam) +{ + EnterCriticalSection(&csDbAccess); + safetyMode=wParam; + LeaveCriticalSection(&csDbAccess); + if(safetyMode) FlushFileBuffers(hDbFile); + return 0; +} + +int InitCache(void) +{ + int i; + DWORD bytesRead; + + CreateServiceFunction(MS_DB_SETSAFETYMODE,CacheSetSafetyMode); + pDbCache=(PBYTE)mir_alloc(CACHESECTIONSIZE*CACHESECTIONCOUNT); + lastUseCounter=CACHESECTIONCOUNT; + for(i=0;ihNext != NULL ) { + LeaveCriticalSection(&csDbAccess); + return (int)VL->hNext; + } } } + + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) + ret=(int)(HANDLE)NULL; + else { + if ( VL == NULL ) { + VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_NO_SERIALIZE+HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList)); + VL->hContact = (HANDLE)wParam; + li.List_Insert(&lContacts,VL,index); + } + VL->hNext = (HANDLE)dbc->ofsNext; + ret=(int)(HANDLE)dbc->ofsNext; + } + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int DeleteContact(WPARAM wParam,LPARAM lParam) +{ + struct DBContact *dbc,*dbcPrev; + DWORD ofsThis,ofsNext,ofsFirstEvent; + struct DBContactSettings *dbcs; + struct DBEvent *dbe; + int index; + + if((HANDLE)wParam==NULL) return 1; + EnterCriticalSection(&csDbAccess); + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + if ( (HANDLE)wParam == (HANDLE)dbHeader.ofsUser ) { + LeaveCriticalSection(&csDbAccess); + log0("FATAL: del of user chain attempted."); + return 1; + } + log0("del contact"); + LeaveCriticalSection(&csDbAccess); + //call notifier while outside mutex + NotifyEventHooks(hContactDeletedEvent,wParam,0); + //get back in + EnterCriticalSection(&csDbAccess); + + { DBCachedContactValueList VLtemp; + VLtemp.hContact = (HANDLE)wParam; + if ( li.List_GetIndex(&lContacts,&VLtemp,&index)) + { + DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index]; + DBCachedContactValue* V = VL->first; + while ( V != NULL ) { + DBCachedContactValue* V1 = V->next; + if ( V->value.type == DBVT_ASCIIZ ) + HeapFree( hCacheHeap, HEAP_NO_SERIALIZE, V->value.pszVal ); + HeapFree( hCacheHeap, HEAP_NO_SERIALIZE, V ); + V = V1; + } + HeapFree( hCacheHeap, HEAP_NO_SERIALIZE, VL ); + + li.List_Remove(&lContacts,index); + } } + + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + //delete settings chain + ofsThis=dbc->ofsFirstSettings; + ofsFirstEvent=dbc->ofsFirstEvent; + while(ofsThis) { + dbcs=(struct DBContactSettings*)DBRead(ofsThis,sizeof(struct DBContactSettings),NULL); + ofsNext=dbcs->ofsNext; + DeleteSpace(ofsThis,offsetof(struct DBContactSettings,blob)+dbcs->cbBlob); + ofsThis=ofsNext; + } + //delete event chain + ofsThis=ofsFirstEvent; + while(ofsThis) { + dbe=(struct DBEvent*)DBRead(ofsThis,sizeof(struct DBEvent),NULL); + ofsNext=dbe->ofsNext; + DeleteSpace(ofsThis,offsetof(struct DBEvent,blob)+dbe->cbBlob); + ofsThis=ofsNext; + } + //find previous contact in chain and change ofsNext + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbHeader.ofsFirstContact==wParam) { + dbHeader.ofsFirstContact=dbc->ofsNext; + DBWrite(0,&dbHeader,sizeof(dbHeader)); + } + else { + ofsNext=dbc->ofsNext; + ofsThis=dbHeader.ofsFirstContact; + dbcPrev=(struct DBContact*)DBRead(ofsThis,sizeof(struct DBContact),NULL); + while(dbcPrev->ofsNext!=wParam) { + if(dbcPrev->ofsNext==0) DatabaseCorruption(); + ofsThis=dbcPrev->ofsNext; + dbcPrev=(struct DBContact*)DBRead(ofsThis,sizeof(struct DBContact),NULL); + } + dbcPrev->ofsNext=ofsNext; + DBWrite(ofsThis,dbcPrev,sizeof(struct DBContact)); + { + DBCachedContactValueList VLtemp; + VLtemp.hContact = (HANDLE)ofsThis; + if ( li.List_GetIndex(&lContacts,&VLtemp,&index)) + { + DBCachedContactValueList *VL = ( DBCachedContactValueList* )lContacts.items[index]; + VL->hNext = ( HANDLE )ofsNext; + } } + } + //delete contact + DeleteSpace(wParam,sizeof(struct DBContact)); + //decrement contact count + dbHeader.contactCount--; + DBWrite(0,&dbHeader,sizeof(dbHeader)); + DBFlush(0); + //quit + LeaveCriticalSection(&csDbAccess); + return 0; +} + +static int AddContact(WPARAM wParam,LPARAM lParam) +{ + struct DBContact dbc; + DWORD ofsNew; + + log0("add contact"); + EnterCriticalSection(&csDbAccess); + ofsNew=CreateNewSpace(sizeof(struct DBContact)); + dbc.signature=DBCONTACT_SIGNATURE; + dbc.eventCount=0; + dbc.ofsFirstEvent=dbc.ofsLastEvent=0; + dbc.ofsFirstSettings=0; + dbc.ofsNext=dbHeader.ofsFirstContact; + dbc.ofsFirstUnreadEvent=0; + dbc.timestampFirstUnread=0; + dbHeader.ofsFirstContact=ofsNew; + dbHeader.contactCount++; + DBWrite(ofsNew,&dbc,sizeof(struct DBContact)); + DBWrite(0,&dbHeader,sizeof(dbHeader)); + DBFlush(0); + + { int index; + + DBCachedContactValueList *VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_NO_SERIALIZE+HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList)); + VL->hContact = (HANDLE)ofsNew; + + li.List_GetIndex(&lContacts,VL,&index); + li.List_Insert(&lContacts,VL,index); + } + + LeaveCriticalSection(&csDbAccess); + NotifyEventHooks(hContactAddedEvent,(WPARAM)ofsNew,0); + return (int)ofsNew; +} + +static int IsDbContact(WPARAM wParam,LPARAM lParam) +{ + struct DBContact dbc; + DWORD ofsContact=(DWORD)wParam; + int ret; + + EnterCriticalSection(&csDbAccess); + { + int index; + DBCachedContactValueList VLtemp,*VL; + VLtemp.hContact = (HANDLE)wParam; + if ( li.List_GetIndex(&lContacts,&VLtemp,&index)) + ret = TRUE; + else { + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + ret=dbc.signature==DBCONTACT_SIGNATURE; + + if (ret) { + VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_NO_SERIALIZE+HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList)); + VL->hContact = (HANDLE)wParam; + li.List_Insert(&lContacts,VL,index); + } } } + + LeaveCriticalSection(&csDbAccess); + return ret; +} diff --git a/miranda-wine/plugins/db3x/dbevents.c b/miranda-wine/plugins/db3x/dbevents.c new file mode 100644 index 0000000..ffc5eed --- /dev/null +++ b/miranda-wine/plugins/db3x/dbevents.c @@ -0,0 +1,436 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" +#include "database.h" + + +DWORD GetModuleNameOfs(const char *szName); +char *GetModuleNameByOfs(DWORD ofs); + +static int GetEventCount(WPARAM wParam,LPARAM lParam); +static int AddEvent(WPARAM wParam,LPARAM lParam); +static int DeleteEvent(WPARAM wParam,LPARAM lParam); +static int GetBlobSize(WPARAM wParam,LPARAM lParam); +static int GetEvent(WPARAM wParam,LPARAM lParam); +static int MarkEventRead(WPARAM wParam,LPARAM lParam); +static int GetEventContact(WPARAM wParam,LPARAM lParam); +static int FindFirstEvent(WPARAM wParam,LPARAM lParam); +static int FindFirstUnreadEvent(WPARAM wParam,LPARAM lParam); +static int FindLastEvent(WPARAM wParam,LPARAM lParam); +static int FindNextEvent(WPARAM wParam,LPARAM lParam); +static int FindPrevEvent(WPARAM wParam,LPARAM lParam); + +extern CRITICAL_SECTION csDbAccess; +extern struct DBHeader dbHeader; + +static HANDLE hEventDeletedEvent,hEventAddedEvent,hEventFilterAddedEvent; + +int InitEvents(void) +{ + CreateServiceFunction(MS_DB_EVENT_GETCOUNT,GetEventCount); + CreateServiceFunction(MS_DB_EVENT_ADD,AddEvent); + CreateServiceFunction(MS_DB_EVENT_DELETE,DeleteEvent); + CreateServiceFunction(MS_DB_EVENT_GETBLOBSIZE,GetBlobSize); + CreateServiceFunction(MS_DB_EVENT_GET,GetEvent); + CreateServiceFunction(MS_DB_EVENT_MARKREAD,MarkEventRead); + CreateServiceFunction(MS_DB_EVENT_GETCONTACT,GetEventContact); + CreateServiceFunction(MS_DB_EVENT_FINDFIRST,FindFirstEvent); + CreateServiceFunction(MS_DB_EVENT_FINDFIRSTUNREAD,FindFirstUnreadEvent); + CreateServiceFunction(MS_DB_EVENT_FINDLAST,FindLastEvent); + CreateServiceFunction(MS_DB_EVENT_FINDNEXT,FindNextEvent); + CreateServiceFunction(MS_DB_EVENT_FINDPREV,FindPrevEvent); + hEventDeletedEvent=CreateHookableEvent(ME_DB_EVENT_DELETED); + hEventAddedEvent=CreateHookableEvent(ME_DB_EVENT_ADDED); + hEventFilterAddedEvent=CreateHookableEvent(ME_DB_EVENT_FILTER_ADD); + return 0; +} + +void UninitEvents(void) +{ +} + +static int GetEventCount(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBContact *dbc; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) ret=-1; + else ret=dbc->eventCount; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int AddEvent(WPARAM wParam,LPARAM lParam) +{ + DBEVENTINFO *dbei=(DBEVENTINFO*)lParam; + struct DBContact dbc; + struct DBEvent dbe,*dbeTest; + DWORD ofsNew,ofsModuleName,ofsContact,ofsThis; + + if(dbei==NULL||dbei->cbSize!=sizeof(DBEVENTINFO)) return (int)NULL; + if(dbei->timestamp==0) return (int)NULL; + if (NotifyEventHooks(hEventFilterAddedEvent,wParam,lParam)) { + return (int)NULL; + } + EnterCriticalSection(&csDbAccess); + if(wParam==0) ofsContact=dbHeader.ofsUser; + else ofsContact=wParam; + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + if(dbc.signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return (int)NULL; + } + ofsNew=CreateNewSpace(offsetof(struct DBEvent,blob)+dbei->cbBlob); + ofsModuleName=GetModuleNameOfs(dbei->szModule); + + dbe.signature=DBEVENT_SIGNATURE; + dbe.ofsModuleName=ofsModuleName; + dbe.timestamp=dbei->timestamp; + dbe.flags=dbei->flags; + dbe.eventType=dbei->eventType; + dbe.cbBlob=dbei->cbBlob; + //find where to put it - sort by timestamp + if(dbc.eventCount==0) { + dbe.ofsPrev=wParam; + dbe.ofsNext=0; + dbe.flags|=DBEF_FIRST; + dbc.ofsFirstEvent=dbc.ofsLastEvent=ofsNew; + } + else { + dbeTest=(struct DBEvent*)DBRead(dbc.ofsFirstEvent,sizeof(struct DBEvent),NULL); + // Should new event be placed before first event in chain? + if (dbei->timestamp < dbeTest->timestamp) { + dbe.ofsPrev=wParam; + dbe.ofsNext=dbc.ofsFirstEvent; + dbe.flags|=DBEF_FIRST; + dbc.ofsFirstEvent=ofsNew; + dbeTest=(struct DBEvent*)DBRead(dbe.ofsNext,sizeof(struct DBEvent),NULL); + dbeTest->flags&=~DBEF_FIRST; + dbeTest->ofsPrev=ofsNew; + DBWrite(dbe.ofsNext,dbeTest,sizeof(struct DBEvent)); + } + else { + // Loop through the chain, starting at the end + ofsThis = dbc.ofsLastEvent; + dbeTest = (struct DBEvent*)DBRead(ofsThis, sizeof(struct DBEvent), NULL); + for(;;) { + // If the new event's timesstamp is equal to or greater than the + // current dbevent, it will be inserted after. If not, continue + // with the previous dbevent in chain. + if (dbe.timestamp >= dbeTest->timestamp) { + dbe.ofsPrev = ofsThis; + dbe.ofsNext = dbeTest->ofsNext; + dbeTest->ofsNext = ofsNew; + DBWrite(ofsThis, dbeTest, sizeof(struct DBEvent)); + if (dbe.ofsNext == 0) + dbc.ofsLastEvent = ofsNew; + else { + dbeTest = (struct DBEvent*)DBRead(dbe.ofsNext, sizeof(struct DBEvent), NULL); + dbeTest->ofsPrev = ofsNew; + DBWrite(dbe.ofsNext, dbeTest, sizeof(struct DBEvent)); + } + break; + } + ofsThis = dbeTest->ofsPrev; + dbeTest = (struct DBEvent*)DBRead(ofsThis, sizeof(struct DBEvent), NULL); + } + } + } + dbc.eventCount++; + if(!(dbe.flags&(DBEF_READ|DBEF_SENT))) { + if(dbe.timestamppBlob,dbei->cbBlob); + DBFlush(0); + LeaveCriticalSection(&csDbAccess); + log1("add event @ %08x",ofsNew); + NotifyEventHooks(hEventAddedEvent,wParam,(LPARAM)ofsNew); + return (int)ofsNew; +} + +static int DeleteEvent(WPARAM wParam,LPARAM lParam) +{ + struct DBContact dbc; + DWORD ofsContact,ofsThis; + struct DBEvent dbe,*dbeNext,*dbePrev; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) ofsContact=dbHeader.ofsUser; + else ofsContact=wParam; + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + dbe=*(struct DBEvent*)DBRead(lParam,sizeof(struct DBEvent),NULL); + if(dbc.signature!=DBCONTACT_SIGNATURE || dbe.signature!=DBEVENT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + log1("delete event @ %08x",wParam); + LeaveCriticalSection(&csDbAccess); + //call notifier while outside mutex + NotifyEventHooks(hEventDeletedEvent,wParam,lParam); + //get back in + EnterCriticalSection(&csDbAccess); + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + dbe=*(struct DBEvent*)DBRead(lParam,sizeof(struct DBEvent),NULL); + //check if this was the first unread, if so, recalc the first unread + if(dbc.ofsFirstUnreadEvent==(DWORD)lParam) { + dbeNext=&dbe; + for(;;) { + if(dbeNext->ofsNext==0) { + dbc.ofsFirstUnreadEvent=0; + dbc.timestampFirstUnread=0; + break; + } + ofsThis=dbeNext->ofsNext; + dbeNext=(struct DBEvent*)DBRead(ofsThis,sizeof(struct DBEvent),NULL); + if(!(dbeNext->flags&(DBEF_READ|DBEF_SENT))) { + dbc.ofsFirstUnreadEvent=ofsThis; + dbc.timestampFirstUnread=dbeNext->timestamp; + break; + } + } + } + //get previous and next events in chain and change offsets + if(dbe.flags&DBEF_FIRST) { + if(dbe.ofsNext==0) { + dbc.ofsFirstEvent=dbc.ofsLastEvent=0; + } + else { + dbeNext=(struct DBEvent*)DBRead(dbe.ofsNext,sizeof(struct DBEvent),NULL); + dbeNext->flags|=DBEF_FIRST; + dbeNext->ofsPrev=dbe.ofsPrev; + DBWrite(dbe.ofsNext,dbeNext,sizeof(struct DBEvent)); + dbc.ofsFirstEvent=dbe.ofsNext; + } + } + else { + if(dbe.ofsNext==0) { + dbePrev=(struct DBEvent*)DBRead(dbe.ofsPrev,sizeof(struct DBEvent),NULL); + dbePrev->ofsNext=0; + DBWrite(dbe.ofsPrev,dbePrev,sizeof(struct DBEvent)); + dbc.ofsLastEvent=dbe.ofsPrev; + } + else { + dbePrev=(struct DBEvent*)DBRead(dbe.ofsPrev,sizeof(struct DBEvent),NULL); + dbePrev->ofsNext=dbe.ofsNext; + DBWrite(dbe.ofsPrev,dbePrev,sizeof(struct DBEvent)); + dbeNext=(struct DBEvent*)DBRead(dbe.ofsNext,sizeof(struct DBEvent),NULL); + dbeNext->ofsPrev=dbe.ofsPrev; + DBWrite(dbe.ofsNext,dbeNext,sizeof(struct DBEvent)); + } + } + //delete event + DeleteSpace(lParam,offsetof(struct DBEvent,blob)+dbe.cbBlob); + //decrement event count + dbc.eventCount--; + DBWrite(ofsContact,&dbc,sizeof(struct DBContact)); + DBFlush(0); + //quit + LeaveCriticalSection(&csDbAccess); + return 0; +} + +static int GetBlobSize(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBEvent *dbe; + + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) ret=-1; + else ret=dbe->cbBlob; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int GetEvent(WPARAM wParam,LPARAM lParam) +{ + struct DBEvent *dbe; + DBEVENTINFO *dbei=(DBEVENTINFO*)lParam; + int bytesToCopy,i; + + if(dbei==NULL||dbei->cbSize!=sizeof(DBEVENTINFO)) return 1; + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + dbei->szModule=GetModuleNameByOfs(dbe->ofsModuleName); + dbei->timestamp=dbe->timestamp; + dbei->flags=dbe->flags; + dbei->eventType=dbe->eventType; + if(dbei->cbBlobcbBlob) bytesToCopy=dbei->cbBlob; + else bytesToCopy=dbe->cbBlob; + dbei->cbBlob=dbe->cbBlob; + for(i=0;;i+=MAXCACHEDREADSIZE) { + if(bytesToCopy-i<=MAXCACHEDREADSIZE) { + CopyMemory(dbei->pBlob+i,DBRead(wParam+offsetof(struct DBEvent,blob)+i,bytesToCopy-i,NULL),bytesToCopy-i); + break; + } + CopyMemory(dbei->pBlob+i,DBRead(wParam+offsetof(struct DBEvent,blob)+i,MAXCACHEDREADSIZE,NULL),MAXCACHEDREADSIZE); + } + LeaveCriticalSection(&csDbAccess); + return 0; +} + +static int MarkEventRead(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBEvent *dbe; + struct DBContact dbc; + DWORD ofsThis; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=*(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + dbe=(struct DBEvent*)DBRead(lParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE || dbc.signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return -1; + } + if(dbe->flags&DBEF_READ || dbe->flags&DBEF_SENT) { + ret=(int)dbe->flags; + LeaveCriticalSection(&csDbAccess); + return ret; + } + log1("mark read @ %08x",wParam); + dbe->flags|=DBEF_READ; + DBWrite(lParam,dbe,sizeof(struct DBEvent)); + ret=(int)dbe->flags; + if(dbc.ofsFirstUnreadEvent==(DWORD)lParam) { + for(;;) { + if(dbe->ofsNext==0) { + dbc.ofsFirstUnreadEvent=0; + dbc.timestampFirstUnread=0; + break; + } + ofsThis=dbe->ofsNext; + dbe=(struct DBEvent*)DBRead(ofsThis,sizeof(struct DBEvent),NULL); + if(!(dbe->flags&(DBEF_READ|DBEF_SENT))) { + dbc.ofsFirstUnreadEvent=ofsThis; + dbc.timestampFirstUnread=dbe->timestamp; + break; + } + } + } + DBWrite(wParam,&dbc,sizeof(struct DBContact)); + DBFlush(0); + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int GetEventContact(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBEvent *dbe; + + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return -1; + } + while(!(dbe->flags&DBEF_FIRST)) + dbe=(struct DBEvent*)DBRead(dbe->ofsPrev,sizeof(struct DBEvent),NULL); + ret=(int)(HANDLE)dbe->ofsPrev; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int FindFirstEvent(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBContact *dbc; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) ret=(int)(HANDLE)NULL; + else ret=(int)dbc->ofsFirstEvent; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int FindFirstUnreadEvent(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBContact *dbc; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) ret=(int)(HANDLE)NULL; + else ret=(int)dbc->ofsFirstUnreadEvent; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int FindLastEvent(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBContact *dbc; + + EnterCriticalSection(&csDbAccess); + if(wParam==0) wParam=dbHeader.ofsUser; + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) ret=(int)(HANDLE)NULL; + else ret=(int)dbc->ofsLastEvent; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int FindNextEvent(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBEvent *dbe; + + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) ret=(int)(HANDLE)NULL; + else ret=(int)(HANDLE)dbe->ofsNext; + LeaveCriticalSection(&csDbAccess); + return ret; +} + +static int FindPrevEvent(WPARAM wParam,LPARAM lParam) +{ + int ret; + struct DBEvent *dbe; + + EnterCriticalSection(&csDbAccess); + dbe=(struct DBEvent*)DBRead(wParam,sizeof(struct DBEvent),NULL); + if(dbe->signature!=DBEVENT_SIGNATURE) ret=(int)(HANDLE)NULL; + else if(dbe->flags&DBEF_FIRST) ret=(int)(HANDLE)NULL; + else ret=(int)(HANDLE)dbe->ofsPrev; + LeaveCriticalSection(&csDbAccess); + return ret; +} diff --git a/miranda-wine/plugins/db3x/dbheaders.c b/miranda-wine/plugins/db3x/dbheaders.c new file mode 100644 index 0000000..da7cb6e --- /dev/null +++ b/miranda-wine/plugins/db3x/dbheaders.c @@ -0,0 +1,78 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" +#include "database.h" + +extern struct DBHeader dbHeader; +extern HANDLE hDbFile; + +struct DBSignature { + char name[15]; + BYTE eof; +}; +static struct DBSignature dbSignature={"Miranda ICQ DB",0x1A}; + +//the cache has not been loaded when these functions are used + +int CreateDbHeaders(HANDLE hFile) +{ + struct DBContact user; + DWORD bytesWritten; + + CopyMemory(dbHeader.signature,&dbSignature,sizeof(dbHeader.signature)); + dbHeader.version=DB_THIS_VERSION; + dbHeader.ofsFileEnd=sizeof(struct DBHeader); + dbHeader.slackSpace=0; + dbHeader.contactCount=0; + dbHeader.ofsFirstContact=0; + dbHeader.ofsFirstModuleName=0; + dbHeader.ofsUser=0; + //create user + dbHeader.ofsUser=dbHeader.ofsFileEnd; + dbHeader.ofsFileEnd+=sizeof(struct DBContact); + SetFilePointer(hFile,0,NULL,FILE_BEGIN); + WriteFile(hFile,&dbHeader,sizeof(dbHeader),&bytesWritten,NULL); + user.signature=DBCONTACT_SIGNATURE; + user.ofsNext=0; + user.ofsFirstSettings=0; + user.eventCount=0; + user.ofsFirstEvent=user.ofsLastEvent=0; + SetFilePointer(hFile,dbHeader.ofsUser,NULL,FILE_BEGIN); + WriteFile(hFile,&user,sizeof(struct DBContact),&bytesWritten,NULL); + FlushFileBuffers(hFile); + return 0; +} + +int CheckDbHeaders(struct DBHeader * hdr) +{ + if(memcmp(hdr->signature,&dbSignature,sizeof(hdr->signature))) return 1; + if(hdr->version!=DB_THIS_VERSION) return 2; + if(hdr->ofsUser==0) return 3; + return 0; +} + +int InitialiseDbHeaders(void) +{ + return 0; +} diff --git a/miranda-wine/plugins/db3x/dbmodulechain.c b/miranda-wine/plugins/db3x/dbmodulechain.c new file mode 100644 index 0000000..352a06c --- /dev/null +++ b/miranda-wine/plugins/db3x/dbmodulechain.c @@ -0,0 +1,132 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" +#include "database.h" + +extern struct DBHeader dbHeader; + +static int EnumModuleNames(WPARAM wParam,LPARAM lParam); + +struct ModuleName { + char *name; + DWORD hash; + DWORD ofs; +}; +static struct ModuleName *moduleName; +static int moduleNameCount; + +int InitModuleNames(void) +{ + struct DBModuleName *dbmn; + DWORD ofsThis,ofsNext; + int nameLen; + + moduleNameCount=0; + moduleName=NULL; + ofsThis=dbHeader.ofsFirstModuleName; + dbmn=(struct DBModuleName*)DBRead(ofsThis,sizeof(struct DBModuleName),NULL); + while(ofsThis) { + if(dbmn->signature!=DBMODULENAME_SIGNATURE) DatabaseCorruption(); + moduleName=(struct ModuleName*)mir_realloc(moduleName,sizeof(struct ModuleName)*(moduleNameCount+1)); + moduleName[moduleNameCount].ofs=ofsThis; + moduleName[moduleNameCount].hash=dbmn->cbName; //very very simple hash so far + moduleName[moduleNameCount].name=(char*)mir_alloc(dbmn->cbName+1); + ofsNext=dbmn->ofsNext; + nameLen=dbmn->cbName; + CopyMemory(moduleName[moduleNameCount].name,DBRead(ofsThis+offsetof(struct DBModuleName,name),nameLen,NULL),nameLen); + moduleName[moduleNameCount].name[nameLen]=0; + moduleNameCount++; + ofsThis=ofsNext; + dbmn=(struct DBModuleName*)DBRead(ofsThis,sizeof(struct DBModuleName),NULL); + } + CreateServiceFunction(MS_DB_MODULES_ENUM,EnumModuleNames); + return 0; +} + +void UninitModuleNames(void) +{ + int i; + for(i=0;iofsFirstSettings; + while(ofsThis) { + dbcs=(struct DBContactSettings*)DBRead(ofsThis,sizeof(struct DBContactSettings),NULL); + if(dbcs->signature!=DBCONTACTSETTINGS_SIGNATURE) DatabaseCorruption(); + if(dbcs->ofsModuleName==ofsModuleName) { + settingsGroupOfsCache[nextSGOCacheEntry].ofsContact=ofsContact; + settingsGroupOfsCache[nextSGOCacheEntry].ofsModuleName=ofsModuleName; + settingsGroupOfsCache[nextSGOCacheEntry].ofsSettingsGroup=ofsThis; + if(++nextSGOCacheEntry==SETTINGSGROUPOFSCOUNT) nextSGOCacheEntry=0; + return ofsThis; + } + ofsThis=dbcs->ofsNext; + } + return 0; +} + +static void InvalidateSettingsGroupOfsCacheEntry(DWORD ofsSettingsGroup) +{ + int i; + + for(i=0;itype == DBVT_UTF8 || d->type == DBVT_ASCIIZ ) ? d->pszVal : NULL; + + memcpy( d, s, sizeof( DBVARIANT )); + if (( s->type == DBVT_UTF8 || s->type == DBVT_ASCIIZ ) && s->pszVal != NULL ) { + if ( szSave != NULL ) + d->pszVal = (char*)HeapReAlloc(hCacheHeap,HEAP_NO_SERIALIZE,szSave,strlen(s->pszVal)+1); + else + d->pszVal = (char*)HeapAlloc(hCacheHeap,HEAP_NO_SERIALIZE,strlen(s->pszVal)+1); + strcpy(d->pszVal,s->pszVal); + } + + switch( d->type ) { + case DBVT_BYTE: log1( "set cached byte: %d", d->bVal ); break; + case DBVT_WORD: log1( "set cached word: %d", d->wVal ); break; + case DBVT_DWORD: log1( "set cached dword: %d", d->dVal ); break; + case DBVT_UTF8: + case DBVT_ASCIIZ: log1( "set cached string: '%s'", d->pszVal ); break; + default: log1( "set cached crap: %d", d->type ); break; +} } + +static void FreeCachedVariant( DBVARIANT* V ) +{ + if (( V->type == DBVT_ASCIIZ || V->type == DBVT_UTF8 ) && V->pszVal != NULL ) + HeapFree(hCacheHeap,HEAP_NO_SERIALIZE,V->pszVal); +} + +static DBVARIANT* GetCachedValuePtr( HANDLE hContact, char* szSetting, int bAllocate ) +{ + int index; + + if ( hContact == 0 ) { + DBCachedGlobalValue Vtemp, *V; + Vtemp.name = szSetting; + if ( li.List_GetIndex(&lGlobalSettings,&Vtemp,&index)) { + V = (DBCachedGlobalValue*)lGlobalSettings.items[index]; + if ( bAllocate == -1 ) { + FreeCachedVariant( &V->value ); + li.List_Remove(&lGlobalSettings,index); + HeapFree(hCacheHeap,HEAP_NO_SERIALIZE,V); + return NULL; + } } + else { + if ( bAllocate != 1 ) + return NULL; + + V = (DBCachedGlobalValue*)HeapAlloc(hCacheHeap,HEAP_NO_SERIALIZE+HEAP_ZERO_MEMORY,sizeof(DBCachedGlobalValue)); + V->name = szSetting; + li.List_Insert(&lGlobalSettings,V,index); + } + + return &V->value; + } + else { + DBCachedContactValue *V, *V1; + DBCachedContactValueList VLtemp,*VL; + + VLtemp.hContact=hContact; + if ( li.List_GetIndex(&lContacts,&VLtemp,&index)) { + VL = (DBCachedContactValueList*)lContacts.items[index]; + } + else { + if ( bAllocate == -1 ) + return NULL; + + VL = (DBCachedContactValueList*)HeapAlloc(hCacheHeap,HEAP_NO_SERIALIZE+HEAP_ZERO_MEMORY,sizeof(DBCachedContactValueList)); + VL->hContact = hContact; + li.List_Insert(&lContacts,VL,index); + } + + for ( V = VL->first; V != NULL; V = V->next) + if (strcmp(V->name,szSetting)==0) + break; + + if ( V == NULL ) + { if ( bAllocate != 1 ) + return NULL; + + V = HeapAlloc(hCacheHeap,HEAP_NO_SERIALIZE+HEAP_ZERO_MEMORY,sizeof(DBCachedContactValue)); + V->next = VL->first; + VL->first = V; + V->name = szSetting; + } + else if ( bAllocate == -1 ) { + FreeCachedVariant(&V->value); + if ( VL->first == V ) + VL->first = V->next; + for ( V1=VL->first; V1 != NULL; V1 = V1->next ) + if ( V1->next == V ) { + V1->next = V->next; + break; + } + HeapFree(hCacheHeap,HEAP_NO_SERIALIZE,V); + return NULL; + } + + return &V->value; +} } + +#define NeedBytes(n) if(bytesRemaining<(n)) pBlob=(PBYTE)DBRead(ofsBlobPtr,(n),&bytesRemaining) +#define MoveAlong(n) {int x=n; pBlob+=(x); ofsBlobPtr+=(x); bytesRemaining-=(x);} +#define VLT(n) ((n==DBVT_UTF8)?DBVT_ASCIIZ:n) +static __inline int GetContactSettingWorker(HANDLE hContact,DBCONTACTGETSETTING *dbcgs,int isStatic) +{ + struct DBContact dbc; + struct DBContactSettings dbcs; + DWORD ofsModuleName,ofsContact,ofsSettingsGroup,ofsBlobPtr; + int settingNameLen; + int bytesRemaining; + PBYTE pBlob; + char* szCachedSettingName; + + if ((!dbcgs->szSetting) || (!dbcgs->szModule)) + return 1; + settingNameLen=strlen(dbcgs->szSetting); + + EnterCriticalSection(&csDbAccess); + + log3("get [%08p] %s/%s",hContact,dbcgs->szModule,dbcgs->szSetting); + + szCachedSettingName = GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,settingNameLen); + { + DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 0 ); + if ( pCachedValue != NULL ) { + if ( pCachedValue->type == DBVT_ASCIIZ || pCachedValue->type == DBVT_UTF8 ) { + int cbOrigLen = dbcgs->pValue->cchVal; + char* cbOrigPtr = dbcgs->pValue->pszVal; + memcpy( dbcgs->pValue, pCachedValue, sizeof( DBVARIANT )); + if ( isStatic ) { + int cbLen = 0; + if ( pCachedValue->pszVal != NULL ) + cbLen = strlen( pCachedValue->pszVal ); + + cbOrigLen--; + dbcgs->pValue->pszVal = cbOrigPtr; + if(cbLenpValue->pszVal,pCachedValue->pszVal,cbOrigLen); + dbcgs->pValue->pszVal[cbOrigLen]=0; + dbcgs->pValue->cchVal=cbLen; + } + else { + dbcgs->pValue->pszVal = (char*)mir_alloc(strlen(pCachedValue->pszVal)+1); + strcpy(dbcgs->pValue->pszVal,pCachedValue->pszVal); + } + } + else + memcpy( dbcgs->pValue, pCachedValue, sizeof( DBVARIANT )); + + switch( dbcgs->pValue->type ) { + case DBVT_BYTE: log1( "get cached byte: %d", dbcgs->pValue->bVal ); break; + case DBVT_WORD: log1( "get cached word: %d", dbcgs->pValue->wVal ); break; + case DBVT_DWORD: log1( "get cached dword: %d", dbcgs->pValue->dVal ); break; + case DBVT_UTF8: + case DBVT_ASCIIZ: log1( "get cached string: '%s'", dbcgs->pValue->pszVal); break; + default: log1( "get cached crap: %d", dbcgs->pValue->type ); break; + } + + LeaveCriticalSection(&csDbAccess); + return ( pCachedValue->type == DBVT_DELETED ) ? 1 : 0; + } } + + ofsModuleName=GetModuleNameOfs(dbcgs->szModule); + if(hContact==NULL) ofsContact=dbHeader.ofsUser; + else ofsContact=(DWORD)hContact; + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + if(dbc.signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + ofsSettingsGroup=GetSettingsGroupOfsByModuleNameOfs(&dbc,ofsContact,ofsModuleName); + if(ofsSettingsGroup) { + dbcs=*(struct DBContactSettings*)DBRead(ofsSettingsGroup,sizeof(struct DBContactSettings),&bytesRemaining); + ofsBlobPtr=ofsSettingsGroup+offsetof(struct DBContactSettings,blob); + pBlob=(PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining); + while(pBlob[0]) { + NeedBytes(1+settingNameLen); + if(pBlob[0]==settingNameLen && !memcmp(pBlob+1,dbcgs->szSetting,settingNameLen)) { + MoveAlong(1+settingNameLen); + NeedBytes(5); + if(isStatic && pBlob[0]&DBVTF_VARIABLELENGTH && VLT(dbcgs->pValue->type) != VLT(pBlob[0])) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + dbcgs->pValue->type=pBlob[0]; + switch(pBlob[0]) { + case DBVT_DELETED: { /* this setting is deleted */ + dbcgs->pValue->type=DBVT_DELETED; + LeaveCriticalSection(&csDbAccess); + return 2; + } + case DBVT_BYTE: dbcgs->pValue->bVal=pBlob[1]; break; + case DBVT_WORD: dbcgs->pValue->wVal=*(PWORD)(pBlob+1); break; + case DBVT_DWORD: dbcgs->pValue->dVal=*(PDWORD)(pBlob+1); break; + case DBVT_UTF8: + case DBVT_ASCIIZ: + NeedBytes(3+*(PWORD)(pBlob+1)); + if(isStatic) { + dbcgs->pValue->cchVal--; + if(*(PWORD)(pBlob+1)pValue->cchVal) dbcgs->pValue->cchVal=*(PWORD)(pBlob+1); + CopyMemory(dbcgs->pValue->pszVal,pBlob+3,dbcgs->pValue->cchVal); + dbcgs->pValue->pszVal[dbcgs->pValue->cchVal]=0; + dbcgs->pValue->cchVal=*(PWORD)(pBlob+1); + } + else { + dbcgs->pValue->pszVal=(char*)mir_alloc(1+*(PWORD)(pBlob+1)); + CopyMemory(dbcgs->pValue->pszVal,pBlob+3,*(PWORD)(pBlob+1)); + dbcgs->pValue->pszVal[*(PWORD)(pBlob+1)]=0; + } + break; + case DBVT_BLOB: + NeedBytes(3+*(PWORD)(pBlob+1)); + if(isStatic) { + if(*(PWORD)(pBlob+1)pValue->cpbVal) dbcgs->pValue->cpbVal=*(PWORD)(pBlob+1); + CopyMemory(dbcgs->pValue->pbVal,pBlob+3,dbcgs->pValue->cchVal); + } + else { + dbcgs->pValue->pbVal=(char*)mir_alloc(*(PWORD)(pBlob+1)); + CopyMemory(dbcgs->pValue->pbVal,pBlob+3,*(PWORD)(pBlob+1)); + } + dbcgs->pValue->cpbVal=*(PWORD)(pBlob+1); + break; + } + + /**** add to cache **********************/ + if ( dbcgs->pValue->type != DBVT_BLOB ) + { + DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 1 ); + if ( pCachedValue != NULL ) + SetCachedVariant(dbcgs->pValue,pCachedValue); + } + + LeaveCriticalSection(&csDbAccess); + logg(); + return 0; + } + NeedBytes(1); + MoveAlong(pBlob[0]+1); + NeedBytes(3); + MoveAlong(1+GetSettingValueLength(pBlob)); + NeedBytes(1); + } } + + /**** add missing setting to cache **********************/ + if ( dbcgs->pValue->type != DBVT_BLOB ) + { + DBVARIANT* pCachedValue = GetCachedValuePtr( hContact, szCachedSettingName, 1 ); + if ( pCachedValue != NULL ) + pCachedValue->type = DBVT_DELETED; + } + + LeaveCriticalSection(&csDbAccess); + logg(); + return 1; +} + +static int GetContactSetting(WPARAM wParam,LPARAM lParam) +{ + DBCONTACTGETSETTING* dgs = ( DBCONTACTGETSETTING* )lParam; + dgs->pValue->type = 0; + if ( GetContactSettingWorker(( HANDLE )wParam, dgs, 0 )) + return 1; + + if ( dgs->pValue->type == DBVT_UTF8 ) { + Utf8Decode( dgs->pValue->pszVal, NULL ); + dgs->pValue->type = DBVT_ASCIIZ; + } + + return 0; +} + +static int GetContactSettingStr(WPARAM wParam,LPARAM lParam) +{ + DBCONTACTGETSETTING* dgs = (DBCONTACTGETSETTING*)lParam; + int iSaveType = dgs->pValue->type; + + if ( GetContactSettingWorker(( HANDLE )wParam, dgs, 0 )) + return 1; + + if ( iSaveType == 0 || iSaveType == dgs->pValue->type ) + return 0; + + if ( dgs->pValue->type != DBVT_ASCIIZ && dgs->pValue->type != DBVT_UTF8 ) + return 0; + + if ( iSaveType == DBVT_WCHAR ) { + if ( dgs->pValue->type != DBVT_UTF8 ) { + int len = MultiByteToWideChar( CP_ACP, 0, dgs->pValue->pszVal, -1, NULL, 0 ); + wchar_t* wszResult = ( wchar_t* )mir_alloc(( len+1 )*sizeof( wchar_t )); + if ( wszResult == NULL ) + return 1; + + MultiByteToWideChar( CP_ACP, 0, dgs->pValue->pszVal, -1, wszResult, len ); + wszResult[ len ] = 0; + mir_free( dgs->pValue->pszVal ); + dgs->pValue->pwszVal = wszResult; + } + else { + char* savePtr = dgs->pValue->pszVal; + Utf8Decode( dgs->pValue->pszVal, &dgs->pValue->pwszVal ); + mir_free( savePtr ); + } + } + else if ( iSaveType == DBVT_UTF8 ) { + char* tmpBuf = Utf8Encode( dgs->pValue->pszVal ); + if ( tmpBuf == NULL ) + return 1; + + mir_free( dgs->pValue->pszVal ); + dgs->pValue->pszVal = tmpBuf; + } + else if ( iSaveType == DBVT_ASCIIZ ) + Utf8Decode( dgs->pValue->pszVal, NULL ); + + dgs->pValue->type = iSaveType; + return 0; +} + +static int GetContactSettingStatic(WPARAM wParam,LPARAM lParam) +{ + DBCONTACTGETSETTING* dgs = (DBCONTACTGETSETTING*)lParam; + if ( GetContactSettingWorker(( HANDLE )wParam, dgs, 1 )) + return 1; + + if ( dgs->pValue->type == DBVT_UTF8 ) { + Utf8Decode( dgs->pValue->pszVal, NULL ); + dgs->pValue->type = DBVT_ASCIIZ; + } + + return 0; +} + +static int FreeVariant(WPARAM wParam,LPARAM lParam) +{ + DBVARIANT *dbv=(DBVARIANT*)lParam; + if ( dbv == 0 ) return 1; + switch ( dbv->type ) { + case DBVT_ASCIIZ: + case DBVT_UTF8: + case DBVT_WCHAR: + { + if ( dbv->pszVal ) mir_free(dbv->pszVal); + dbv->pszVal=0; + break; + } + case DBVT_BLOB: + { + if ( dbv->pbVal ) mir_free(dbv->pbVal); + dbv->pbVal=0; + break; + } + } + dbv->type=0; + return 0; +} + +static int SetSettingResident(WPARAM wParam,LPARAM lParam) +{ + char* szSetting; + size_t cbSettingNameLen = strlen(( char* )lParam ); + int idx; + char* szTemp = ( char* )alloca( cbSettingNameLen+2 ); + strcpy( szTemp+1, ( char* )lParam ); + + EnterCriticalSection(&csDbAccess); + if ( !li.List_GetIndex( &lSettings, szTemp, &idx )) + szSetting = InsertCachedSetting( szTemp, cbSettingNameLen+2, idx ); + else + szSetting = lSettings.items[ idx ]; + + *szSetting = (char)wParam; + + LeaveCriticalSection(&csDbAccess); + return 0; +} + +static int WriteContactSetting(WPARAM wParam,LPARAM lParam) +{ + DBCONTACTWRITESETTING *dbcws=(DBCONTACTWRITESETTING*)lParam; + struct DBContact dbc; + DWORD ofsModuleName; + struct DBContactSettings dbcs; + PBYTE pBlob; + int settingNameLen=0; + int moduleNameLen=0; + int settingDataLen=0; + + int bytesRequired,bytesRemaining; + DWORD ofsContact,ofsSettingsGroup,ofsBlobPtr; + + if (dbcws == NULL) + return 1; + + if (dbcws->value.type == DBVT_WCHAR) { + if (dbcws->value.pszVal != NULL) { + char* val = Utf8EncodeUcs2(dbcws->value.pwszVal); + if ( val == NULL ) + return 1; + + dbcws->value.pszVal = ( char* )alloca( strlen( val )+1 ); + strcpy( dbcws->value.pszVal, val ); + mir_free(val); + dbcws->value.type = DBVT_UTF8; + } + else return 1; + } + + if(dbcws->value.type!=DBVT_BYTE && dbcws->value.type!=DBVT_WORD && dbcws->value.type!=DBVT_DWORD && dbcws->value.type!=DBVT_ASCIIZ && dbcws->value.type!=DBVT_UTF8 && dbcws->value.type!=DBVT_BLOB) + return 1; + if ((!dbcws->szModule) || (!dbcws->szSetting) || ((dbcws->value.type == DBVT_ASCIIZ || dbcws->value.type == DBVT_UTF8 )&& dbcws->value.pszVal == NULL) || (dbcws->value.type == DBVT_BLOB && dbcws->value.pbVal == NULL) ) + return 1; + // the db format can't tolerate more than 255 bytes of space (incl. null) for settings+module name + settingNameLen=strlen(dbcws->szSetting); + moduleNameLen=strlen(dbcws->szModule); + if ( settingNameLen > 0xFE ) + { + #ifdef _DEBUG + OutputDebugString("WriteContactSetting() got a > 255 setting name length. \n"); + #endif + return 1; + } + if ( moduleNameLen > 0xFE ) + { + #ifdef _DEBUG + OutputDebugString("WriteContactSetting() got a > 255 module name length. \n"); + #endif + return 1; + } + + // the db can not tolerate strings/blobs longer than 0xFFFF since the format writes 2 lengths + switch( dbcws->value.type ) { + case DBVT_ASCIIZ: case DBVT_BLOB: case DBVT_UTF8: + { int len = ( dbcws->value.type != DBVT_BLOB ) ? strlen(dbcws->value.pszVal) : dbcws->value.cpbVal; + if ( len >= 0xFFFF ) { + #ifdef _DEBUG + OutputDebugString("WriteContactSetting() writing huge string/blob, rejecting ( >= 0xFFFF ) \n"); + #endif + return 1; + } + } + } + + EnterCriticalSection(&csDbAccess); + { + char* szCachedSettingName = GetCachedSetting(dbcws->szModule, dbcws->szSetting, settingNameLen); + if ( dbcws->value.type != DBVT_BLOB ) { + DBVARIANT* pCachedValue = GetCachedValuePtr((HANDLE)wParam, szCachedSettingName, 1); + if ( pCachedValue != NULL ) { + BOOL bIsIdentical = FALSE; + if ( pCachedValue->type == dbcws->value.type ) { + switch(dbcws->value.type) { + case DBVT_BYTE: bIsIdentical = pCachedValue->bVal == dbcws->value.bVal; break; + case DBVT_WORD: bIsIdentical = pCachedValue->wVal == dbcws->value.wVal; break; + case DBVT_DWORD: bIsIdentical = pCachedValue->dVal == dbcws->value.dVal; break; + case DBVT_UTF8: + case DBVT_ASCIIZ: bIsIdentical = strcmp( pCachedValue->pszVal, dbcws->value.pszVal ) == 0; break; + } + if ( bIsIdentical ) { + LeaveCriticalSection(&csDbAccess); + return 0; + } + } + SetCachedVariant(&dbcws->value, pCachedValue); + } + if ( szCachedSettingName[-1] != 0 ) { + LeaveCriticalSection(&csDbAccess); + NotifyEventHooks(hSettingChangeEvent,wParam,lParam); + return 0; + } + } + else GetCachedValuePtr((HANDLE)wParam, szCachedSettingName, -1); + } + + ofsModuleName=GetModuleNameOfs(dbcws->szModule); + if(wParam==0) ofsContact=dbHeader.ofsUser; + else ofsContact=wParam; + + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + if(dbc.signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + log0("write setting"); + //make sure the module group exists + ofsSettingsGroup=GetSettingsGroupOfsByModuleNameOfs(&dbc,ofsContact,ofsModuleName); + if(ofsSettingsGroup==0) { //module group didn't exist - make it + if(dbcws->value.type&DBVTF_VARIABLELENGTH) { + if(dbcws->value.type==DBVT_ASCIIZ || dbcws->value.type==DBVT_UTF8) bytesRequired=strlen(dbcws->value.pszVal)+2; + else if(dbcws->value.type==DBVT_BLOB) bytesRequired=dbcws->value.cpbVal+2; + } + else bytesRequired=dbcws->value.type; + bytesRequired+=2+settingNameLen; + bytesRequired+=(DB_SETTINGS_RESIZE_GRANULARITY-(bytesRequired%DB_SETTINGS_RESIZE_GRANULARITY))%DB_SETTINGS_RESIZE_GRANULARITY; + ofsSettingsGroup=CreateNewSpace(bytesRequired+offsetof(struct DBContactSettings,blob)); + dbcs.signature=DBCONTACTSETTINGS_SIGNATURE; + dbcs.ofsNext=dbc.ofsFirstSettings; + dbcs.ofsModuleName=ofsModuleName; + dbcs.cbBlob=bytesRequired; + dbcs.blob[0]=0; + dbc.ofsFirstSettings=ofsSettingsGroup; + DBWrite(ofsContact,&dbc,sizeof(struct DBContact)); + DBWrite(ofsSettingsGroup,&dbcs,sizeof(struct DBContactSettings)); + ofsBlobPtr=ofsSettingsGroup+offsetof(struct DBContactSettings,blob); + pBlob=(PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining); + } + else { + dbcs=*(struct DBContactSettings*)DBRead(ofsSettingsGroup,sizeof(struct DBContactSettings),&bytesRemaining); + //find if the setting exists + ofsBlobPtr=ofsSettingsGroup+offsetof(struct DBContactSettings,blob); + pBlob=(PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining); + while(pBlob[0]) { + NeedBytes(settingNameLen+1); + if(pBlob[0]==settingNameLen && !memcmp(pBlob+1,dbcws->szSetting,settingNameLen)) + break; + NeedBytes(1); + MoveAlong(pBlob[0]+1); + NeedBytes(3); + MoveAlong(1+GetSettingValueLength(pBlob)); + NeedBytes(1); + } + if(pBlob[0]) { //setting already existed, and up to end of name is in cache + MoveAlong(1+settingNameLen); + //if different type or variable length and length is different + NeedBytes(3); + if(pBlob[0]!=dbcws->value.type || ((pBlob[0]==DBVT_ASCIIZ || pBlob[0]==DBVT_UTF8) && *(PWORD)(pBlob+1)!=strlen(dbcws->value.pszVal)) || (pBlob[0]==DBVT_BLOB && *(PWORD)(pBlob+1)!=dbcws->value.cpbVal)) { + //bin it + int nameLen,valLen; + DWORD ofsSettingToCut; + NeedBytes(3); + nameLen=1+settingNameLen; + valLen=1+GetSettingValueLength(pBlob); + ofsSettingToCut=ofsBlobPtr-nameLen; + MoveAlong(valLen); + NeedBytes(1); + while(pBlob[0]) { + MoveAlong(pBlob[0]+1); + NeedBytes(3); + MoveAlong(1+GetSettingValueLength(pBlob)); + NeedBytes(1); + } + DBMoveChunk(ofsSettingToCut,ofsSettingToCut+nameLen+valLen,ofsBlobPtr+1-ofsSettingToCut); + ofsBlobPtr-=nameLen+valLen; + pBlob=(PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining); + } + else { + //replace existing setting at pBlob + MoveAlong(1); //skip data type + switch(dbcws->value.type) { + case DBVT_BYTE: DBWrite(ofsBlobPtr,&dbcws->value.bVal,1); break; + case DBVT_WORD: DBWrite(ofsBlobPtr,&dbcws->value.wVal,2); break; + case DBVT_DWORD: DBWrite(ofsBlobPtr,&dbcws->value.dVal,4); break; + case DBVT_UTF8: + case DBVT_ASCIIZ: DBWrite(ofsBlobPtr+2,dbcws->value.pszVal,strlen(dbcws->value.pszVal)); break; + case DBVT_BLOB: DBWrite(ofsBlobPtr+2,dbcws->value.pbVal,dbcws->value.cpbVal); break; + } + //quit + DBFlush(1); + LeaveCriticalSection(&csDbAccess); + //notify + NotifyEventHooks(hSettingChangeEvent,wParam,lParam); + return 0; + } + } + } + //cannot do a simple replace, add setting to end of list + //pBlob already points to end of list + //see if it fits + if(dbcws->value.type&DBVTF_VARIABLELENGTH) { + if(dbcws->value.type==DBVT_ASCIIZ || dbcws->value.type==DBVT_UTF8) bytesRequired=strlen(dbcws->value.pszVal)+2; + else if(dbcws->value.type==DBVT_BLOB) bytesRequired=dbcws->value.cpbVal+2; + } + else bytesRequired=dbcws->value.type; + bytesRequired+=2+settingNameLen; + bytesRequired+=ofsBlobPtr+1-(ofsSettingsGroup+offsetof(struct DBContactSettings,blob)); + if((DWORD)bytesRequired>dbcs.cbBlob) { + //doesn't fit: move entire group + struct DBContactSettings *dbcsPrev; + DWORD ofsDbcsPrev,oldSize,ofsNew; + + InvalidateSettingsGroupOfsCacheEntry(ofsSettingsGroup); + bytesRequired+=(DB_SETTINGS_RESIZE_GRANULARITY-(bytesRequired%DB_SETTINGS_RESIZE_GRANULARITY))%DB_SETTINGS_RESIZE_GRANULARITY; + //find previous group to change its offset + ofsDbcsPrev=dbc.ofsFirstSettings; + if(ofsDbcsPrev==ofsSettingsGroup) ofsDbcsPrev=0; + else { + dbcsPrev=(struct DBContactSettings*)DBRead(ofsDbcsPrev,sizeof(struct DBContactSettings),NULL); + while(dbcsPrev->ofsNext!=ofsSettingsGroup) { + if(dbcsPrev->ofsNext==0) DatabaseCorruption(); + ofsDbcsPrev=dbcsPrev->ofsNext; + dbcsPrev=(struct DBContactSettings*)DBRead(ofsDbcsPrev,sizeof(struct DBContactSettings),NULL); + } + } + //create the new one + ofsNew=CreateNewSpace(bytesRequired+offsetof(struct DBContactSettings,blob)); + //copy across + DBMoveChunk(ofsNew,ofsSettingsGroup,bytesRequired+offsetof(struct DBContactSettings,blob)); + oldSize=dbcs.cbBlob; + dbcs.cbBlob=bytesRequired; + DBWrite(ofsNew,&dbcs,offsetof(struct DBContactSettings,blob)); + if(ofsDbcsPrev==0) { + dbc.ofsFirstSettings=ofsNew; + DBWrite(ofsContact,&dbc,sizeof(struct DBContact)); + } + else { + dbcsPrev=(struct DBContactSettings*)DBRead(ofsDbcsPrev,sizeof(struct DBContactSettings),NULL); + dbcsPrev->ofsNext=ofsNew; + DBWrite(ofsDbcsPrev,dbcsPrev,offsetof(struct DBContactSettings,blob)); + } + DeleteSpace(ofsSettingsGroup,oldSize+offsetof(struct DBContactSettings,blob)); + ofsBlobPtr+=ofsNew-ofsSettingsGroup; + ofsSettingsGroup=ofsNew; + pBlob=(PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining); + } + //we now have a place to put it and enough space: make it + DBWrite(ofsBlobPtr,&settingNameLen,1); + DBWrite(ofsBlobPtr+1,(PVOID)dbcws->szSetting,settingNameLen); + MoveAlong(1+settingNameLen); + DBWrite(ofsBlobPtr,&dbcws->value.type,1); + MoveAlong(1); + switch(dbcws->value.type) { + case DBVT_BYTE: DBWrite(ofsBlobPtr,&dbcws->value.bVal,1); MoveAlong(1); break; + case DBVT_WORD: DBWrite(ofsBlobPtr,&dbcws->value.wVal,2); MoveAlong(2); break; + case DBVT_DWORD: DBWrite(ofsBlobPtr,&dbcws->value.dVal,4); MoveAlong(4); break; + case DBVT_UTF8: + case DBVT_ASCIIZ: + { int len=strlen(dbcws->value.pszVal); + DBWrite(ofsBlobPtr,&len,2); + DBWrite(ofsBlobPtr+2,dbcws->value.pszVal,len); + MoveAlong(2+len); + } + break; + case DBVT_BLOB: + DBWrite(ofsBlobPtr,&dbcws->value.cpbVal,2); + DBWrite(ofsBlobPtr+2,dbcws->value.pbVal,dbcws->value.cpbVal); + MoveAlong(2+dbcws->value.cpbVal); + break; + } + { BYTE zero=0; + DBWrite(ofsBlobPtr,&zero,1); + } + //quit + DBFlush(1); + LeaveCriticalSection(&csDbAccess); + //notify + NotifyEventHooks(hSettingChangeEvent,wParam,lParam); + return 0; +} + +static int DeleteContactSetting(WPARAM wParam,LPARAM lParam) +{ + DBCONTACTGETSETTING *dbcgs=(DBCONTACTGETSETTING*)lParam; + struct DBContact *dbc; + DWORD ofsModuleName,ofsSettingsGroup,ofsBlobPtr; + struct DBContactSettings dbcs; + PBYTE pBlob; + int settingNameLen=strlen(dbcgs->szSetting),bytesRemaining; + char* szCachedSettingName; + WPARAM saveWparam = wParam; + + if ((!dbcgs->szModule) || (!dbcgs->szSetting)) + return 1; + + EnterCriticalSection(&csDbAccess); + ofsModuleName=GetModuleNameOfs(dbcgs->szModule); + if(wParam==0) wParam=dbHeader.ofsUser; + + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + //make sure the module group exists + ofsSettingsGroup=GetSettingsGroupOfsByModuleNameOfs(dbc,wParam,ofsModuleName); + if(ofsSettingsGroup==0) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + dbc=(struct DBContact*)DBRead(wParam,sizeof(struct DBContact),NULL); + if(dbc->signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + ofsSettingsGroup=GetSettingsGroupOfsByModuleNameOfs(dbc,wParam,ofsModuleName); + if(ofsSettingsGroup==0) { + LeaveCriticalSection(&csDbAccess); + return 1; + } + dbcs=*(struct DBContactSettings*)DBRead(ofsSettingsGroup,sizeof(struct DBContactSettings),NULL); + //find if the setting exists + ofsBlobPtr=ofsSettingsGroup+offsetof(struct DBContactSettings,blob); + pBlob=(PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining); + while(pBlob[0]) { + NeedBytes(settingNameLen+1); + if(pBlob[0]==settingNameLen && !memcmp(pBlob+1,dbcgs->szSetting,settingNameLen)) + break; + NeedBytes(1); + MoveAlong(pBlob[0]+1); + NeedBytes(3); + MoveAlong(1+GetSettingValueLength(pBlob)); + NeedBytes(1); + } + if(!pBlob[0]) { //setting didn't exist + LeaveCriticalSection(&csDbAccess); + return 1; + } + { //bin it + int nameLen,valLen; + DWORD ofsSettingToCut; + MoveAlong(1+settingNameLen); + NeedBytes(3); + nameLen=1+settingNameLen; + valLen=1+GetSettingValueLength(pBlob); + ofsSettingToCut=ofsBlobPtr-nameLen; + MoveAlong(valLen); + NeedBytes(1); + while(pBlob[0]) { + MoveAlong(pBlob[0]+1); + NeedBytes(3); + MoveAlong(1+GetSettingValueLength(pBlob)); + NeedBytes(1); + } + DBMoveChunk(ofsSettingToCut,ofsSettingToCut+nameLen+valLen,ofsBlobPtr+1-ofsSettingToCut); + } + + szCachedSettingName = GetCachedSetting(dbcgs->szModule,dbcgs->szSetting,settingNameLen); + GetCachedValuePtr((HANDLE)saveWparam, szCachedSettingName, -1 ); + + //quit + DBFlush(1); + LeaveCriticalSection(&csDbAccess); + { //notify + DBCONTACTWRITESETTING dbcws; + dbcws.szModule=dbcgs->szModule; + dbcws.szSetting=dbcgs->szSetting; + dbcws.value.type=DBVT_DELETED; + NotifyEventHooks(hSettingChangeEvent,saveWparam,(LPARAM)&dbcws); + } + return 0; +} + +static int EnumContactSettings(WPARAM wParam,LPARAM lParam) +{ + DBCONTACTENUMSETTINGS *dbces=(DBCONTACTENUMSETTINGS*)lParam; + struct DBContact dbc; + struct DBContactSettings dbcs; + DWORD ofsModuleName,ofsContact,ofsBlobPtr; + int bytesRemaining, result; + PBYTE pBlob; + char szSetting[256]; + + if (!dbces->szModule) + return -1; + + EnterCriticalSection(&csDbAccess); + + ofsModuleName=GetModuleNameOfs(dbces->szModule); + if(wParam==0) ofsContact=dbHeader.ofsUser; + else ofsContact=wParam; + dbc=*(struct DBContact*)DBRead(ofsContact,sizeof(struct DBContact),NULL); + if(dbc.signature!=DBCONTACT_SIGNATURE) { + LeaveCriticalSection(&csDbAccess); + return -1; + } + dbces->ofsSettings=GetSettingsGroupOfsByModuleNameOfs(&dbc,ofsContact,ofsModuleName); + if(!dbces->ofsSettings) { + LeaveCriticalSection(&csDbAccess); + return -1; + } + dbcs=*(struct DBContactSettings*)DBRead(dbces->ofsSettings,sizeof(struct DBContactSettings),&bytesRemaining); + ofsBlobPtr=dbces->ofsSettings+offsetof(struct DBContactSettings,blob); + pBlob=(PBYTE)DBRead(ofsBlobPtr,1,&bytesRemaining); + if(pBlob[0]==0) { + LeaveCriticalSection(&csDbAccess); + return -1; + } + result = 0; + while(pBlob[0]) { + NeedBytes(1); + NeedBytes(1+pBlob[0]); + CopyMemory(szSetting,pBlob+1,pBlob[0]); szSetting[pBlob[0]]=0; + result = (dbces->pfnEnumProc)(szSetting,dbces->lParam); + MoveAlong(1+pBlob[0]); + NeedBytes(3); + MoveAlong(1+GetSettingValueLength(pBlob)); + NeedBytes(1); + } + LeaveCriticalSection(&csDbAccess); + return result; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// +// Module initialization procedure + +static int stringCompare( DBCachedSettingName* p1, DBCachedSettingName* p2 ) +{ + return strcmp( p1->name, p2->name ); +} + +static int stringCompare2( DBCachedGlobalValue* p1, DBCachedGlobalValue* p2 ) +{ + return strcmp( p1->name, p2->name ); +} + +static int handleCompare( void* p1, void* p2 ) +{ + if ( *( long* )p1 == *( long* )p2 ) + return 0; + + return *( long* )p1 - *( long* )p2; +} + +int InitSettings(void) +{ + CreateServiceFunction(MS_DB_CONTACT_GETSETTING,GetContactSetting); + CreateServiceFunction(MS_DB_CONTACT_GETSETTING_STR,GetContactSettingStr); + CreateServiceFunction(MS_DB_CONTACT_GETSETTINGSTATIC,GetContactSettingStatic); + CreateServiceFunction(MS_DB_CONTACT_FREEVARIANT,FreeVariant); + CreateServiceFunction(MS_DB_CONTACT_WRITESETTING,WriteContactSetting); + CreateServiceFunction(MS_DB_CONTACT_DELETESETTING,DeleteContactSetting); + CreateServiceFunction(MS_DB_CONTACT_ENUMSETTINGS,EnumContactSettings); + CreateServiceFunction(MS_DB_SETSETTINGRESIDENT,SetSettingResident); + hSettingChangeEvent=CreateHookableEvent(ME_DB_CONTACT_SETTINGCHANGED); + + hCacheHeap=HeapCreate(HEAP_NO_SERIALIZE,0,0); + lSettings.sortFunc=stringCompare; + lSettings.increment=50; + lContacts.sortFunc=handleCompare; + lContacts.increment=100; + lGlobalSettings.sortFunc=stringCompare2; + lGlobalSettings.increment=100; + return 0; +} + +void UninitSettings(void) +{ + HeapDestroy(hCacheHeap); + li.List_Destroy(&lContacts); + li.List_Destroy(&lSettings); + li.List_Destroy(&lGlobalSettings); +} diff --git a/miranda-wine/plugins/db3x/dbtime.c b/miranda-wine/plugins/db3x/dbtime.c new file mode 100644 index 0000000..e9189b9 --- /dev/null +++ b/miranda-wine/plugins/db3x/dbtime.c @@ -0,0 +1,163 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" +#include "database.h" + +static int daysInMonth[12]={31,28,31,30,31,30,31,31,30,31,30,31}; +static int IsLeapYear(int year) +{ + if(year&3) return 0; + if(year%100) return 1; + if(year%400) return 0; + return 1; +} + +static int CompareSystemTimes(SYSTEMTIME *st,SYSTEMTIME *switchDate) +{ + FILETIME ft1,ft2; + + if(switchDate->wYear==0) { //strange day-in-month thing + SYSTEMTIME tempst; + + //short-circuit if the months aren't the same + if(st->wMonthwMonth) return -1; + if(st->wMonth>switchDate->wMonth) return 1; + + tempst=*switchDate; + tempst.wYear=st->wYear; + tempst.wDay=1; + SystemTimeToFileTime(&tempst,&ft1); + FileTimeToSystemTime(&ft1,&tempst); //gets the day of week of the first of the month + tempst.wDay=1+(7+switchDate->wDayOfWeek-tempst.wDayOfWeek)%7; + if(switchDate->wDay==5) { //last wDayOfWeek in month + if(tempst.wMonth==2) { + if(IsLeapYear(tempst.wYear)) daysInMonth[1]=29; + else daysInMonth[1]=28; + } + tempst.wDay+=7*3; //can't be less than 4 of that day in the month + if(tempst.wDay+7<=daysInMonth[switchDate->wMonth-1]) tempst.wDay+=7; + } + else tempst.wDay+=7*(switchDate->wDay-1); //nth of month + SystemTimeToFileTime(&tempst,&ft2); + } + else { + switchDate->wYear=st->wYear; + SystemTimeToFileTime(switchDate,&ft2); + } + SystemTimeToFileTime(st,&ft1); + return CompareFileTime(&ft1,&ft2); +} + +static int TimestampToLocal(WPARAM wParam,LPARAM lParam) +{ + TIME_ZONE_INFORMATION tzInfo; + LARGE_INTEGER liFiletime; + FILETIME filetime; + SYSTEMTIME st; + + GetTimeZoneInformation(&tzInfo); + if(tzInfo.StandardDate.wMonth==0) { //no daylight savings time + return (int)(wParam-tzInfo.Bias*60); + } + //this huge number is the difference between 1970 and 1601 in seconds + liFiletime.QuadPart=(mir_i64(11644473600)+(__int64)wParam)*10000000; + filetime.dwHighDateTime=liFiletime.HighPart; + filetime.dwLowDateTime=liFiletime.LowPart; + FileTimeToSystemTime(&filetime,&st); + if(tzInfo.DaylightDate.wMonth0) { + return (int)(wParam-(tzInfo.Bias+tzInfo.StandardBias)*60); + } + return (int)(wParam-(tzInfo.Bias+tzInfo.DaylightBias)*60); + } + else { + //southern hemisphere + if(CompareSystemTimes(&st,&tzInfo.StandardDate)<0 || + CompareSystemTimes(&st,&tzInfo.DaylightDate)>0) { + return (int)(wParam-(tzInfo.Bias+tzInfo.DaylightBias)*60); + } + return (int)(wParam-(tzInfo.Bias+tzInfo.StandardBias)*60); + } + return 0; +} + +static int TimestampToString(WPARAM wParam,LPARAM lParam) +{ + DBTIMETOSTRING *tts=(DBTIMETOSTRING*)lParam; + LARGE_INTEGER liFiletime; + FILETIME filetime; + SYSTEMTIME st; + char dateTimeStr[64]; + char *pDest,*pFormat; + int destCharsLeft,dateTimeStrLen; + + //this huge number is the difference between 1970 and 1601 in seconds + liFiletime.QuadPart=(mir_i64(11644473600)+(__int64)(DWORD)TimestampToLocal(wParam,0))*10000000; + filetime.dwHighDateTime=liFiletime.HighPart; + filetime.dwLowDateTime=liFiletime.LowPart; + FileTimeToSystemTime(&filetime,&st); + destCharsLeft=tts->cbDest; + for(pFormat=tts->szFormat,pDest=tts->szDest;*pFormat;pFormat++) { + switch(*pFormat) { + case 't': + GetTimeFormat(LOCALE_USER_DEFAULT,TIME_NOSECONDS,&st,NULL,dateTimeStr,sizeof(dateTimeStr)); + break; + case 's': + GetTimeFormat(LOCALE_USER_DEFAULT,0,&st,NULL,dateTimeStr,sizeof(dateTimeStr)); + break; + case 'm': + GetTimeFormat(LOCALE_USER_DEFAULT,TIME_NOMINUTESORSECONDS,&st,NULL,dateTimeStr,sizeof(dateTimeStr)); + break; + case 'd': + GetDateFormat(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&st,NULL,dateTimeStr,sizeof(dateTimeStr)); + break; + case 'D': + GetDateFormat(LOCALE_USER_DEFAULT,DATE_LONGDATE,&st,NULL,dateTimeStr,sizeof(dateTimeStr)); + break; + default: + if(destCharsLeft) { + *pDest++=*pFormat; + destCharsLeft--; + } + continue; + } + dateTimeStrLen=strlen(dateTimeStr); + if(destCharsLeftszDest[tts->cbDest-1]=0; + return 0; +} + +int InitTime(void) +{ + CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOLOCAL,TimestampToLocal); + CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOSTRING,TimestampToString); + return 0; +} diff --git a/miranda-wine/plugins/db3x/encrypt.c b/miranda-wine/plugins/db3x/encrypt.c new file mode 100644 index 0000000..1382a27 --- /dev/null +++ b/miranda-wine/plugins/db3x/encrypt.c @@ -0,0 +1,67 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" +#include "database.h" + +//VERY VERY VERY BASIC ENCRYPTION FUNCTION + + +void Encrypt(char*msg,BOOL up) +{ + int i; + int jump; + if (up) + { + jump=5; + } + else + { + jump=-5; + } + + for (i=0;msg[i];i++) + { + msg[i]=msg[i]+jump; + } + +} + +static int EncodeString(WPARAM wParam,LPARAM lParam) +{ + Encrypt((char*)lParam,TRUE); + return 0; +} + +static int DecodeString(WPARAM wParam,LPARAM lParam) +{ + Encrypt((char*)lParam,FALSE); + return 0; +} + +int InitCrypt(void) +{ + CreateServiceFunction(MS_DB_CRYPT_ENCODESTRING,EncodeString); + CreateServiceFunction(MS_DB_CRYPT_DECODESTRING,DecodeString); + return 0; +} diff --git a/miranda-wine/plugins/db3x/encryption.h b/miranda-wine/plugins/db3x/encryption.h new file mode 100644 index 0000000..73c2d7e --- /dev/null +++ b/miranda-wine/plugins/db3x/encryption.h @@ -0,0 +1,23 @@ +/* +Miranda ICQ: the free icq client for MS Windows +Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. +*/ +#ifndef MODULAR +#include + +void Encrypt(char*msg,BOOL up); +#endif \ No newline at end of file diff --git a/miranda-wine/plugins/db3x/init.c b/miranda-wine/plugins/db3x/init.c new file mode 100644 index 0000000..91834ed --- /dev/null +++ b/miranda-wine/plugins/db3x/init.c @@ -0,0 +1,193 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" +#include "database.h" +#include + +struct MM_INTERFACE memoryManagerInterface; +struct LIST_INTERFACE li; +extern char szDbPath[MAX_PATH]; + +HINSTANCE g_hInst=NULL; +PLUGINLINK *pluginLink; + +static int getCapability( int flag ) +{ + return 0; +} + +// returns 0 if the profile is created, EMKPRF* +static int makeDatabase(char * profile, int * error) +{ + HANDLE hFile=CreateFile(profile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + if ( hFile != INVALID_HANDLE_VALUE ) { + CreateDbHeaders(hFile); + CloseHandle(hFile); + return 0; + } + if ( error != NULL ) *error=EMKPRF_CREATEFAILED; + return 1; +} + +// returns 0 if the given profile has a valid header +static int grokHeader( char * profile, int * error ) +{ + int rc=1; + int chk=0; + struct DBHeader hdr; + HANDLE hFile = INVALID_HANDLE_VALUE; + DWORD dummy=0; + + hFile = CreateFile(profile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if ( hFile == INVALID_HANDLE_VALUE ) { + if ( error != NULL ) *error=EGROKPRF_CANTREAD; + return 1; + } + // read the header, which can fail (for various reasons) + if ( !ReadFile(hFile, &hdr, sizeof(struct DBHeader), &dummy, NULL) ) { + if ( error != NULL) *error=EGROKPRF_CANTREAD; + CloseHandle(hFile); + return 1; + } + chk=CheckDbHeaders(&hdr); + if ( chk == 0 ) { + // all the internal tests passed, hurrah + rc=0; + if ( error != NULL ) *error=0; + } else { + // didn't pass at all, or some did. + switch ( chk ) { + case 1: + { + // "Miranda ICQ DB" wasn't present + if ( error != NULL ) *error = EGROKPRF_UNKHEADER; + break; + } + case 2: + { + // header was present, but version information newer + if ( error != NULL ) *error= EGROKPRF_VERNEWER; + break; + } + case 3: + { + // header/version OK, internal data missing + if ( error != NULL ) *error=EGROKPRF_DAMAGED; + break; + } + } // switch + } //if + CloseHandle(hFile); + return rc; +} + +// returns 0 if all the APIs are injected otherwise, 1 +static int LoadDatabase( char * profile, void * plink ) +{ + PLUGINLINK *link = plink; +#ifdef _DEBUG + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + // don't need thread notifications + strncpy(szDbPath, profile, sizeof(szDbPath)); + // this is like Load()'s pluginLink + pluginLink=link; + // set the memory manager + memoryManagerInterface.cbSize=sizeof(struct MM_INTERFACE); + CallService(MS_SYSTEM_GET_MMI,0,(LPARAM)&memoryManagerInterface); + // set the lists manager; + li.cbSize = sizeof( li ); + if ( CallService(MS_SYSTEM_GET_LI,0,(LPARAM)&li) == CALLSERVICE_NOTFOUND ) { + MessageBoxA( NULL, "This version of plugin requires Miranda IM 0.5 or later", "Fatal error", MB_OK ); + return 1; + } + + // inject all APIs and hooks into the core + return LoadDatabaseModule(); +} + +static int UnloadDatabase(int wasLoaded) +{ + if ( !wasLoaded) return 0; + UnloadDatabaseModule(); + return 0; +} + +static int getFriendlyName( char * buf, size_t cch, int shortName ) +{ + strncpy(buf,shortName ? "db3x driver" : "db3x database support",cch); + return 0; +} + + +static DATABASELINK dblink = { + sizeof(DATABASELINK), + getCapability, + getFriendlyName, + makeDatabase, + grokHeader, + LoadDatabase, + UnloadDatabase, +}; + +static PLUGININFO pluginInfo = { + sizeof(PLUGININFO), + "Miranda database driver", + PLUGIN_MAKE_VERSION(0,6,0,0), + "Provides Miranda database support: global settings, contacts, history, settings per contact.", + "Miranda-IM project", + "ghazan@miranda-im.org", + "Copyright 2000-2006 Miranda IM project", + "", + 0, + DEFMOD_DB +}; + + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved) +{ + g_hInst=hInstDLL; + return TRUE; +} + +__declspec(dllexport) DATABASELINK* DatabasePluginInfo(void * reserved) +{ + return &dblink; +} + +__declspec(dllexport) PLUGININFO * MirandaPluginInfo(DWORD mirandaVersion) +{ + if ( mirandaVersion < PLUGIN_MAKE_VERSION(0,4,0,0) ) return NULL; + return &pluginInfo; +} + +int __declspec(dllexport) Load(PLUGINLINK * link) +{ + return 1; +} + +int __declspec(dllexport) Unload(void) +{ + return 0; +} diff --git a/miranda-wine/plugins/db3x/resource.h b/miranda-wine/plugins/db3x/resource.h new file mode 100644 index 0000000..96abbff --- /dev/null +++ b/miranda-wine/plugins/db3x/resource.h @@ -0,0 +1,30 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDC_NOTOALL 3 +#define IDD_INSTALLINI 235 +#define IDD_WARNINICHANGE 236 +#define IDD_INIIMPORTDONE 237 +#define IDC_ININAME 1333 +#define IDC_VIEWINI 1334 +#define IDC_SECURITYINFO 1335 +#define IDC_SETTINGNAME 1336 +#define IDC_NEWVALUE 1337 +#define IDC_WARNNOMORE 1338 +#define IDC_DELETE 1339 +#define IDC_RECYCLE 1340 +#define IDC_NEWNAME 1341 +#define IDC_MOVE 1342 +#define IDC_LEAVE 1343 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 269 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1657 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/miranda-wine/plugins/db3x/resource.rc b/miranda-wine/plugins/db3x/resource.rc new file mode 100644 index 0000000..daa99f3 --- /dev/null +++ b/miranda-wine/plugins/db3x/resource.rc @@ -0,0 +1,169 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_INSTALLINI DIALOGEX 0, 0, 212, 102 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | + WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Install Database Settings" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Yes",IDOK,26,83,50,14 + PUSHBUTTON "No",IDCANCEL,81,83,50,14 + LTEXT "A file containing new database settings has been placed in the Miranda IM directory.", + IDC_STATIC,5,5,202,16 + LTEXT "Do you want to import the settings now?",IDC_STATIC,5, + 69,202,8 + PUSHBUTTON "No to all",IDC_NOTOALL,136,83,50,14 + LTEXT "",IDC_ININAME,5,24,143,16,SS_NOPREFIX | SS_CENTERIMAGE + PUSHBUTTON "&View contents",IDC_VIEWINI,149,25,58,14 + LTEXT "Security systems to prevent malicious changes are in place and you will be warned before changes that are not known to be safe.", + IDC_SECURITYINFO,5,43,202,24 +END + +IDD_WARNINICHANGE DIALOGEX 0, 0, 187, 113 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | + WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Database Setting Change" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "Database settings are being imported from",IDC_STATIC,5, + 5,177,8 + CONTROL "",IDC_ININAME,"Static",SS_SIMPLE | SS_NOPREFIX | + WS_GROUP,5,13,177,8 + LTEXT "This file wishes to change the setting",IDC_STATIC,5,24, + 177,8 + CONTROL "",IDC_SETTINGNAME,"Static",SS_SIMPLE | SS_NOPREFIX | + WS_GROUP,12,33,170,8 + LTEXT "to the value",IDC_STATIC,5,42,177,8 + CONTROL "",IDC_NEWVALUE,"Static",SS_SIMPLE | SS_NOPREFIX | + WS_GROUP,12,51,170,8 + LTEXT "",IDC_SECURITYINFO,5,60,177,8 + LTEXT "Do you want to allow this change?",IDC_STATIC,5,71,177, + 8 + CONTROL "&Allow all further changes to this section", + IDC_WARNNOMORE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13, + 80,169,10 + DEFPUSHBUTTON "&Yes",IDYES,5,94,50,14 + PUSHBUTTON "&No",IDNO,59,94,50,14 + PUSHBUTTON "Cancel Import",IDCANCEL,123,94,59,14 +END + +IDD_INIIMPORTDONE DIALOGEX 0, 0, 186, 73 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | + WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Database Import Complete" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "The import has completed from",IDC_STATIC,5,5,176,8 + CONTROL "",IDC_ININAME,"Static",SS_SIMPLE | SS_NOPREFIX | + WS_GROUP,5,13,176,8 + LTEXT "What do you want to do with the file now?",IDC_STATIC,5, + 24,176,8 + PUSHBUTTON "&Recycle",IDC_RECYCLE,5,36,50,14 + PUSHBUTTON "&Delete",IDC_DELETE,68,36,50,14 + EDITTEXT IDC_NEWNAME,5,55,117,12,ES_AUTOHSCROLL + PUSHBUTTON "&Move/Rename",IDC_MOVE,124,54,57,14 + PUSHBUTTON "&Leave",IDC_LEAVE,131,36,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_INSTALLINI, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 207 + TOPMARGIN, 5 + BOTTOMMARGIN, 97 + END + + IDD_WARNINICHANGE, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 182 + TOPMARGIN, 5 + BOTTOMMARGIN, 108 + END + + IDD_INIIMPORTDONE, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 181 + TOPMARGIN, 5 + BOTTOMMARGIN, 68 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/miranda-wine/plugins/db3x/utf.c b/miranda-wine/plugins/db3x/utf.c new file mode 100644 index 0000000..52064a6 --- /dev/null +++ b/miranda-wine/plugins/db3x/utf.c @@ -0,0 +1,166 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#include "commonheaders.h" +#include "database.h" + +///////////////////////////////////////////////////////////////////////////////////////// +// Utf8Decode - converts UTF8-encoded string to the UCS2/MBCS format + +void Utf8Decode( char* str, wchar_t** ucs2 ) +{ + int len; + wchar_t* tempBuf; + + if ( str == NULL ) + return; + + len = strlen( str ); + if ( len < 2 ) { + if ( ucs2 != NULL ) { + *ucs2 = ( wchar_t* )mir_alloc(( len+1 )*sizeof( wchar_t )); + MultiByteToWideChar( CP_ACP, 0, str, len, *ucs2, len ); + ( *ucs2 )[ len ] = 0; + } + return; + } + + tempBuf = ( wchar_t* )alloca(( len+1 )*sizeof( wchar_t )); + { + wchar_t* d = tempBuf; + BYTE* s = ( BYTE* )str; + + while( *s ) + { + if (( *s & 0x80 ) == 0 ) { + *d++ = *s++; + continue; + } + + if (( s[0] & 0xE0 ) == 0xE0 && ( s[1] & 0xC0 ) == 0x80 && ( s[2] & 0xC0 ) == 0x80 ) { + *d++ = (( WORD )( s[0] & 0x0F) << 12 ) + ( WORD )(( s[1] & 0x3F ) << 6 ) + ( WORD )( s[2] & 0x3F ); + s += 3; + continue; + } + + if (( s[0] & 0xE0 ) == 0xC0 && ( s[1] & 0xC0 ) == 0x80 ) { + *d++ = ( WORD )(( s[0] & 0x1F ) << 6 ) + ( WORD )( s[1] & 0x3F ); + s += 2; + continue; + } + + *d++ = *s++; + } + + *d = 0; + } + + if ( ucs2 != NULL ) { + int fullLen = ( len+1 )*sizeof( wchar_t ); + *ucs2 = ( wchar_t* )mir_alloc( fullLen ); + memcpy( *ucs2, tempBuf, fullLen ); + } + + WideCharToMultiByte( CP_ACP, 0, tempBuf, -1, str, len, NULL, NULL ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Utf8Encode - converts MBCS string to the UTF8-encoded format + +char* Utf8Encode( const char* src ) +{ + int len; + char* result; + wchar_t* tempBuf; + + if ( src == NULL ) + return NULL; + + len = strlen( src ); + result = ( char* )mir_alloc( len*3 + 1 ); + if ( result == NULL ) + return NULL; + + tempBuf = ( wchar_t* )alloca(( len+1 )*sizeof( wchar_t )); + MultiByteToWideChar( CP_ACP, 0, src, -1, tempBuf, len ); + tempBuf[ len ] = 0; + { + wchar_t* s = tempBuf; + BYTE* d = ( BYTE* )result; + + while( *s ) { + int U = *s++; + + if ( U < 0x80 ) { + *d++ = ( BYTE )U; + } + else if ( U < 0x800 ) { + *d++ = 0xC0 + (( U >> 6 ) & 0x3F ); + *d++ = 0x80 + ( U & 0x003F ); + } + else { + *d++ = 0xE0 + ( U >> 12 ); + *d++ = 0x80 + (( U >> 6 ) & 0x3F ); + *d++ = 0x80 + ( U & 0x3F ); + } } + + *d = 0; + } + + return result; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Utf8Encode - converts UCS2 string to the UTF8-encoded format + +char* Utf8EncodeUcs2( const wchar_t* src ) +{ + int len = wcslen( src ); + char* result = ( char* )mir_alloc( len*3 + 1 ); + if ( result == NULL ) + return NULL; + + { const wchar_t* s = src; + BYTE* d = ( BYTE* )result; + + while( *s ) { + int U = *s++; + + if ( U < 0x80 ) { + *d++ = ( BYTE )U; + } + else if ( U < 0x800 ) { + *d++ = 0xC0 + (( U >> 6 ) & 0x3F ); + *d++ = 0x80 + ( U & 0x003F ); + } + else { + *d++ = 0xE0 + ( U >> 12 ); + *d++ = 0x80 + (( U >> 6 ) & 0x3F ); + *d++ = 0x80 + ( U & 0x3F ); + } } + + *d = 0; + } + + return result; +} diff --git a/miranda-wine/plugins/png2dib/m_png.h b/miranda-wine/plugins/png2dib/m_png.h new file mode 100644 index 0000000..cd037ba --- /dev/null +++ b/miranda-wine/plugins/png2dib/m_png.h @@ -0,0 +1,64 @@ +/* +Plugin of Miranda IM for reading/writing PNG images. +Copyright (c) 2004-6 George Hazan (ghazan@postman.ru) + +Portions of this code are gotten from the libpng codebase. +Copyright 2000, Willem van Schaik. For conditions of distribution and +use, see the copyright/license/disclaimer notice in png.h + +Miranda IM: the free icq client for MS Windows +Copyright (C) 2000-2002 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. + +File name : $Source: /cvsroot/miranda/miranda/plugins/png2dib/m_png.h,v $ +Revision : $Revision: 3502 $ +Last change on : $Date: 2006-08-16 01:21:49 +0400 (Срд, 16 Ðвг 2006) $ +Last change by : $Author: ghazan $ + +*/ + +/* Image/Dib2Png +Converts a Device Independent Bitmap to a png stored in memory + wParam=0 + lParam=(WPARAM)(DIB2PNG*)descr +*/ + +typedef struct +{ + BITMAPINFO* pbmi; + BYTE* pDiData; + BYTE* pResult; + long* pResultLen; +} + DIB2PNG; + +#define MS_DIB2PNG "Image/Dib2Png" + +/* Image/Png2Dib +Converts a png stored in memory to a Device Independent Bitmap + wParam=0 + lParam=(WPARAM)(PNG2DIB*)descr +*/ + +typedef struct +{ + BYTE* pSource; + DWORD cbSourceSize; + BITMAPINFOHEADER** pResult; +} + PNG2DIB; + +#define MS_PNG2DIB "Image/Png2Dib" diff --git a/miranda-wine/plugins/png2dib/png2dib.c b/miranda-wine/plugins/png2dib/png2dib.c new file mode 100644 index 0000000..5e531ef --- /dev/null +++ b/miranda-wine/plugins/png2dib/png2dib.c @@ -0,0 +1,411 @@ +/* +Plugin of Miranda IM for reading/writing PNG images. +Copyright (c) 2004-6 George Hazan (ghazan@postman.ru) + +Portions of this code are gotten from the libpng codebase. +Copyright 2000, Willem van Schaik. For conditions of distribution and +use, see the copyright/license/disclaimer notice in png.h + +Miranda IM: the free icq client for MS Windows +Copyright (C) 2000-2002 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. + +File name : $Source: /cvsroot/miranda/miranda/plugins/png2dib/png2dib.c,v $ +Revision : $Revision: 3502 $ +Last change on : $Date: 2006-08-16 01:21:49 +0400 (Срд, 16 Ðвг 2006) $ +Last change by : $Author: ghazan $ + +*/ + +#include +#include +#include +#include +#include + +#include "libpng/png.h" + +#include "newpluginapi.h" +#include "version.h" +#include "m_png.h" + +DWORD __declspec(dllexport) getver( void ) +{ + return __VERSION_DWORD; +} + +// PNG image handler functions + +typedef struct { + char* mBuffer; + size_t mBufSize; + size_t mBufPtr; +} + HMemBufInfo; + +static void png_read_data( png_structp png_ptr, png_bytep data, png_size_t length ) +{ + HMemBufInfo* io = ( HMemBufInfo* )png_ptr->io_ptr; + if ( length + io->mBufPtr > io->mBufSize ) + length = io->mBufSize - io->mBufPtr; + + if ( length > 0 ) { + memcpy( data, io->mBuffer + io->mBufPtr, length ); + io->mBufPtr += length; + } + else png_error(png_ptr, "Read Error"); +} + +static void png_write_data( png_structp png_ptr, png_bytep data, png_size_t length ) +{ + HMemBufInfo* io = ( HMemBufInfo* )png_ptr->io_ptr; + if ( io->mBuffer != NULL ) + memcpy( io->mBuffer + io->mBufPtr, data, length ); + + io->mBufPtr += length; +} + +static void png_flush( png_structp png_ptr ) +{ +} + +/* + * Converting a png image into a bitmap + */ + +BOOL __declspec(dllexport) mempng2dib( + BYTE* pSource, + DWORD cbSourceSize, + BITMAPINFOHEADER** ppDibData ) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + HMemBufInfo sBuffer = { pSource, cbSourceSize, 8 }; + + BOOL bResult = FALSE; + int iWidth; + int iHeight; + png_color pBkgColor; + int iBitDepth; + int iColorType; + double dGamma; + png_color_16* pBackground; + png_uint_32 ulChannels; + png_uint_32 ulRowBytes; + png_byte* pbImageData; + png_byte** ppbRowPointers = NULL; + int i; + int wDIRowBytes; + BYTE* pImageData; + + *ppDibData = NULL; + + if ( pSource == NULL || cbSourceSize == 0 ) + return FALSE; + + if ( !png_check_sig( pSource, 8 )) + return FALSE; + + // create the two png(-info) structures + png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); + if (!png_ptr) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + if ( !info_ptr ) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return FALSE; + } + + // initialize the png structure + png_set_read_fn(png_ptr, (png_voidp)&sBuffer, png_read_data); + png_set_sig_bytes(png_ptr, 8); + + // read all PNG info up to image data + png_read_info(png_ptr, info_ptr); + + // get width, height, bit-depth and color-type + + png_get_IHDR(png_ptr, info_ptr, &iWidth, &iHeight, &iBitDepth, &iColorType, NULL, NULL, NULL); + + // expand images of all color-type and bit-depth to 3x8 bit RGB images + // let the library process things like alpha, transparency, background + + if ( iBitDepth == 16 ) + png_set_strip_16( png_ptr ); + if ( iColorType == PNG_COLOR_TYPE_PALETTE ) + png_set_expand( png_ptr ); + if ( iBitDepth < 8 ) + png_set_expand( png_ptr ); + if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS )) + png_set_expand( png_ptr ); + if ( iColorType == PNG_COLOR_TYPE_GRAY || iColorType == PNG_COLOR_TYPE_GRAY_ALPHA ) + png_set_gray_to_rgb( png_ptr ); + + // set the background color to draw transparent and alpha images over. + if (png_get_bKGD( png_ptr, info_ptr, &pBackground )) { + png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + pBkgColor.red = (byte) pBackground->red; + pBkgColor.green = (byte) pBackground->green; + pBkgColor.blue = (byte) pBackground->blue; + } + + // if required set gamma conversion + if ( png_get_gAMA( png_ptr, info_ptr, &dGamma )) + png_set_gamma( png_ptr, (double) 2.2, dGamma ); + + // after the transformations have been registered update info_ptr data + png_read_update_info(png_ptr, info_ptr); + + // get again width, height and the new bit-depth and color-type + png_get_IHDR(png_ptr, info_ptr, &iWidth, &iHeight, &iBitDepth, &iColorType, NULL, NULL, NULL); + + // row_bytes is the width x number of channels + ulRowBytes = png_get_rowbytes(png_ptr, info_ptr); + ulChannels = png_get_channels(png_ptr, info_ptr); + wDIRowBytes = (WORD) (( ulChannels * iWidth + 3L) >> 2) << 2; + + // now we can allocate memory to store the image + { DWORD cbMemSize = sizeof( BITMAPINFOHEADER ); + cbMemSize += wDIRowBytes * iHeight; + if (( pbImageData = ( png_byte* )GlobalAlloc( LPTR, cbMemSize )) == NULL ) { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return FALSE; + } } + + // initialize the dib-structure + { BITMAPINFOHEADER* pbmih = ( BITMAPINFOHEADER* )pbImageData; + *ppDibData = pbmih; + + pbmih->biSize = sizeof( BITMAPINFOHEADER ); + pbmih->biWidth = iWidth; + pbmih->biHeight = iHeight; + pbmih->biPlanes = 1; + pbmih->biBitCount = ulChannels * 8; + pbmih->biCompression = 0; + pbmih->biSizeImage = iWidth * iHeight * ulChannels; + + pbImageData += sizeof( BITMAPINFOHEADER ); + } + + pImageData = (BYTE*)malloc( ulRowBytes * iHeight ); + if ( pImageData == NULL ) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return FALSE; + } + + // and allocate memory for an array of row-pointers + ppbRowPointers = ( png_bytepp )alloca( iHeight * sizeof( png_bytep )); + + // set the individual row-pointers to point at the correct offsets + for ( i = 0; i < iHeight; i++ ) + ppbRowPointers[i] = ( png_bytep )&pImageData[ i*ulRowBytes ]; + + // now we can go ahead and just read the whole image + png_read_image( png_ptr, ppbRowPointers ); + png_read_end(png_ptr, NULL); + + // repack bytes to fill the bitmap + for ( i = iHeight-1; i >= 0; i-- ) + { + int j; + png_byte a; + png_bytep s = ppbRowPointers[i]; + BYTE* dest = pbImageData; pbImageData += wDIRowBytes; + + for ( j = 0; j < iWidth; j++ ) { + png_byte r = *s++; + png_byte g = *s++; + png_byte b = *s++; + if ( ulChannels == 4 ) + a = *s++; + + *dest++ = b; + *dest++ = g; + *dest++ = r; + if ( ulChannels == 4 ) + *dest++ = a; + } } + + free( pImageData ); + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return TRUE; +} + +/* + * Converting a bitmap into a png image + */ + +BOOL __declspec(dllexport) dib2mempng( BITMAPINFO* pbmi, png_byte* pDiData, BYTE* pResult, long* pResultLen ) +{ + int ciBitDepth = 8; + int ciChannels = pbmi->bmiHeader.biBitCount / 8; + + png_uint_32 ulSrcRowBytes, ulDstRowBytes; + int i; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_bytepp ppbRowPointers; + png_bytep pTempBuffer; + + HMemBufInfo sBuffer = { pResult, 0, 0 }; + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); + if (!png_ptr) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + return FALSE; + } + + // initialize the png structure + png_set_write_fn(png_ptr, (png_voidp)&sBuffer, png_write_data, png_flush); + + png_set_IHDR(png_ptr, info_ptr, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight, ciBitDepth, + PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + // write the file header information + png_write_info(png_ptr, info_ptr); + + // swap the BGR pixels in the DiData structure to RGB + png_set_bgr(png_ptr); + + // row_bytes is the width x number of channels + ulSrcRowBytes = ((( pbmi->bmiHeader.biWidth * ciChannels + 3 ) >> 2 ) << 2 ); + ulDstRowBytes = ((( pbmi->bmiHeader.biWidth * 3 + 3 ) >> 2 ) << 2 ); + + ppbRowPointers = (png_bytepp)alloca( pbmi->bmiHeader.biHeight * sizeof(png_bytep)); + + pTempBuffer = ( png_bytep )malloc( pbmi->bmiHeader.biHeight * ulDstRowBytes ); + if ( pTempBuffer != NULL ) { + png_bytep pDest = pTempBuffer; + for ( i = pbmi->bmiHeader.biHeight-1; i >= 0; i--) { + BYTE *s, *d; + int j; + s = pDiData; pDiData += ulSrcRowBytes; + d = ppbRowPointers[i] = pDest; pDest += ulDstRowBytes; + + if ( ciChannels >= 3 ) { + for ( j = 0; j < pbmi->bmiHeader.biWidth; j++ ) { + png_byte b = *s++; + png_byte g = *s++; + png_byte r = *s++; + png_byte a = 0; + + if ( ciChannels == 4 ) + a = *s++; + + *d++ = b; + *d++ = g; + *d++ = r; + } } + else { + for ( j = 0; j < pbmi->bmiHeader.biWidth; j++ ) { + DWORD point; + if ( ciChannels == 1 ) { + *d++ = ( BYTE )( point & 0x03 ) << 6; + *d++ = ( BYTE )(( point & 0x0C ) >> 2 ) << 6; + *d++ = ( BYTE )(( point & 0x30 ) >> 4 ) << 6; + point = *s++; + } + else { + point = *( WORD* )s; + s += sizeof( WORD ); + *d++ = ( BYTE )(( point & 0x001F ) << 3 ); + *d++ = ( BYTE )((( point & 0x07e0 ) >> 6 ) << 3 ); + *d++ = ( BYTE )((( point & 0xF800 ) >> 11 ) << 3 ); + } } } } + + png_write_image (png_ptr, ppbRowPointers); + png_write_end(png_ptr, info_ptr); + + if ( pResultLen != NULL ) + *pResultLen = sBuffer.mBufPtr; + + free( pTempBuffer ); + } + + png_destroy_write_struct(&png_ptr, &info_ptr ); + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Standard Miranda structures & functions + +HINSTANCE hInst = NULL; +PLUGINLINK *pluginLink; + +static HANDLE hDib2mempng = NULL; +static HANDLE hMempng2Dib = NULL; + +PLUGININFO pluginInfo = { + sizeof( PLUGININFO ), + "PNG images processor", + __VERSION_DWORD, + "png2dib plugin for Miranda IM ( "__DATE__" )", + "George Hazan", + "ghazan@miranda-im.org", + "(c) 2004-06 George Hazan", + "http://addons.miranda-im.org/details.php?action=viewfile&id=1420", + 0, + 0 +}; + +__declspec( dllexport ) PLUGININFO* MirandaPluginInfo( DWORD mirandaVersion ) +{ + if ( mirandaVersion < PLUGIN_MAKE_VERSION( 0,4,3,0 )) { + MessageBox( NULL, "The png2dib plugin cannot be loaded. It requires Miranda IM 0.5 or later.", "png2dib Plugin", MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST ); + return NULL; + } + + return &pluginInfo; +} + +/////////////////////////////////////////////////////////////////////////////// +// Load - initializes the plugin instance + +static int serviceDib2Png( WPARAM wParam, LPARAM lParam ) +{ + DIB2PNG* param = ( DIB2PNG* )lParam; + return dib2mempng( param->pbmi, param->pDiData, param->pResult, param->pResultLen ); +} + +static int servicePng2Dib( WPARAM wParam, LPARAM lParam ) +{ + PNG2DIB* param = ( PNG2DIB* )lParam; + return mempng2dib( param->pSource, param->cbSourceSize, param->pResult ); +} + +int __declspec( dllexport ) Load( PLUGINLINK *link ) +{ + pluginLink = link; + + hDib2mempng = CreateServiceFunction( MS_DIB2PNG, serviceDib2Png ); + hMempng2Dib = CreateServiceFunction( MS_PNG2DIB, servicePng2Dib ); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// Unload - destroys the plugin instance + +int __declspec( dllexport ) Unload( void ) +{ + DestroyServiceFunction( hDib2mempng ); + DestroyServiceFunction( hMempng2Dib ); + return 0; +} diff --git a/miranda-wine/plugins/png2dib/version.h b/miranda-wine/plugins/png2dib/version.h new file mode 100644 index 0000000..d21c408 --- /dev/null +++ b/miranda-wine/plugins/png2dib/version.h @@ -0,0 +1,3 @@ +#define __FILEVERSION_STRING 0,1,3,1 +#define __VERSION_STRING "0.1.3.1" +#define __VERSION_DWORD 0x00010301 diff --git a/miranda-wine/plugins/png2dib/version.rc b/miranda-wine/plugins/png2dib/version.rc new file mode 100644 index 0000000..e9f49ed --- /dev/null +++ b/miranda-wine/plugins/png2dib/version.rc @@ -0,0 +1,36 @@ + +#include +#include "version.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", " " + VALUE "FileDescription", "Miranda png2dib plugin" + VALUE "FileVersion", __VERSION_STRING + VALUE "InternalName", "png2dib" + VALUE "LegalCopyright", "Copyright c 2004-2006 George Hazan" + VALUE "OriginalFilename", "png2dib.dll" + VALUE "ProductName", "Miranda" + VALUE "ProductVersion", __VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/miranda-wine/plugins/srmm/cmdlist.c b/miranda-wine/plugins/srmm/cmdlist.c new file mode 100644 index 0000000..4897751 --- /dev/null +++ b/miranda-wine/plugins/srmm/cmdlist.c @@ -0,0 +1,124 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#include +#include +#include +#include "commonheaders.h" + +static unsigned long tcmdlist_hash(const CMDCHAR *data) { + unsigned long hash = 0; + int i, shift = 0; + + for(i=0; data[i]; i++) { + hash ^= data[i]<24) hash ^= (data[i]>>(32-shift))&0x7F; + shift = (shift+5)&0x1F; + } + return hash; +} + +TCmdList *tcmdlist_append(TCmdList *list, CMDCHAR *data) { + TCmdList *n; + TCmdList *new_list = malloc(sizeof(TCmdList)); + TCmdList *attach_to = NULL; + + if (!data) { + free(new_list); + return list; + } + new_list->next = NULL; +#ifdef _UNICODE + new_list->szCmd = _tcsdup(data); +#else + new_list->szCmd = _strdup(data); +#endif + new_list->hash = tcmdlist_hash(data); + for (n=list; n!=NULL; n=n->next) { + attach_to = n; + } + if (attach_to==NULL) { + new_list->prev = NULL; + return new_list; + } + else { + new_list->prev = attach_to; + attach_to->next = new_list; + if (tcmdlist_len(list)>20) { + list = tcmdlist_remove(list, list->szCmd); + } + return list; + } +} + +TCmdList *tcmdlist_remove(TCmdList *list, CMDCHAR *data) { + TCmdList *n; + unsigned long hash; + + if (!data) return list; + hash = tcmdlist_hash(data); + for (n=list; n!=NULL; n=n->next) { +#ifdef _UNICODE + if (n->hash==hash&&!_tcscmp(n->szCmd, data)) { +#else + if (n->hash==hash&&!strcmp(n->szCmd, data)) { +#endif + if (n->next) n->next->prev = n->prev; + if (n->prev) n->prev->next = n->next; + if (n==list) list = n->next; + free(n->szCmd); + free(n); + return list; + } + } + return list; +} + +int tcmdlist_len(TCmdList *list) { + TCmdList *n; + int i = 0; + + for (n=list; n!=NULL; n=n->next) { + i++; + } + return i; +} + +TCmdList *tcmdlist_last(TCmdList *list) { + TCmdList *n; + + for (n=list; n!=NULL; n=n->next) { + if (!n->next) + return n; + } + return NULL; +} + +void tcmdlist_free(TCmdList *list) { + TCmdList *n = list, *next; + + while (n!=NULL) { + next = n->next; + free(n->szCmd); + free(n); + n = next; + } +} diff --git a/miranda-wine/plugins/srmm/cmdlist.h b/miranda-wine/plugins/srmm/cmdlist.h new file mode 100644 index 0000000..54b057a --- /dev/null +++ b/miranda-wine/plugins/srmm/cmdlist.h @@ -0,0 +1,48 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#ifndef SRMM_CMDLIST_H +#define SRMM_CMDLIST_H + +#ifdef _UNICODE + #define CMDCHAR TCHAR +#else + #define CMDCHAR char +#endif + +typedef struct _TCmdList { + struct _TCmdList *next; + struct _TCmdList *prev; +#ifdef _UNICODE + wchar_t *szCmd; +#else + char *szCmd; +#endif + unsigned long hash; +} TCmdList; + +TCmdList *tcmdlist_append(TCmdList *list, CMDCHAR *data); +TCmdList *tcmdlist_remove(TCmdList *list, CMDCHAR *data); +int tcmdlist_len(TCmdList *list); +TCmdList *tcmdlist_last(TCmdList *list); +void tcmdlist_free(TCmdList * list); + +#endif diff --git a/miranda-wine/plugins/srmm/commonheaders.h b/miranda-wine/plugins/srmm/commonheaders.h new file mode 100644 index 0000000..4236248 --- /dev/null +++ b/miranda-wine/plugins/srmm/commonheaders.h @@ -0,0 +1,57 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ + +#if defined(UNICODE) && !defined(_UNICODE) + #define _UNICODE +#endif +#include +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include +#include +#include +#include "resource.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cmdlist.h" +#include "msgs.h" +#include "globals.h" +#include "richutil.h" diff --git a/miranda-wine/plugins/srmm/globals.c b/miranda-wine/plugins/srmm/globals.c new file mode 100644 index 0000000..3247e1a --- /dev/null +++ b/miranda-wine/plugins/srmm/globals.c @@ -0,0 +1,107 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#include "commonheaders.h" + +struct GlobalMessageData *g_dat=NULL; +extern HINSTANCE g_hInst; +static HANDLE g_hDbEvent = 0, g_hAck = 0; +static int dbaddedevent(WPARAM wParam, LPARAM lParam); +static int ackevent(WPARAM wParam, LPARAM lParam); + +void InitGlobals() { + g_dat = (struct GlobalMessageData *)malloc(sizeof(struct GlobalMessageData)); + g_dat->hMessageWindowList = (HANDLE) CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + g_hDbEvent = HookEvent(ME_DB_EVENT_ADDED, dbaddedevent); + g_hAck = HookEvent(ME_PROTO_ACK, ackevent); + ReloadGlobals(); + g_dat->hIcons[SMF_ICON_ADD] = (HICON) LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ADDCONTACT), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); + g_dat->hIcons[SMF_ICON_USERDETAIL] = (HICON) LoadImage(g_hInst, MAKEINTRESOURCE(IDI_USERDETAILS), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); + g_dat->hIcons[SMF_ICON_HISTORY] = (HICON) LoadImage(g_hInst, MAKEINTRESOURCE(IDI_HISTORY), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); + g_dat->hIcons[SMF_ICON_ARROW] = (HICON) LoadImage(g_hInst, MAKEINTRESOURCE(IDI_DOWNARROW), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); + g_dat->hIcons[SMF_ICON_TYPING] = (HICON) LoadImage(g_hInst, MAKEINTRESOURCE(IDI_TYPING), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); +} + +void FreeGlobals() { + int i; + + if (g_dat) { + for (i=0; i < SIZEOF(g_dat->hIcons); i++) + DestroyIcon(g_dat->hIcons[i]); + free(g_dat); + } + if (g_hDbEvent) UnhookEvent(g_hDbEvent); + if (g_hAck) UnhookEvent(g_hAck); +} + +void ReloadGlobals() { + g_dat->flags = 0; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWINFOLINE, SRMSGDEFSET_SHOWINFOLINE)) + g_dat->flags |= SMF_SHOWINFO; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWBUTTONLINE, SRMSGDEFSET_SHOWBUTTONLINE)) + g_dat->flags |= SMF_SHOWBTNS; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDBUTTON, SRMSGDEFSET_SENDBUTTON)) + g_dat->flags |= SMF_SENDBTN; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, SRMSGDEFSET_SHOWTYPING)) + g_dat->flags |= SMF_SHOWTYPING; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, SRMSGDEFSET_SHOWTYPINGWIN)) + g_dat->flags |= SMF_SHOWTYPINGWIN; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, SRMSGDEFSET_SHOWTYPINGNOWIN)) + g_dat->flags |= SMF_SHOWTYPINGTRAY; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)) + g_dat->flags |= SMF_SHOWTYPINGCLIST; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS)) + g_dat->flags |= SMF_SHOWICONS; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME)) + g_dat->flags |= SMF_SHOWTIME; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AVATARENABLE, SRMSGDEFSET_AVATARENABLE)) + g_dat->flags |= SMF_AVATAR; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE)) + g_dat->flags |= SMF_SHOWDATE; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, SRMSGDEFSET_SHOWSECS)) + g_dat->flags |= SMF_SHOWSECS; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES)) + g_dat->flags |= SMF_HIDENAMES; + g_dat->openFlags = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, SRMSGDEFSET_POPFLAGS); +} + +static int dbaddedevent(WPARAM wParam, LPARAM lParam) { + if (wParam) { + HWND h = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)wParam); + if(h) SendMessage(h, HM_DBEVENTADDED, wParam, lParam); + } + return 0; +} + +static int ackevent(WPARAM wParam, LPARAM lParam) { + ACKDATA *pAck = (ACKDATA *)lParam; + + if (!pAck) return 0; + else if (pAck->type==ACKTYPE_AVATAR) { + HWND h = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)pAck->hContact); + if(h) SendMessage(h, HM_AVATARACK, wParam, lParam); + } + else if (pAck->type==ACKTYPE_MESSAGE) { + HWND h = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)pAck->hContact); + if(h) SendMessage(h, HM_EVENTSENT, wParam, lParam); + } + return 0; +} diff --git a/miranda-wine/plugins/srmm/globals.h b/miranda-wine/plugins/srmm/globals.h new file mode 100644 index 0000000..12723fa --- /dev/null +++ b/miranda-wine/plugins/srmm/globals.h @@ -0,0 +1,59 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#ifndef SRMM_GLOBALS_H +#define SRMM_GLOBALS_H + +#define SMF_SHOWINFO 0x00000001 +#define SMF_SHOWBTNS 0x00000002 +#define SMF_SENDBTN 0x00000004 +#define SMF_SHOWTYPING 0x00000008 +#define SMF_SHOWTYPINGWIN 0x00000010 +#define SMF_SHOWTYPINGTRAY 0x00000020 +#define SMF_SHOWTYPINGCLIST 0x00000040 +#define SMF_SHOWICONS 0x00000080 +#define SMF_SHOWTIME 0x00000100 +#define SMF_AVATAR 0x00000200 +#define SMF_SHOWDATE 0x00000400 +#define SMF_HIDENAMES 0x00000800 +#define SMF_SHOWSECS 0x00001000 + +#define SMF_ICON_ADD 0 +#define SMF_ICON_USERDETAIL 1 +#define SMF_ICON_HISTORY 2 +#define SMF_ICON_ARROW 3 +#define SMF_ICON_TYPING 4 + +struct GlobalMessageData +{ + unsigned int flags; + HICON hIcons[5]; + HANDLE hMessageWindowList; + DWORD openFlags; +}; + +void InitGlobals(); +void FreeGlobals(); +void ReloadGlobals(); + +extern struct GlobalMessageData *g_dat; + +#endif diff --git a/miranda-wine/plugins/srmm/msgdialog.c b/miranda-wine/plugins/srmm/msgdialog.c new file mode 100644 index 0000000..0d8085e --- /dev/null +++ b/miranda-wine/plugins/srmm/msgdialog.c @@ -0,0 +1,1859 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ + +#define _USE_32BIT_TIME_T + +#include "commonheaders.h" +#pragma hdrstop + +#include + +#define TIMERID_MSGSEND 0 +#define TIMERID_FLASHWND 1 +#define TIMERID_TYPE 2 +#define TIMEOUT_FLASHWND 900 +#define TIMEOUT_TYPEOFF 10000 //send type off after 10 seconds of inactivity +#define SB_CHAR_WIDTH 45; +#define VALID_AVATAR(x) (x==PA_FORMAT_PNG||x==PA_FORMAT_JPEG||x==PA_FORMAT_ICON||x==PA_FORMAT_BMP||x==PA_FORMAT_GIF) + +#if defined(_UNICODE) + #define SEND_FLAGS PREF_UNICODE +#else + #define SEND_FLAGS 0 +#endif + +extern HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand; +extern HANDLE hHookWinEvt; +extern struct CREOleCallback reOleCallback; +extern HINSTANCE g_hInst; + +static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus); + +static WNDPROC OldMessageEditProc, OldSplitterProc; +static const UINT infoLineControls[] = { IDC_PROTOCOL, IDC_NAME }; +static const UINT buttonLineControls[] = { IDC_ADD, IDC_USERMENU, IDC_DETAILS, IDC_HISTORY }; +static const UINT sendControls[] = { IDC_MESSAGE }; + +static void NotifyLocalWinEvent(HANDLE hContact, HWND hwnd, unsigned int type) { + MessageWindowEventData mwe = { 0 }; + + if (hContact==NULL || hwnd==NULL) return; + mwe.cbSize = sizeof(mwe); + mwe.hContact = hContact; + mwe.hwndWindow = hwnd; + mwe.szModule = SRMMMOD; + mwe.uType = type; + mwe.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH; + NotifyEventHooks(hHookWinEvt, 0, (LPARAM)&mwe); +} + +static char *MsgServiceName(HANDLE hContact) +{ +#ifdef _UNICODE + char szServiceName[100]; + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto == NULL) + return PSS_MESSAGE; + + mir_snprintf(szServiceName, SIZEOF(szServiceName), "%s%sW", szProto, PSS_MESSAGE); + if (ServiceExists(szServiceName)) + return PSS_MESSAGE "W"; +#endif + return PSS_MESSAGE; +} + +#if defined(_UNICODE) +static int RTL_Detect(WCHAR *pszwText) +{ + WORD *infoTypeC2; + int i; + int iLen = lstrlenW(pszwText); + + infoTypeC2 = (WORD *)malloc(sizeof(WORD) * (iLen + 2)); + + if(infoTypeC2) { + ZeroMemory(infoTypeC2, sizeof(WORD) * (iLen + 2)); + + GetStringTypeW(CT_CTYPE2, pszwText, iLen, infoTypeC2); + + for(i = 0; i < iLen; i++) { + if(infoTypeC2[i] == C2_RIGHTTOLEFT) { + free(infoTypeC2); + //_DebugTraceA("RTL text found"); + return 1; + } + } + free(infoTypeC2); + //_DebugTraceA("NO RTL text detected"); + } + return 0; +} +#endif + +// mod from tabsrmm +static void AddToFileList(char ***pppFiles,int *totalCount,const char *szFilename) { + *pppFiles=(char**)realloc(*pppFiles,(++*totalCount+1)*sizeof(char*)); + (*pppFiles)[*totalCount]=NULL; + (*pppFiles)[*totalCount-1]=_strdup(szFilename); + if(GetFileAttributesA(szFilename)&FILE_ATTRIBUTE_DIRECTORY) { + WIN32_FIND_DATAA fd; + HANDLE hFind; + char szPath[MAX_PATH]; + lstrcpyA(szPath,szFilename); + lstrcatA(szPath,"\\*"); + if(hFind=FindFirstFileA(szPath,&fd)) { + do { + if(!lstrcmpA(fd.cFileName,".") || !lstrcmpA(fd.cFileName,"..")) continue; + lstrcpyA(szPath,szFilename); + lstrcatA(szPath,"\\"); + lstrcatA(szPath,fd.cFileName); + AddToFileList(pppFiles,totalCount,szPath); + } while(FindNextFileA(hFind,&fd)); + FindClose(hFind); + } + } +} + +static void ShowMultipleControls(HWND hwndDlg, const UINT * controls, int cControls, int state) +{ + int i; + for (i = 0; i < cControls; i++) + ShowWindow(GetDlgItem(hwndDlg, controls[i]), state); +} + +static void SetDialogToType(HWND hwndDlg) +{ + struct MessageWindowData *dat; + WINDOWPLACEMENT pl = { 0 }; + + dat = (struct MessageWindowData *) GetWindowLong(hwndDlg, GWL_USERDATA); + if (dat->hContact) { + ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), (g_dat->flags&SMF_SHOWINFO) ? SW_SHOW : SW_HIDE); + } + else + ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), SW_HIDE); + if (dat->hContact) { + ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), (g_dat->flags&SMF_SHOWBTNS) ? SW_SHOW : SW_HIDE); + if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE); + } + else { + ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), SW_HIDE); + } + ShowMultipleControls(hwndDlg, sendControls, SIZEOF(sendControls), SW_SHOW); + if (!dat->hwndStatus) { + dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL); + SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0); + } + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT)) { + RECT rc; + int statwidths[2]; + + GetWindowRect(dat->hwndStatus, &rc); + statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH; + statwidths[1] = -1; + SendMessage(dat->hwndStatus, SB_SETPARTS, 2, (LPARAM) statwidths); + } + else { + int statwidths[] = { -1 }; + + SendMessage(dat->hwndStatus, SB_SETPARTS, 1, (LPARAM) statwidths); + } + UpdateReadChars(hwndDlg, dat->hwndStatus); + ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SPLITTER), SW_SHOW); + ShowWindow(GetDlgItem(hwndDlg, IDOK), (g_dat->flags&SMF_SENDBTN) ? SW_SHOW : SW_HIDE); + EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE))?TRUE:FALSE); + if (dat->avatarPic==0||!(g_dat->flags&SMF_AVATAR)) + ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE); + SendMessage(hwndDlg, DM_UPDATETITLE, 0, 0); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + pl.length = sizeof(pl); + GetWindowPlacement(hwndDlg, &pl); + if (!IsWindowVisible(hwndDlg)) + pl.showCmd = SW_HIDE; + SetWindowPlacement(hwndDlg, &pl); //in case size is smaller than new minimum +} + +struct SavedMessageData +{ + UINT message; + WPARAM wParam; + LPARAM lParam; + DWORD keyStates; //use MOD_ defines from RegisterHotKey() +}; + +struct MsgEditSubclassData +{ + DWORD lastEnterTime; + struct SavedMessageData *keyboardMsgQueue; + int msgQueueCount; +}; + +static void SaveKeyboardMessage(struct MsgEditSubclassData *dat, UINT message, WPARAM wParam, LPARAM lParam) +{ + dat->keyboardMsgQueue = (struct SavedMessageData *) realloc(dat->keyboardMsgQueue, sizeof(struct SavedMessageData) * (dat->msgQueueCount + 1)); + dat->keyboardMsgQueue[dat->msgQueueCount].message = message; + dat->keyboardMsgQueue[dat->msgQueueCount].wParam = wParam; + dat->keyboardMsgQueue[dat->msgQueueCount].lParam = lParam; + dat->keyboardMsgQueue[dat->msgQueueCount].keyStates = (GetKeyState(VK_SHIFT) & 0x8000 ? MOD_SHIFT : 0) | (GetKeyState(VK_CONTROL) & 0x8000 ? MOD_CONTROL : 0) | (GetKeyState(VK_MENU) & 0x8000 ? MOD_ALT : 0); + dat->msgQueueCount++; +} + +#define EM_REPLAYSAVEDKEYSTROKES (WM_USER+0x100) +#define EM_SUBCLASSED (WM_USER+0x101) +#define EM_UNSUBCLASSED (WM_USER+0x102) +#define ENTERCLICKTIME 1000 //max time in ms during which a double-tap on enter will cause a send +#define EDITMSGQUEUE_PASSTHRUCLIPBOARD //if set the typing queue won't capture ctrl-C etc because people might want to use them on the read only text + //todo: decide if this should be set or not +static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct MsgEditSubclassData *dat; + struct MessageWindowData *pdat; + + pdat=(struct MessageWindowData *)GetWindowLong(GetParent(hwnd),GWL_USERDATA); + dat = (struct MsgEditSubclassData *) GetWindowLong(hwnd, GWL_USERDATA); + switch (msg) { + case WM_DROPFILES: + SendMessage(GetParent(hwnd), WM_DROPFILES, (WPARAM)wParam, (LPARAM)lParam); + break; + case EM_SUBCLASSED: + dat = (struct MsgEditSubclassData *) malloc(sizeof(struct MsgEditSubclassData)); + SetWindowLong(hwnd, GWL_USERDATA, (LONG) dat); + dat->lastEnterTime = 0; + dat->keyboardMsgQueue = NULL; + dat->msgQueueCount = 0; + return 0; + case EM_SETREADONLY: + if (wParam) { + if (dat->keyboardMsgQueue) + free(dat->keyboardMsgQueue); + dat->keyboardMsgQueue = NULL; + dat->msgQueueCount = 0; + } + break; + case EM_REPLAYSAVEDKEYSTROKES: + { + int i; + BYTE keyStateArray[256], originalKeyStateArray[256]; + MSG msg; + + while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + GetKeyboardState(originalKeyStateArray); + GetKeyboardState(keyStateArray); + for (i = 0; i < dat->msgQueueCount; i++) { + keyStateArray[VK_SHIFT] = dat->keyboardMsgQueue[i].keyStates & MOD_SHIFT ? 0x80 : 0; + keyStateArray[VK_CONTROL] = dat->keyboardMsgQueue[i].keyStates & MOD_CONTROL ? 0x80 : 0; + keyStateArray[VK_MENU] = dat->keyboardMsgQueue[i].keyStates & MOD_ALT ? 0x80 : 0; + SetKeyboardState(keyStateArray); + PostMessage(hwnd, dat->keyboardMsgQueue[i].message, dat->keyboardMsgQueue[i].wParam, dat->keyboardMsgQueue[i].lParam); + while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + if (dat->keyboardMsgQueue) + free(dat->keyboardMsgQueue); + dat->keyboardMsgQueue = NULL; + dat->msgQueueCount = 0; + SetKeyboardState(originalKeyStateArray); + return 0; + } + case WM_CHAR: + if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY) + break; + //for saved msg queue the keyup/keydowns generate wm_chars themselves + if (wParam == '\n' || wParam == '\r') { + if (((GetKeyState(VK_CONTROL) & 0x8000) != 0) ^ (0 != DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER))) { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)) { + if (dat->lastEnterTime + ENTERCLICKTIME < GetTickCount()) + dat->lastEnterTime = GetTickCount(); + else { + SendMessage(hwnd, WM_CHAR, '\b', 0); + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + } + } + else + dat->lastEnterTime = 0; + if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-a + SendMessage(hwnd, EM_SETSEL, 0, -1); + return 0; + } + if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w + SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return 0; + } + if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-backspace + DWORD start, end; + TCHAR *text; + int textLen; + SendMessage(hwnd, EM_GETSEL, (WPARAM) & end, (LPARAM) (PDWORD) NULL); + SendMessage(hwnd, WM_KEYDOWN, VK_LEFT, 0); + SendMessage(hwnd, EM_GETSEL, (WPARAM) & start, (LPARAM) (PDWORD) NULL); + textLen = GetWindowTextLength(hwnd); + text = (TCHAR *) malloc(sizeof(TCHAR) * (textLen + 1)); + GetWindowText(hwnd, text, textLen + 1); + MoveMemory(text + start, text + end, sizeof(TCHAR) * (textLen + 1 - end)); + SetWindowText(hwnd, text); + free(text); + SendMessage(hwnd, EM_SETSEL, start, start); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd); + return 0; + } + break; + case WM_KEYUP: + if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY) { + int i; + //mustn't allow keyups for which there is no keydown + for (i = 0; i < dat->msgQueueCount; i++) + if (dat->keyboardMsgQueue[i].message == WM_KEYDOWN && dat->keyboardMsgQueue[i].wParam == wParam) + break; + if (i == dat->msgQueueCount) + break; + #ifdef EDITMSGQUEUE_PASSTHRUCLIPBOARD + if (GetKeyState(VK_CONTROL) & 0x8000) { + if (wParam == 'X' || wParam == 'C' || wParam == 'V' || wParam == VK_INSERT) + break; + } + if (GetKeyState(VK_SHIFT) & 0x8000) { + if (wParam == VK_INSERT || wParam == VK_DELETE) + break; + } + #endif + SaveKeyboardMessage(dat, msg, wParam, lParam); + return 0; + } + break; + case WM_KEYDOWN: + if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY) { + #ifdef EDITMSGQUEUE_PASSTHRUCLIPBOARD + if (GetKeyState(VK_CONTROL) & 0x8000) { + if (wParam == 'X' || wParam == 'C' || wParam == 'V' || wParam == VK_INSERT) + break; + } + if (GetKeyState(VK_SHIFT) & 0x8000) { + if (wParam == VK_INSERT || wParam == VK_DELETE) + break; + } + #endif + SaveKeyboardMessage(dat, msg, wParam, lParam); + return 0; + } + if (wParam == VK_UP && (GetKeyState(VK_CONTROL) & 0x8000) && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT) && !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)) { + if (pdat->cmdList) { + if (!pdat->cmdListCurrent) { + pdat->cmdListCurrent = tcmdlist_last(pdat->cmdList); + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + SetWindowText(hwnd, pdat->cmdListCurrent->szCmd); + SendMessage(hwnd, EM_SCROLLCARET, 0,0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + SendMessage(hwnd, EM_SETSEL, 0, -1); + } + else if (pdat->cmdListCurrent->prev) { + pdat->cmdListCurrent = pdat->cmdListCurrent->prev; + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + SetWindowText(hwnd, pdat->cmdListCurrent->szCmd); + SendMessage(hwnd, EM_SCROLLCARET, 0,0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + SendMessage(hwnd, EM_SETSEL, 0, -1); + } + } + EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(GetDlgItem(GetParent(hwnd), IDC_MESSAGE)) != 0); + UpdateReadChars(GetParent(hwnd), pdat->hwndStatus); + } + else if (wParam == VK_DOWN && (GetKeyState(VK_CONTROL) & 0x8000) && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT) && !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)) { + if (pdat->cmdList) { + if (!pdat->cmdListCurrent) + pdat->cmdListCurrent = tcmdlist_last(pdat->cmdList); + if (pdat->cmdListCurrent->next) { + pdat->cmdListCurrent = pdat->cmdListCurrent->next; + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + SetWindowText(hwnd, pdat->cmdListCurrent->szCmd); + SendMessage(hwnd, EM_SCROLLCARET, 0,0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + SendMessage(hwnd, EM_SETSEL, 0, -1); + } + else { + pdat->cmdListCurrent = 0; + SetWindowTextA(hwnd, ""); + } + } + EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(GetDlgItem(GetParent(hwnd), IDC_MESSAGE)) != 0); + UpdateReadChars(GetParent(hwnd), pdat->hwndStatus); + } + if (wParam == VK_RETURN) + break; + //fall through + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_MOUSEWHEEL: + case WM_KILLFOCUS: + dat->lastEnterTime = 0; + break; + case WM_SYSCHAR: + dat->lastEnterTime = 0; + if ((wParam == 's' || wParam == 'S') && GetKeyState(VK_MENU) & 0x8000) { + if (GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY) + SaveKeyboardMessage(dat, msg, wParam, lParam); + else + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + break; + case EM_UNSUBCLASSED: + if (dat->keyboardMsgQueue) + free(dat->keyboardMsgQueue); + free(dat); + return 0; + } + return CallWindowProc(OldMessageEditProc, hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_NCHITTEST: + return HTCLIENT; + case WM_SETCURSOR: + { + RECT rc; + GetClientRect(hwnd, &rc); + SetCursor(rc.right > rc.bottom ? hCurSplitNS : hCurSplitWE); + return TRUE; + } + case WM_LBUTTONDOWN: + SetCapture(hwnd); + return 0; + case WM_MOUSEMOVE: + if (GetCapture() == hwnd) { + RECT rc; + GetClientRect(hwnd, &rc); + SendMessage(GetParent(hwnd), DM_SPLITTERMOVED, rc.right > rc.bottom ? (short) HIWORD(GetMessagePos()) + rc.bottom / 2 : (short) LOWORD(GetMessagePos()) + rc.right / 2, (LPARAM) hwnd); + } + return 0; + case WM_LBUTTONUP: + ReleaseCapture(); + return 0; + } + return CallWindowProc(OldSplitterProc, hwnd, msg, wParam, lParam); +} + +static int MessageDialogResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL * urc) +{ + struct MessageWindowData *dat = (struct MessageWindowData *) lParam; + + if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS)) { + int i; + for (i = 0; i < SIZEOF(buttonLineControls); i++) + if (buttonLineControls[i] == urc->wId) + OffsetRect(&urc->rcItem, 0, -dat->lineHeight); + } + switch (urc->wId) { + case IDC_NAME: + { + int len; + HWND h; + + h = GetDlgItem(hwndDlg, IDC_NAME); + len = GetWindowTextLength(h); + if (len > 0) { + HDC hdc; + SIZE textSize; + TCHAR buf[256]; + HFONT hFont; + + GetWindowText(h, buf, SIZEOF(buf)); + + hdc = GetDC(h); + hFont = SelectObject(hdc, (HFONT) SendMessage(GetDlgItem(hwndDlg, IDOK), WM_GETFONT, 0, 0)); + GetTextExtentPoint32(hdc, buf, lstrlen(buf), &textSize); + urc->rcItem.right = urc->rcItem.left + textSize.cx + 10; + if ((g_dat->flags&SMF_SHOWBTNS) && urc->rcItem.right > urc->dlgNewSize.cx - dat->nLabelRight) + urc->rcItem.right = urc->dlgNewSize.cx - dat->nLabelRight; + SelectObject(hdc, hFont); + ReleaseDC(h, hdc); + } + } + case IDC_PROTOCOL: + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; + case IDC_ADD: + case IDC_USERMENU: + case IDC_DETAILS: + case IDC_HISTORY: + return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP; + case IDC_LOG: + if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS)) + urc->rcItem.top -= dat->lineHeight; + urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos; + return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + case IDC_SPLITTER: + urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; + urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos; + return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; + case IDC_MESSAGE: + { + if (!(g_dat->flags&SMF_SENDBTN)) + urc->rcItem.right = urc->dlgNewSize.cx - urc->rcItem.left; + if ((g_dat->flags&SMF_AVATAR)&&dat->avatarPic) { + urc->rcItem.left = dat->avatarWidth+4; + } + urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; + if (!(g_dat->flags&SMF_SENDBTN)) + return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM; + return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; + } + case IDCANCEL: + case IDOK: + urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; + return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; + case IDC_AVATAR: + urc->rcItem.top=urc->rcItem.bottom-(dat->avatarHeight + 2); + urc->rcItem.right=urc->rcItem.left+(dat->avatarWidth + 2); + return RD_ANCHORX_LEFT|RD_ANCHORY_BOTTOM; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; +} + +static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus) +{ + if (hwndStatus && SendMessage(hwndStatus, SB_GETPARTS, 0, 0) == 2) { + TCHAR buf[128]; + int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); + + mir_sntprintf(buf, SIZEOF(buf), _T("%d"), len); + SendMessage(hwndStatus, SB_SETTEXT, 1, (LPARAM) buf); + } +} + +void ShowAvatar(HWND hwndDlg, struct MessageWindowData *dat) { + DBVARIANT dbv; + + if (dat->avatarPic) { + DeleteObject(dat->avatarPic); + dat->avatarPic=0; + } + if (!DBGetContactSetting(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, &dbv)) { + if(dbv.pszVal) { + HANDLE hFile; + + hFile = CreateFileA(dbv.pszVal, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile!=INVALID_HANDLE_VALUE) { + dat->avatarPic=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal); + CloseHandle(hFile); + } + } + DBFreeVariant(&dbv); + } + SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0); + SendMessage(hwndDlg, DM_AVATARSIZECHANGE, 0, 0); +} + +static void NotifyTyping(struct MessageWindowData *dat, int mode) +{ + DWORD protoStatus; + DWORD protoCaps; + DWORD typeCaps; + + if (!dat->hContact) + return; + // Don't send to protocols who don't support typing + // Don't send to users who are unchecked in the typing notification options + // Don't send to protocols that are offline + // Don't send to users who are not visible and + // Don't send to users who are not on the visible list when you are in invisible mode. + if (!DBGetContactSettingByte(dat->hContact, SRMMMOD, SRMSGSET_TYPING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW))) + return; + if (!dat->szProto) + return; + protoStatus = CallProtoService(dat->szProto, PS_GETSTATUS, 0, 0); + protoCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1, 0); + typeCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0); + + if (!(typeCaps & PF4_SUPPORTTYPING)) + return; + if (protoStatus < ID_STATUS_ONLINE) + return; + if (protoCaps & PF1_VISLIST && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE) + return; + if (protoCaps & PF1_INVISLIST && protoStatus == ID_STATUS_INVISIBLE && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) != ID_STATUS_ONLINE) + return; + if (DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0) + && !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN)) + return; + // End user check + dat->nTypeMode = mode; + CallService(MS_PROTO_SELFISTYPING, (WPARAM) dat->hContact, dat->nTypeMode); +} + +BOOL CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct MessageWindowData *dat; + + dat = (struct MessageWindowData *) GetWindowLong(hwndDlg, GWL_USERDATA); + switch (msg) { + case WM_INITDIALOG: + { + struct NewMessageWindowLParam *newData = (struct NewMessageWindowLParam *) lParam; + TranslateDialogDefault(hwndDlg); + dat = (struct MessageWindowData *) calloc(sizeof(struct MessageWindowData),1); + SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) dat); + { + dat->hContact = newData->hContact; + NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING); + if (newData->szInitialText) { + int len; +#if defined(_UNICODE) + if(newData->isWchar) + SetDlgItemText(hwndDlg, IDC_MESSAGE, (TCHAR *)newData->szInitialText); + else + SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText); +#else + SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText); +#endif + len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); + PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, len, len); + } + } + dat->szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->hContact, 0); + RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_LOG)); + { // avatar stuff + dat->avatarPic = 0; + dat->avatarWidth = 0; + dat->avatarHeight = 0; + dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)?DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT):0; + } + if (dat->hContact && dat->szProto != NULL) + dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + else + dat->wStatus = ID_STATUS_OFFLINE; + dat->wOldStatus = dat->wStatus; + dat->hSendId = NULL; + dat->hBkgBrush = NULL; + dat->hDbEventFirst = NULL; + dat->sendBuffer = NULL; + dat->splitterPos = (int) DBGetContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", (DWORD) - 1); + dat->windowWasCascaded = 0; + dat->nFlash = 0; + dat->nTypeSecs = 0; + dat->nLastTyping = 0; + dat->showTyping = 0; + dat->cmdList = 0; + dat->cmdListCurrent = 0; + dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF; + SetTimer(hwndDlg, TIMERID_TYPE, 1000, NULL); + dat->lastMessage = 0; + dat->lastEventType = -1; + dat->nFlashMax = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT); + { + RECT rc, rc2; + GetWindowRect(GetDlgItem(hwndDlg, IDC_USERMENU), &rc); + GetWindowRect(hwndDlg, &rc2); + dat->nLabelRight = rc2.right - rc.left; + } + { + RECT rc; + POINT pt; + GetWindowRect(GetDlgItem(hwndDlg, IDC_SPLITTER), &rc); + pt.y = (rc.top + rc.bottom) / 2; + pt.x = 0; + ScreenToClient(hwndDlg, &pt); + dat->originalSplitterPos = pt.y; + if (dat->splitterPos == -1) + dat->splitterPos = dat->originalSplitterPos;// + 60; + GetWindowRect(GetDlgItem(hwndDlg, IDC_ADD), &rc); + dat->lineHeight = rc.bottom - rc.top + 3; + } + WindowList_Add(g_dat->hMessageWindowList, hwndDlg, dat->hContact); + GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &dat->minEditInit); + SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0); + dat->hwndStatus = NULL; + SendDlgItemMessage(hwndDlg, IDC_ADD, BM_SETIMAGE, IMAGE_ICON, (LPARAM) g_dat->hIcons[SMF_ICON_ADD]); + SendDlgItemMessage(hwndDlg, IDC_DETAILS, BM_SETIMAGE, IMAGE_ICON, (LPARAM) g_dat->hIcons[SMF_ICON_USERDETAIL]); + SendDlgItemMessage(hwndDlg, IDC_HISTORY, BM_SETIMAGE, IMAGE_ICON, (LPARAM) g_dat->hIcons[SMF_ICON_HISTORY]); + SendDlgItemMessage(hwndDlg, IDC_USERMENU, BM_SETIMAGE, IMAGE_ICON, (LPARAM) g_dat->hIcons[SMF_ICON_ARROW]); + // Make them flat buttons + { + int i; + + SendMessage(GetDlgItem(hwndDlg, IDC_NAME), BUTTONSETASFLATBTN, 0, 0); + for (i = 0; i < SIZEOF(buttonLineControls); i++) + SendMessage(GetDlgItem(hwndDlg, buttonLineControls[i]), BUTTONSETASFLATBTN, 0, 0); + } + SendMessage(GetDlgItem(hwndDlg, IDC_ADD), BUTTONADDTOOLTIP, (WPARAM) Translate("Add Contact Permanently to List"), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_USERMENU), BUTTONADDTOOLTIP, (WPARAM) Translate("User Menu"), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_DETAILS), BUTTONADDTOOLTIP, (WPARAM) Translate("View User's Details"), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_HISTORY), BUTTONADDTOOLTIP, (WPARAM) Translate("View User's History"), 0); + + EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOL), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_AVATAR), FALSE); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK); + /* duh, how come we didnt use this from the start? */ + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, (WPARAM) TRUE, 0); + if (dat->hContact) { + if (dat->szProto) { + int nMax; + nMax = CallProtoService(dat->szProto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM) dat->hContact); + if (nMax) + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_LIMITTEXT, (WPARAM) nMax, 0); + /* get around a lame bug in the Windows template resource code where richedits are limited to 0x7FFF */ + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_LIMITTEXT, (WPARAM) sizeof(TCHAR) * 0x7FFFFFFF, 0); + } + } + OldMessageEditProc = (WNDPROC) SetWindowLong(GetDlgItem(hwndDlg, IDC_MESSAGE), GWL_WNDPROC, (LONG) MessageEditSubclassProc); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SUBCLASSED, 0, 0); + OldSplitterProc = (WNDPROC) SetWindowLong(GetDlgItem(hwndDlg, IDC_SPLITTER), GWL_WNDPROC, (LONG) SplitterSubclassProc); + if (dat->hContact) { + int historyMode = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY); + // This finds the first message to display, it works like shit + dat->hDbEventFirst = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) dat->hContact, 0); + switch (historyMode) { + case LOADHISTORY_COUNT: + { + int i; + HANDLE hPrevEvent; + DBEVENTINFO dbei = { 0 }; + dbei.cbSize = sizeof(dbei); + for (i = DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT); i > 0; i--) { + if (dat->hDbEventFirst == NULL) + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); + else + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0); + if (hPrevEvent == NULL) + break; + dbei.cbBlob = 0; + dat->hDbEventFirst = hPrevEvent; + CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei); + if (!DbEventIsShown(&dbei, dat)) + i++; + } + break; + } + case LOADHISTORY_TIME: + { + HANDLE hPrevEvent; + DBEVENTINFO dbei = { 0 }; + DWORD firstTime; + + dbei.cbSize = sizeof(dbei); + if (dat->hDbEventFirst == NULL) + dbei.timestamp = time(NULL); + else + CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei); + firstTime = dbei.timestamp - 60 * DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME); + for (;;) { + if (dat->hDbEventFirst == NULL) + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); + else + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0); + if (hPrevEvent == NULL) + break; + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) & dbei); + if (dbei.timestamp < firstTime) + break; + dat->hDbEventFirst = hPrevEvent; + } + break; + } + } + } + SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 1, 0); + { + int savePerContact = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT); + if (Utils_RestoreWindowPosition(hwndDlg, savePerContact ? dat->hContact : NULL, SRMMMOD, "")) { + if (savePerContact) { + if (Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, SRMMMOD, "")) + SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE); + } + else + SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE); + } + if (!savePerContact && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE)) + WindowList_Broadcast(g_dat->hMessageWindowList, DM_CASCADENEWWINDOW, (WPARAM) hwndDlg, (LPARAM) & dat->windowWasCascaded); + } + { + DBEVENTINFO dbei = { 0 }; + HANDLE hdbEvent; + + dbei.cbSize = sizeof(dbei); + hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); + if (hdbEvent) { + do { + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + CallService(MS_DB_EVENT_GET, (WPARAM) hdbEvent, (LPARAM) & dbei); + if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { + dat->lastMessage = dbei.timestamp; + SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); + break; + } + } + while (hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) hdbEvent, 0)); + } + + } + SendMessage(hwndDlg, DM_GETAVATAR, 0, 0); + ShowWindow(hwndDlg, SW_SHOWNORMAL); + NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN); + return TRUE; + } + case WM_CONTEXTMENU: + { + if (dat->hwndStatus && dat->hwndStatus == (HWND) wParam) { + POINT pt; + HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0); + + GetCursorPos(&pt); + TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwndDlg, NULL); + DestroyMenu(hMenu); + } + break; + } + // Mod from tabsrmm + case WM_DROPFILES: + { + if (dat->szProto==NULL) break; + if (!(CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1,0)&PF1_FILESEND)) break; + if (dat->wStatus==ID_STATUS_OFFLINE) break; + if (dat->hContact!=NULL) { + HDROP hDrop; + char **ppFiles=NULL; + char szFilename[MAX_PATH]; + int fileCount,totalCount=0,i; + + hDrop=(HDROP)wParam; + fileCount=DragQueryFile(hDrop,-1,NULL,0); + ppFiles=NULL; + for(i=0;ihContact, (LPARAM)ppFiles); + for(i=0;ppFiles[i];i++) free(ppFiles[i]); + free(ppFiles); + } + break; + } + case HM_AVATARACK: + { + ACKDATA *pAck = (ACKDATA *)lParam; + PROTO_AVATAR_INFORMATION *pai = (PROTO_AVATAR_INFORMATION *)pAck->hProcess; + HWND hwnd = 0; + + if (pAck->hContact!=dat->hContact) + return 0; + if (pAck->type != ACKTYPE_AVATAR) + return 0; + if (pAck->result == ACKRESULT_STATUS) { + SendMessage(hwndDlg, DM_GETAVATAR, 0, 0); + break; + } + if (pai==NULL) + return 0; + if (pAck->result == ACKRESULT_SUCCESS) { + if (pai->filename&&strlen(pai->filename)&&VALID_AVATAR(pai->format)) { + DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, pai->filename); + ShowAvatar(hwndDlg, dat); + } + } + else if (pAck->result == ACKRESULT_FAILED) { + DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, ""); + ShowAvatar(hwndDlg, dat); + } + break; + } + case DM_AVATARCALCSIZE: + { + BITMAP bminfo; + + if (dat->avatarPic==0||!(g_dat->flags&SMF_AVATAR)) { + dat->avatarWidth=50; + dat->avatarHeight=50; + ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE); + return 0; + } + GetObject(dat->avatarPic, sizeof(bminfo), &bminfo); + dat->avatarWidth=bminfo.bmWidth+2; + dat->avatarHeight=bminfo.bmHeight+2; + if (dat->limitAvatarH&&dat->avatarHeight>dat->limitAvatarH) { + double aspect = 0; + + aspect = (double)dat->limitAvatarH / (double)bminfo.bmHeight; + dat->avatarWidth = (int)(bminfo.bmWidth * aspect + 2); + dat->avatarHeight = dat->limitAvatarH + 2; + } + ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_SHOW); + break; + } + case DM_UPDATESIZEBAR: + { + dat->minEditBoxSize.cx = dat->minEditInit.right - dat->minEditInit.left; + dat->minEditBoxSize.cy = dat->minEditInit.bottom - dat->minEditInit.top; + if (g_dat->flags&SMF_AVATAR) { + SendMessage(hwndDlg, DM_AVATARCALCSIZE, 0, 0); + if(dat->avatarPic) { + if (dat->minEditBoxSize.cy<=dat->avatarHeight) + dat->minEditBoxSize.cy = dat->avatarHeight; + } + } + break; + } + case DM_AVATARSIZECHANGE: + { + RECT rc; + GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc); + if (rc.bottom-rc.topminEditBoxSize.cy) { + SendMessage(hwndDlg, DM_SPLITTERMOVED, rc.top-(rc.bottom-rc.top-dat->minEditBoxSize.cy-4), (LPARAM) GetDlgItem(hwndDlg, IDC_SPLITTER)); + } + SendMessage(hwndDlg, WM_SIZE, 0, 0); + SendMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); + break; + } + case DM_GETAVATAR: + { + PROTO_AVATAR_INFORMATION pai; + int caps = 0, result; + + SetWindowLong(hwndDlg, DWL_MSGRESULT, 0); + if (!(g_dat->flags&SMF_AVATAR)||!(CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0)&PF4_AVATARS)) { + SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0); + SendMessage(hwndDlg, DM_AVATARSIZECHANGE, 0, 0); + SetWindowLong(hwndDlg, DWL_MSGRESULT, 1); + return 0; + } + if(DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) { + ShowAvatar(hwndDlg, dat); + SetWindowLong(hwndDlg, DWL_MSGRESULT, 1); + return 0; + } + ZeroMemory((void *)&pai, sizeof(pai)); + pai.cbSize = sizeof(pai); + pai.hContact = dat->hContact; + pai.format = PA_FORMAT_UNKNOWN; + strcpy(pai.filename, ""); + result = CallProtoService(dat->szProto, PS_GETAVATARINFO, GAIF_FORCE, (LPARAM)&pai); + if (result==GAIR_SUCCESS) { + if (VALID_AVATAR(pai.format)) + DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, pai.filename); + else DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, ""); + ShowAvatar(hwndDlg, dat); + } else if (result == GAIR_NOAVATAR) { + DBWriteContactSettingString(dat->hContact, SRMMMOD, SRMSGSET_AVATAR, ""); + ShowAvatar(hwndDlg, dat); + } + SetWindowLong(hwndDlg, DWL_MSGRESULT, 1); + break; + } + case DM_TYPING: + { + dat->nTypeSecs = (int) lParam > 0 ? (int) lParam : 0; + break; + } + case DM_UPDATEWINICON: + { + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)) { + WORD wStatus; + + if (dat->szProto) { + wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedProtoIcon(dat->szProto, wStatus)); + break; + } + } + SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE)); + break; + } + case DM_USERNAMETOCLIP: + { + CONTACTINFO ci; + char buf[128]; + HGLOBAL hData; + + buf[0] = 0; + if(dat->hContact) { + ZeroMemory(&ci, sizeof(ci)); + ci.cbSize = sizeof(ci); + ci.hContact = dat->hContact; + ci.szProto = dat->szProto; + ci.dwFlag = CNF_UNIQUEID; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + switch (ci.type) { + case CNFT_ASCIIZ: + mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal); + miranda_sys_free(ci.pszVal); + break; + case CNFT_DWORD: + mir_snprintf(buf, SIZEOF(buf), "%u", ci.dVal); + break; + } + } + if (!OpenClipboard(hwndDlg) || !lstrlenA(buf)) break; + EmptyClipboard(); + hData = GlobalAlloc(GMEM_MOVEABLE, lstrlenA(buf) + 1); + lstrcpyA(GlobalLock(hData), buf); + GlobalUnlock(hData); + SetClipboardData(CF_TEXT, hData); + CloseClipboard(); + } + break; + } + case DM_UPDATELASTMESSAGE: + { + if (!dat->hwndStatus || dat->nTypeSecs) + break; + if (dat->lastMessage) { + DBTIMETOSTRINGT dbtts; + TCHAR date[64], time[64], fmt[128]; + + dbtts.szFormat = _T("d"); + dbtts.cbDest = SIZEOF(date); + dbtts.szDest = date; + CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT, dat->lastMessage, (LPARAM) & dbtts); + dbtts.szFormat = _T("t"); + dbtts.cbDest = SIZEOF(time); + dbtts.szDest = time; + CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT, dat->lastMessage, (LPARAM) & dbtts); + mir_sntprintf(fmt, SIZEOF(fmt), TranslateT("Last message received on %s at %s."), date, time); + SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) fmt); + SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) NULL); + } + else { + SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) _T("")); + SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) NULL); + } + break; + } + case DM_OPTIONSAPPLIED: + SetDialogToType(hwndDlg); + if (dat->hBkgBrush) + DeleteObject(dat->hBkgBrush); + { + COLORREF colour = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR); + dat->hBkgBrush = CreateSolidBrush(colour); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETBKGNDCOLOR, 0, colour); + } + { // avatar stuff + dat->avatarPic = 0; + dat->limitAvatarH = 0; + if (CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0)&PF4_AVATARS) { + dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)?DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT):0; + } + if (!wParam) SendMessage(hwndDlg, DM_GETAVATAR, 0, 0); + } + InvalidateRect(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, FALSE); + { + HFONT hFont; + LOGFONT lf; + hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0); + if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0)) + DeleteObject(hFont); + LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, &lf, NULL); + hFont = CreateFontIndirect(&lf); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0)); + } + + /* + * configure message history for proper RTL formatting + */ + + { + PARAFORMAT2 pf2; + ZeroMemory((void *)&pf2, sizeof(pf2)); + pf2.cbSize = sizeof(pf2); + + pf2.wEffects = PFE_RTLPARA; + pf2.dwMask = PFM_RTLPARA; + SetDlgItemText(hwndDlg, IDC_LOG, _T("")); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + pf2.wEffects = 0; + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD); + } + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); + break; + case DM_UPDATETITLE: + { + TCHAR newtitle[256], oldtitle[256], *szStatus; + TCHAR *contactName, *pszNewTitleEnd; + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) wParam; + + pszNewTitleEnd = _T("Message Session"); + if (dat->hContact) { + if (dat->szProto) { + CONTACTINFO ci; + char buf[128]; + int statusIcon = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON); + + buf[0] = 0; + dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + contactName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR); + ZeroMemory(&ci, sizeof(ci)); + ci.cbSize = sizeof(ci); + ci.hContact = dat->hContact; + ci.szProto = dat->szProto; + ci.dwFlag = CNF_UNIQUEID; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + switch (ci.type) { + case CNFT_ASCIIZ: + mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal); + miranda_sys_free(ci.pszVal); + break; + case CNFT_DWORD: + mir_snprintf(buf, SIZEOF(buf), "%u", ci.dVal); + break; + } + } + if ( buf[0] ) + SetDlgItemTextA(hwndDlg, IDC_NAME, buf ); + else + SetDlgItemText(hwndDlg, IDC_NAME, contactName); + + szStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, dat->szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE), GCMDF_TCHAR); + if (statusIcon) + mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s - %s"), contactName, TranslateTS(pszNewTitleEnd)); + else + mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s (%s): %s"), contactName, szStatus, TranslateTS(pszNewTitleEnd)); + if (!cws || (!strcmp(cws->szModule, dat->szProto) && !strcmp(cws->szSetting, "Status"))) { + InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOCOL), NULL, TRUE); + if (statusIcon) { + SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); + } + } + + // log + if ((dat->wStatus != dat->wOldStatus || lParam != 0) + && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)) { + DBEVENTINFO dbei; + TCHAR buffer[200]; + HANDLE hNewEvent; + int iLen; + + TCHAR *szOldStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wOldStatus, GCMDF_TCHAR); + TCHAR *szNewStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wStatus, GCMDF_TCHAR); + + if (dat->wStatus == ID_STATUS_OFFLINE) { + iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed off (was %s)"), szOldStatus); + SendMessage(hwndDlg, DM_TYPING, 0, 0); + } + else if (dat->wOldStatus == ID_STATUS_OFFLINE) + iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed on (%s)"), szNewStatus); + else + iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("is now %s (was %s)"), szNewStatus, szOldStatus); + + { + char* blob = ( char* )alloca( 1000 ); + #if defined( _UNICODE ) + int ansiLen = WideCharToMultiByte(CP_ACP, 0, buffer, -1, blob, 1000, 0, 0); + memcpy( blob+ansiLen, buffer, sizeof(TCHAR)*(iLen+1)); + dbei.cbBlob = ansiLen + sizeof(TCHAR)*(iLen+1); + #else + int wLen = MultiByteToWideChar(CP_ACP, 0, buffer, -1, NULL, 0 ); + memcpy( blob, buffer, iLen+1 ); + MultiByteToWideChar(CP_ACP, 0, buffer, -1, (WCHAR*)&blob[iLen+1], wLen+1 ); + dbei.cbBlob = iLen+1 + sizeof(WCHAR)*wLen; + #endif + + dbei.cbSize = sizeof(dbei); + dbei.pBlob = (PBYTE) blob; + dbei.eventType = EVENTTYPE_STATUSCHANGE; + dbei.flags = 0; + dbei.timestamp = time(NULL); + dbei.szModule = dat->szProto; + hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) dat->hContact, (LPARAM) & dbei); + if (dat->hDbEventFirst == NULL) { + dat->hDbEventFirst = hNewEvent; + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + } + } + } + dat->wOldStatus = dat->wStatus; + } + } + else lstrcpyn(newtitle, pszNewTitleEnd, SIZEOF(newtitle)); + + GetWindowText(hwndDlg, oldtitle, SIZEOF(oldtitle)); + if ( lstrcmp(newtitle, oldtitle )) { //swt() flickers even if the title hasn't actually changed + SetWindowText(hwndDlg, newtitle); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + } + break; + } + case DM_GETWINDOWSTATE: + { + UINT state = 0; + + state |= MSG_WINDOW_STATE_EXISTS; + if (IsWindowVisible(hwndDlg)) + state |= MSG_WINDOW_STATE_VISIBLE; + if (GetForegroundWindow()==hwndDlg) + state |= MSG_WINDOW_STATE_FOCUS; + if (IsIconic(hwndDlg)) + state |= MSG_WINDOW_STATE_ICONIC; + SetWindowLong(hwndDlg, DWL_MSGRESULT, state); + return TRUE; + + } + case DM_CASCADENEWWINDOW: + if ((HWND) wParam == hwndDlg) + break; + { + RECT rcThis, rcNew; + GetWindowRect(hwndDlg, &rcThis); + GetWindowRect((HWND) wParam, &rcNew); + if (abs(rcThis.left - rcNew.left) < 3 && abs(rcThis.top - rcNew.top) < 3) { + int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME); + SetWindowPos((HWND) wParam, 0, rcNew.left + offset, rcNew.top + offset, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + *(int *) lParam = 1; + } + } + break; + case WM_ACTIVATE: + if (LOWORD(wParam) != WA_ACTIVE) + break; + //fall through + case WM_MOUSEACTIVATE: + if (KillTimer(hwndDlg, TIMERID_FLASHWND)) + FlashWindow(hwndDlg, FALSE); + break; + case WM_SETFOCUS: + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + break; + case WM_GETMINMAXINFO: + { + MINMAXINFO *mmi = (MINMAXINFO *) lParam; + RECT rcWindow, rcLog; + GetWindowRect(hwndDlg, &rcWindow); + GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog); + mmi->ptMinTrackSize.x = rcWindow.right - rcWindow.left - ((rcLog.right - rcLog.left) - dat->minEditBoxSize.cx); + mmi->ptMinTrackSize.y = rcWindow.bottom - rcWindow.top - ((rcLog.bottom - rcLog.top) - dat->minEditBoxSize.cy); + return 0; + } + case WM_SIZE: + { + UTILRESIZEDIALOG urd; + if (IsIconic(hwndDlg)) + break; + if (dat->hwndStatus) { + SendMessage(dat->hwndStatus, WM_SIZE, 0, 0); + if (SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) == 2) { + int statwidths[2]; + RECT rc; + + GetWindowRect(dat->hwndStatus, &rc); + statwidths[0] = rc.right - rc.left - SB_CHAR_WIDTH; + statwidths[1] = -1; + SendMessage(dat->hwndStatus, SB_SETPARTS, 2, (LPARAM) statwidths); + } + } + ZeroMemory(&urd, sizeof(urd)); + urd.cbSize = sizeof(urd); + urd.hInstance = g_hInst; + urd.hwndDlg = hwndDlg; + urd.lParam = (LPARAM) dat; + urd.lpTemplate = MAKEINTRESOURCEA(IDD_MSG); + urd.pfnResizer = MessageDialogResize; + CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) & urd); + // The statusbar sometimes draws over these 2 controls so + // redraw them + if (dat->hwndStatus) { + RedrawWindow(GetDlgItem(hwndDlg, IDOK), NULL, NULL, RDW_INVALIDATE); + RedrawWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE); + } + if ((g_dat->flags&SMF_AVATAR)&&dat->avatarPic) + RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE); + break; + } + case DM_SPLITTERMOVED: + { + POINT pt; + RECT rc; + RECT rcLog; + GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog); + if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SPLITTER)) { + int oldSplitterY; + GetClientRect(hwndDlg, &rc); + pt.x = 0; + pt.y = wParam; + ScreenToClient(hwndDlg, &pt); + + oldSplitterY = dat->splitterPos; + dat->splitterPos = rc.bottom - pt.y + 23; + GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc); + if (rc.bottom - rc.top + (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy) + dat->splitterPos = oldSplitterY + dat->minEditBoxSize.cy - (rc.bottom - rc.top); + if (rcLog.bottom - rcLog.top - (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy) + dat->splitterPos = oldSplitterY - dat->minEditBoxSize.cy + (rcLog.bottom - rcLog.top); + } + SendMessage(hwndDlg, WM_SIZE, 0, 0); + break; + } + case DM_REMAKELOG: + dat->lastEventType = -1; + StreamInEvents(hwndDlg, dat->hDbEventFirst, -1, 0); + break; + case DM_APPENDTOLOG: //takes wParam=hDbEvent + StreamInEvents(hwndDlg, (HANDLE) wParam, 1, 1); + break; + case DM_SCROLLLOGTOBOTTOM: + { + SCROLLINFO si = { 0 }; + if ((GetWindowLong(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL) == 0) + break; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE; + GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si); + si.fMask = SIF_POS; + si.nPos = si.nMax - si.nPage + 1; + SetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si, TRUE); + PostMessage(GetDlgItem(hwndDlg, IDC_LOG), WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0); + break; + } + case HM_DBEVENTADDED: + if ((HANDLE) wParam != dat->hContact) + break; + { + DBEVENTINFO dbei = { 0 }; + + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei); + if (dat->hDbEventFirst == NULL) + dat->hDbEventFirst = (HANDLE) lParam; + if (dbei.eventType == EVENTTYPE_MESSAGE && (dbei.flags & DBEF_READ)) + break; + if (DbEventIsShown(&dbei, dat)) { + if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & (DBEF_SENT))) { + if (GetForegroundWindow()==hwndDlg) + SkinPlaySound("RecvMsgActive"); + else SkinPlaySound("RecvMsgInactive"); + } + if (dbei.eventType == EVENTTYPE_MESSAGE && dat->hwndStatus && !(dbei.flags & (DBEF_SENT))) { + dat->lastMessage = dbei.timestamp; + SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); + } + if ((HANDLE) lParam != dat->hDbEventFirst && (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, lParam, 0) == NULL) + SendMessage(hwndDlg, DM_APPENDTOLOG, lParam, 0); + else + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + if ((GetActiveWindow() != hwndDlg || GetForegroundWindow() != hwndDlg) && !(dbei.flags & DBEF_SENT) + && dbei.eventType != EVENTTYPE_STATUSCHANGE) { + SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); + } + } + break; + } + case WM_TIMER: + if (wParam == TIMERID_MSGSEND) { + KillTimer(hwndDlg, wParam); + ShowWindow(hwndDlg, SW_SHOWNORMAL); + EnableWindow(hwndDlg, FALSE); + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGSENDERROR), hwndDlg, ErrorDlgProc, (LPARAM) strdup( Translate("The message send timed out."))); + } + else if (wParam == TIMERID_FLASHWND) { + FlashWindow(hwndDlg, TRUE); + if (dat->nFlash > dat->nFlashMax) { + KillTimer(hwndDlg, TIMERID_FLASHWND); + FlashWindow(hwndDlg, FALSE); + dat->nFlash = 0; + } + dat->nFlash++; + } + else if (wParam == TIMERID_TYPE) { + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON && GetTickCount() - dat->nLastTyping > TIMEOUT_TYPEOFF) { + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + } + if (dat->showTyping) { + if (dat->nTypeSecs) { + dat->nTypeSecs--; + if (GetForegroundWindow() == hwndDlg) + SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); + } + else { + SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); + if (g_dat->flags&SMF_SHOWTYPINGWIN) + SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); + dat->showTyping = 0; + } + } + else { + if (dat->nTypeSecs) { + TCHAR szBuf[256]; + TCHAR *szContactName = ( TCHAR* ) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR); + + mir_sntprintf(szBuf, SIZEOF(szBuf), TranslateT("%s is typing a message..."), szContactName); + dat->nTypeSecs--; + SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) szBuf); + SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) g_dat->hIcons[SMF_ICON_TYPING]); + if ((g_dat->flags&SMF_SHOWTYPINGWIN) && GetForegroundWindow() != hwndDlg) + SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) g_dat->hIcons[SMF_ICON_TYPING]); + dat->showTyping = 1; + } + } + } + break; + case DM_ERRORDECIDED: + EnableWindow(hwndDlg, TRUE); + switch (wParam) { + case MSGERROR_CANCEL: + EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETREADONLY, FALSE, 0); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + break; + case MSGERROR_RETRY: + { + if (dat->hSendId == NULL && dat->hContact == NULL) + return 0; + dat->hSendId = (HANDLE) CallContactService(dat->hContact, MsgServiceName(dat->hContact), SEND_FLAGS, (LPARAM) dat->sendBuffer); + } + SetTimer(hwndDlg, TIMERID_MSGSEND, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT), NULL); + break; + } + break; + case WM_CTLCOLOREDIT: + { + COLORREF colour; + if ((HWND) lParam != GetDlgItem(hwndDlg, IDC_MESSAGE)) + break; + LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, NULL, &colour); + SetTextColor((HDC) wParam, colour); + SetBkColor((HDC) wParam, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); + return (BOOL) dat->hBkgBrush; + } + case WM_MEASUREITEM: + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; + if (dis->hwndItem == GetDlgItem(hwndDlg, IDC_PROTOCOL)) { + if (dat->szProto) { + HICON hIcon; + int dwStatus; + + dwStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + hIcon = LoadSkinnedProtoIcon(dat->szProto, dwStatus); + if (hIcon) { + if (DBGetContactSettingDword(dat->hContact, dat->szProto, "IdleTS", 0)) { + HIMAGELIST hImageList; + + hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, 1, 0); + ImageList_AddIcon(hImageList, hIcon); + ImageList_DrawEx(hImageList, 0, dis->hDC, dis->rcItem.left, dis->rcItem.top, 0, 0, CLR_NONE, CLR_NONE, ILD_SELECTED); + ImageList_RemoveAll(hImageList); + ImageList_Destroy(hImageList); + } + else DrawIconEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL); + } + } + } + else if (dis->hwndItem == GetDlgItem(hwndDlg, IDC_AVATAR) && dat->avatarPic && (g_dat->flags&SMF_AVATAR)) { + BITMAP bminfo; + HPEN hPen, hOldPen; + + hPen = CreatePen(PS_SOLID, 1, RGB(0,0,0)); + hOldPen = SelectObject(dis->hDC, hPen); + Rectangle(dis->hDC, 0, 0, dat->avatarWidth, dat->avatarHeight); + SelectObject(dis->hDC,hOldPen); + DeleteObject(hPen); + GetObject(dat->avatarPic, sizeof(bminfo), &bminfo); + { + HDC hdcMem = CreateCompatibleDC(dis->hDC); + HBITMAP hbmMem = (HBITMAP)SelectObject(hdcMem, dat->avatarPic); + { + double aspect = 0, w = 0; + + aspect = (double)dat->limitAvatarH / (double)bminfo.bmHeight; + w = (double)bminfo.bmWidth * aspect; + SetStretchBltMode(dis->hDC, HALFTONE); + StretchBlt(dis->hDC, 1, 1, dat->avatarWidth-2, dat->avatarHeight-2, hdcMem, 0, 0, bminfo.bmWidth, bminfo.bmHeight, SRCCOPY); + } + SelectObject(hdcMem,hbmMem); + DeleteDC(hdcMem); + } + } + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + } + case WM_COMMAND: + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) dat->hContact)) + break; + switch (LOWORD(wParam)) { + case IDOK: + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDOK))) + break; + { + int flags = SEND_FLAGS; + //this is a 'send' button + int bufSize = GetWindowTextLengthA(GetDlgItem(hwndDlg, IDC_MESSAGE)) + 1; + dat->sendBuffer = (char *) realloc(dat->sendBuffer, bufSize * (sizeof(TCHAR) + 1)); + dat->bIsRtl = 0; + GetDlgItemTextA(hwndDlg, IDC_MESSAGE, dat->sendBuffer, bufSize); + #if defined( _UNICODE ) + // all that crap with temporary buffers is related to the bug #0001466 (empty messages + // on x64 machines). GetDlgItemTextW should use the 2-byte aligned buffer + { WCHAR* temp = ( WCHAR* )alloca( bufSize * sizeof( TCHAR )); + GetDlgItemTextW(hwndDlg, IDC_MESSAGE, temp, bufSize); + memcpy(( TCHAR*)&dat->sendBuffer[bufSize], temp, bufSize * sizeof( TCHAR )); + if ( RTL_Detect( temp )) { + flags |= PREF_RTL; + dat->bIsRtl = 1; + } + } + #endif + if (dat->sendBuffer[0] == 0) + break; + #if defined( _UNICODE ) + dat->cmdList = tcmdlist_append(dat->cmdList, (TCHAR *) & dat->sendBuffer[bufSize]); + #else + dat->cmdList = tcmdlist_append(dat->cmdList, dat->sendBuffer); + #endif + dat->cmdListCurrent = 0; + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) { + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + } + + if (dat->hContact == NULL) + break; //never happens + dat->sendCount = 1; + dat->hSendId = (HANDLE) CallContactService(dat->hContact, MsgServiceName(dat->hContact), flags, (LPARAM) dat->sendBuffer); + EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETREADONLY, TRUE, 0); + + //create a timeout timer + SetTimer(hwndDlg, TIMERID_MSGSEND, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT), NULL); + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)) + ShowWindow(hwndDlg, SW_MINIMIZE); + } + return TRUE; + case IDCANCEL: + DestroyWindow(hwndDlg); + return TRUE; + case IDC_USERMENU: + case IDC_NAME: + { + if(GetKeyState(VK_SHIFT) & 0x8000) { // copy user name + SendMessage(hwndDlg, DM_USERNAMETOCLIP, 0, 0); + } + else { + RECT rc; + HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0); + GetWindowRect(GetDlgItem(hwndDlg, LOWORD(wParam)), &rc); + TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); + DestroyMenu(hMenu); + } + } + break; + case IDC_HISTORY: + CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM) dat->hContact, 0); + break; + case IDC_DETAILS: + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) dat->hContact, 0); + break; + case IDC_ADD: + { + ADDCONTACTSTRUCT acs = { 0 }; + + acs.handle = dat->hContact; + acs.handleType = HANDLE_CONTACT; + acs.szProto = 0; + CallService(MS_ADDCONTACT_SHOW, (WPARAM) hwndDlg, (LPARAM) & acs); + } + if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) { + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE); + } + break; + case IDC_MESSAGE: + if (HIWORD(wParam) == EN_CHANGE) { + int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); + UpdateReadChars(hwndDlg, dat->hwndStatus); + EnableWindow(GetDlgItem(hwndDlg, IDOK), len != 0); + if (!(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000)) { + dat->nLastTyping = GetTickCount(); + if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE))) { + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_OFF) { + NotifyTyping(dat, PROTOTYPE_SELFTYPING_ON); + } + } + else { + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) { + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + } + } + } + } + break; + } + break; + case WM_NOTIFY: + switch (((NMHDR *) lParam)->idFrom) { + case IDC_LOG: + switch (((NMHDR *) lParam)->code) { + case EN_MSGFILTER: + switch (((MSGFILTER *) lParam)->msg) { + case WM_LBUTTONDOWN: + { + HCURSOR hCur = GetCursor(); + if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) + || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) { + SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE); + return TRUE; + } + break; + } + case WM_MOUSEMOVE: + { + HCURSOR hCur = GetCursor(); + if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) + || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) + SetCursor(LoadCursor(NULL, IDC_ARROW)); + break; + } + case WM_RBUTTONUP: + { + HMENU hMenu, hSubMenu; + POINT pt; + CHARRANGE sel, all = { 0, -1 }; + + hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + hSubMenu = GetSubMenu(hMenu, 0); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hSubMenu, 0); + SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel); + if (sel.cpMin == sel.cpMax) + EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + 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 IDM_COPY: + SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0); + break; + case IDM_COPYALL: + SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all); + SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0); + SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel); + break; + case IDM_SELECTALL: + SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all); + break; + case IDM_CLEAR: + SetDlgItemText(hwndDlg, IDC_LOG, _T("")); + dat->hDbEventFirst = NULL; + break; + } + DestroyMenu(hMenu); + SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE); + return TRUE; + } + } + break; + case EN_LINK: + switch (((ENLINK *) lParam)->msg) { + case WM_SETCURSOR: + SetCursor(hCurHyperlinkHand); + SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE); + return TRUE; + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + { + TEXTRANGEA tr; + CHARRANGE sel; + + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM) & sel); + if (sel.cpMin != sel.cpMax) + break; + tr.chrg = ((ENLINK *) lParam)->chrg; + tr.lpstrText = malloc(tr.chrg.cpMax - tr.chrg.cpMin + 8); + SendDlgItemMessageA(hwndDlg, IDC_LOG, EM_GETTEXTRANGE, 0, (LPARAM) & tr); + if (strchr(tr.lpstrText, '@') != NULL && strchr(tr.lpstrText, ':') == NULL && strchr(tr.lpstrText, '/') == NULL) { + MoveMemory(tr.lpstrText + 7, tr.lpstrText, tr.chrg.cpMax - tr.chrg.cpMin + 1); + CopyMemory(tr.lpstrText, "mailto:", 7); + } + if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN) { + HMENU hMenu, hSubMenu; + POINT pt; + + hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + hSubMenu = GetSubMenu(hMenu, 1); + 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 IDM_OPENNEW: + CallService(MS_UTILS_OPENURL, 1, (LPARAM) tr.lpstrText); + break; + case IDM_OPENEXISTING: + CallService(MS_UTILS_OPENURL, 0, (LPARAM) tr.lpstrText); + break; + case IDM_COPYLINK: + { + HGLOBAL hData; + if (!OpenClipboard(hwndDlg)) + break; + EmptyClipboard(); + hData = GlobalAlloc(GMEM_MOVEABLE, lstrlenA(tr.lpstrText) + 1); + lstrcpyA(GlobalLock(hData), tr.lpstrText); + GlobalUnlock(hData); + SetClipboardData(CF_TEXT, hData); + CloseClipboard(); + break; + } + } + free(tr.lpstrText); + DestroyMenu(hMenu); + SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE); + return TRUE; + } + else { + CallService(MS_UTILS_OPENURL, 1, (LPARAM) tr.lpstrText); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + } + + free(tr.lpstrText); + break; + } + } + break; + } + break; + } + break; + case HM_EVENTSENT: + { + ACKDATA *ack = (ACKDATA *) lParam; + DBEVENTINFO dbei = { 0 }; + HANDLE hNewEvent; + + if (ack->type != ACKTYPE_MESSAGE) + break; + if (dat->sendCount==0) + break; + switch (ack->result) { + case ACKRESULT_FAILED: + KillTimer(hwndDlg, TIMERID_MSGSEND); + ShowWindow(hwndDlg, SW_SHOWNORMAL); + EnableWindow(hwndDlg, FALSE); + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGSENDERROR), hwndDlg, ErrorDlgProc, (ack->lParam == 0) ? 0 : (LPARAM) strdup((char *) ack->lParam)); + return 0; + } + if (dat->sendBuffer==NULL) return 0; + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.flags = DBEF_SENT + (( dat->bIsRtl ) ? DBEF_RTL : 0 ); + + dbei.szModule = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->hContact, 0); + dbei.timestamp = time(NULL); + dbei.cbBlob = lstrlenA(dat->sendBuffer) + 1; + #if defined( _UNICODE ) + dbei.cbBlob *= sizeof(TCHAR) + 1; + #endif + dbei.pBlob = (PBYTE) dat->sendBuffer; + hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) dat->hContact, (LPARAM) & dbei); + SkinPlaySound("SendMsg"); + if (dat->hDbEventFirst == NULL) { + dat->hDbEventFirst = hNewEvent; + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + } + + dat->hSendId = NULL; + { + int len; + //all messages sent + dat->sendCount = 0; + KillTimer(hwndDlg, TIMERID_MSGSEND); + SetDlgItemText(hwndDlg, IDC_MESSAGE, _T("")); + EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETREADONLY, FALSE, 0); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REPLAYSAVEDKEYSTROKES, 0, 0); + if (GetForegroundWindow() == hwndDlg) + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); + UpdateReadChars(hwndDlg, dat->hwndStatus); + EnableWindow(GetDlgItem(hwndDlg, IDOK), len != 0); + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)) + DestroyWindow(hwndDlg); + } + break; + } + case WM_DESTROY: + NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING); + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) { + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + } + if (dat->hBkgBrush) + DeleteObject(dat->hBkgBrush); + if (dat->sendBuffer != NULL) + free(dat->sendBuffer); + if (dat->hwndStatus) + DestroyWindow(dat->hwndStatus); + tcmdlist_free(dat->cmdList); + WindowList_Remove(g_dat->hMessageWindowList, hwndDlg); + DBWriteContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", dat->splitterPos); + SetWindowLong(GetDlgItem(hwndDlg, IDC_SPLITTER), GWL_WNDPROC, (LONG) OldSplitterProc); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_UNSUBCLASSED, 0, 0); + SetWindowLong(GetDlgItem(hwndDlg, IDC_MESSAGE), GWL_WNDPROC, (LONG) OldMessageEditProc); + { + HFONT hFont; + hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0); + if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0)) + DeleteObject(hFont); + } + { + WINDOWPLACEMENT wp = { 0 }; + HANDLE hContact; + + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)) + hContact = dat->hContact; + else + hContact = NULL; + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + if (!dat->windowWasCascaded) { + DBWriteContactSettingDword(hContact, SRMMMOD, "x", wp.rcNormalPosition.left); + DBWriteContactSettingDword(hContact, SRMMMOD, "y", wp.rcNormalPosition.top); + } + DBWriteContactSettingDword(hContact, SRMMMOD, "width", wp.rcNormalPosition.right - wp.rcNormalPosition.left); + DBWriteContactSettingDword(hContact, SRMMMOD, "height", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top); + } + if (dat->avatarPic) + DeleteObject(dat->avatarPic); + NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE); + if (dat->hContact&&DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP)) { + if (DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) { + CallService(MS_DB_CONTACT_DELETE, (WPARAM)dat->hContact, 0); + } + } + free(dat); + SetWindowLong(hwndDlg, GWL_USERDATA, 0); + break; + } + return FALSE; +} diff --git a/miranda-wine/plugins/srmm/msglog.c b/miranda-wine/plugins/srmm/msglog.c new file mode 100644 index 0000000..a988868 --- /dev/null +++ b/miranda-wine/plugins/srmm/msglog.c @@ -0,0 +1,549 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#include "commonheaders.h" +#pragma hdrstop +#include +#include +#include + +extern HINSTANCE g_hInst; + +static int logPixelSY; +#define LOGICON_MSG_IN 0 +#define LOGICON_MSG_OUT 1 +#define LOGICON_MSG_NOTICE 2 +static PBYTE pLogIconBmpBits[3]; +static int logIconBmpSize[ SIZEOF(pLogIconBmpBits) ]; +static HIMAGELIST g_hImageList; + +#define STREAMSTAGE_HEADER 0 +#define STREAMSTAGE_EVENTS 1 +#define STREAMSTAGE_TAIL 2 +#define STREAMSTAGE_STOP 3 +struct LogStreamData +{ + int stage; + HANDLE hContact; + HANDLE hDbEvent, hDbEventLast; + char *buffer; + int bufferOffset, bufferLen; + int eventsToInsert; + int isEmpty; + struct MessageWindowData *dlgDat; +}; + +static char szSep2[40], szSep2_RTL[50]; + +static void AppendToBuffer(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const char *fmt, ...) +{ + va_list va; + int charsDone; + + va_start(va, fmt); + for (;;) { + charsDone = mir_vsnprintf(*buffer + *cbBufferEnd, *cbBufferAlloced - *cbBufferEnd, fmt, va); + if (charsDone >= 0) + break; + *cbBufferAlloced += 1024; + *buffer = (char *) realloc(*buffer, *cbBufferAlloced); + } + va_end(va); + *cbBufferEnd += charsDone; +} + +static int AppendToBufferWithRTF(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, TCHAR* line) +{ + DWORD textCharsCount = 0; + char *d; + + int lineLen = _tcslen(line) * 9 + 8; + if (*cbBufferEnd + lineLen > *cbBufferAlloced) { + cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024); + *buffer = (char *) realloc(*buffer, *cbBufferAlloced); + } + + d = *buffer + *cbBufferEnd; + strcpy(d, "{\\uc1 "); + d += 6; + + for (; *line; line++, textCharsCount++) { + if (*line == '\r' && line[1] == '\n') { + CopyMemory(d, "\\par ", 5); + line++; + d += 5; + } + else if (*line == '\n') { + CopyMemory(d, "\\par ", 5); + d += 5; + } + else if (*line == '\t') { + CopyMemory(d, "\\tab ", 5); + d += 5; + } + else if (*line == '\\' || *line == '{' || *line == '}') { + *d++ = '\\'; + *d++ = (char) *line; + } + else if (*line < 128) { + *d++ = (char) *line; + } + else d += sprintf(d, "\\u%d ?", *line); + } + + strcpy(d, "}"); + d++; + + *cbBufferEnd = (int) (d - *buffer); + return textCharsCount; +} + +#if defined( _UNICODE ) + #define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %S;}" +#else + #define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %s;}" +#endif + +static char *CreateRTFHeader(struct MessageWindowData *dat) +{ + char *buffer; + int bufferAlloced, bufferEnd; + int i; + LOGFONT lf; + COLORREF colour; + HDC hdc; + + hdc = GetDC(NULL); + logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(NULL, hdc); + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) malloc(bufferAlloced); + buffer[0] = '\0'; + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl"); + + for (i = 0; i < msgDlgFontCount; i++) { + LoadMsgDlgFont(i, &lf, NULL); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, FONT_FORMAT, i, lf.lfCharSet, lf.lfFaceName); + } + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl "); + for (i = 0; i < msgDlgFontCount; i++) { + LoadMsgDlgFont(i, NULL, &colour); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + } + if (GetSysColorBrush(COLOR_HOTLIGHT) == NULL) + colour = RGB(0, 0, 255); + else + colour = GetSysColor(COLOR_HOTLIGHT); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}"); + //AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}\\pard"); + return buffer; +} + +//free() the return value +static char *CreateRTFTail(struct MessageWindowData *dat) +{ + char *buffer; + int bufferAlloced, bufferEnd; + + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) malloc(bufferAlloced); + buffer[0] = '\0'; + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}"); + return buffer; +} + +//return value is static +static char *SetToStyle(int style) +{ + static char szStyle[128]; + LOGFONT lf; + + LoadMsgDlgFont(style, &lf, NULL); + wsprintfA(szStyle, "\\f%u\\cf%u\\b%d\\i%d\\fs%u", style, style, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / logPixelSY); + return szStyle; +} + +int DbEventIsShown(DBEVENTINFO * dbei, struct MessageWindowData *dat) +{ + switch (dbei->eventType) { + case EVENTTYPE_MESSAGE: + return 1; + case EVENTTYPE_STATUSCHANGE: + if (dbei->flags & DBEF_READ) + return 0; + return 1; + } + return 0; +} + +//free() the return value +static char *CreateRTFFromDbEvent(struct MessageWindowData *dat, HANDLE hContact, HANDLE hDbEvent, struct LogStreamData *streamData) +{ + char *buffer; + int bufferAlloced, bufferEnd; + DBEVENTINFO dbei = { 0 }; + int showColon = 0; + + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM) hDbEvent, 0); + if (dbei.cbBlob == -1) + return NULL; + dbei.pBlob = (PBYTE) malloc(dbei.cbBlob); + CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei); + if (!DbEventIsShown(&dbei, dat)) { + free(dbei.pBlob); + return NULL; + } + if (!(dbei.flags & DBEF_SENT) && dbei.eventType == EVENTTYPE_MESSAGE) { + CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent); + CallService(MS_CLIST_REMOVEEVENT, (WPARAM) hContact, (LPARAM) hDbEvent); + } + else if (dbei.eventType == EVENTTYPE_STATUSCHANGE) { + CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent); + } + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) malloc(bufferAlloced); + buffer[0] = '\0'; + + if (!dat->bIsAutoRTL && !streamData->isEmpty) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par"); + + if (dbei.flags & DBEF_RTL) { + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlpar"); + dat->bIsAutoRTL = TRUE; + } + else + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrpar"); + + streamData->isEmpty = 0; + + if (dat->bIsAutoRTL) { + if(dbei.flags & DBEF_RTL) { + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrch\\rtlch"); + }else{ + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlch\\ltrch"); + } + } + + if (g_dat->flags&SMF_SHOWICONS) { + int i; + + switch (dbei.eventType) { + case EVENTTYPE_MESSAGE: + if (dbei.flags & DBEF_SENT) { + i = LOGICON_MSG_OUT; + } + else { + i = LOGICON_MSG_IN; + } + break; + case EVENTTYPE_STATUSCHANGE: + i = LOGICON_MSG_NOTICE; + break; + } + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\f0\\fs14"); + while (bufferAlloced - bufferEnd < logIconBmpSize[i]) + bufferAlloced += 1024; + buffer = (char *) realloc(buffer, bufferAlloced); + CopyMemory(buffer + bufferEnd, pLogIconBmpBits[i], logIconBmpSize[i]); + bufferEnd += logIconBmpSize[i]; + } + if (g_dat->flags&SMF_SHOWTIME) { + DBTIMETOSTRINGT dbtts; + TCHAR str[64]; + + if (g_dat->flags&SMF_SHOWSECS) + dbtts.szFormat = g_dat->flags&SMF_SHOWDATE ? _T("d s") : _T("s"); + else + dbtts.szFormat = g_dat->flags&SMF_SHOWDATE ? _T("d t") : _T("t"); + dbtts.cbDest = SIZEOF(str); + dbtts.szDest = str; + CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT, dbei.timestamp, (LPARAM)&dbtts); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, str); + showColon = 1; + } + if (!(g_dat->flags&SMF_HIDENAMES) && dbei.eventType != EVENTTYPE_STATUSCHANGE) { + TCHAR* szName; + CONTACTINFO ci; + ZeroMemory(&ci, sizeof(ci)); + + if (dbei.flags & DBEF_SENT) { + ci.cbSize = sizeof(ci); + ci.hContact = NULL; + ci.szProto = dbei.szModule; + ci.dwFlag = CNF_DISPLAY; + #if defined( _UNICODE ) + ci.dwFlag += CNF_UNICODE; + #endif + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + // CNF_DISPLAY always returns a string type + szName = ( TCHAR* )ci.pszVal; + } + } + else szName = ( TCHAR* ) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName); + showColon = 1; + if (ci.pszVal) + miranda_sys_free(ci.pszVal); + } + + if (showColon) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s :", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON)); + + switch (dbei.eventType) { + case EVENTTYPE_MESSAGE: + { + TCHAR* msg; + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG)); + + #if defined( _UNICODE ) + { + int msglen = strlen((char *) dbei.pBlob) + 1; + if (msglen != (int) dbei.cbBlob) + msg = (TCHAR *) & dbei.pBlob[msglen]; + else { + msg = (TCHAR *) alloca(sizeof(TCHAR) * msglen); + MultiByteToWideChar(CP_ACP, 0, (char *) dbei.pBlob, -1, msg, msglen); + } + } + #else + msg = (BYTE *) dbei.pBlob; + #endif + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg); + break; + } + case EVENTTYPE_STATUSCHANGE: + { + TCHAR *msg, *szName; + CONTACTINFO ci; + ZeroMemory(&ci, sizeof(ci)); + + if (dbei.flags & DBEF_SENT) { + ci.cbSize = sizeof(ci); + ci.hContact = NULL; + ci.szProto = dbei.szModule; + ci.dwFlag = CNF_DISPLAY; + #if defined( _UNICODE ) + ci.dwFlag += CNF_UNICODE; + #endif + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + // CNF_DISPLAY always returns a string type + szName = ( TCHAR* )ci.pszVal; + } + } + else szName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, _T(" ")); + #if defined( _UNICODE ) + { + int msglen = strlen((char *) dbei.pBlob) + 1; + msg = ( TCHAR* )alloca(sizeof(TCHAR) * msglen); + MultiByteToWideChar(CP_ACP, 0, (char *) dbei.pBlob, -1, msg, msglen); + } + #else + msg = (BYTE *) dbei.pBlob; + #endif + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg); + if (ci.pszVal) + miranda_sys_free(ci.pszVal); + break; + } + } + if(dat->bIsAutoRTL) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par"); + + dat->lastEventType = dbei.flags; + free(dbei.pBlob); + return buffer; +} + +static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + struct LogStreamData *dat = (struct LogStreamData *) dwCookie; + + if (dat->buffer == NULL) { + dat->bufferOffset = 0; + switch (dat->stage) { + case STREAMSTAGE_HEADER: + dat->buffer = CreateRTFHeader(dat->dlgDat); + dat->stage = STREAMSTAGE_EVENTS; + break; + case STREAMSTAGE_EVENTS: + if (dat->eventsToInsert) { + do { + dat->buffer = CreateRTFFromDbEvent(dat->dlgDat, dat->hContact, dat->hDbEvent, dat); + if (dat->buffer) + dat->hDbEventLast = dat->hDbEvent; + dat->hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) dat->hDbEvent, 0); + if (--dat->eventsToInsert == 0) + break; + } while (dat->buffer == NULL && dat->hDbEvent); + if (dat->buffer) { + dat->isEmpty = 0; + break; + } + } + dat->stage = STREAMSTAGE_TAIL; + //fall through + case STREAMSTAGE_TAIL: + dat->buffer = CreateRTFTail(dat->dlgDat); + dat->stage = STREAMSTAGE_STOP; + break; + case STREAMSTAGE_STOP: + *pcb = 0; + return 0; + } + dat->bufferLen = lstrlenA(dat->buffer); + } + *pcb = min(cb, dat->bufferLen - dat->bufferOffset); + CopyMemory(pbBuff, dat->buffer + dat->bufferOffset, *pcb); + dat->bufferOffset += *pcb; + if (dat->bufferOffset == dat->bufferLen) { + free(dat->buffer); + dat->buffer = NULL; + } + return 0; +} + +void StreamInEvents(HWND hwndDlg, HANDLE hDbEventFirst, int count, int fAppend) +{ + EDITSTREAM stream = { 0 }; + struct LogStreamData streamData = { 0 }; + struct MessageWindowData *dat = (struct MessageWindowData *) GetWindowLong(hwndDlg, GWL_USERDATA); + CHARRANGE oldSel, sel; + + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_HIDESELECTION, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM) & oldSel); + streamData.hContact = dat->hContact; + streamData.hDbEvent = hDbEventFirst; + streamData.dlgDat = dat; + streamData.eventsToInsert = count; + streamData.isEmpty = fAppend ? GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOG)) == 0 : 1; + stream.pfnCallback = LogStreamInEvents; + stream.dwCookie = (DWORD_PTR) & streamData; + if (fAppend) { + sel.cpMin = sel.cpMax = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOG)); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXSETSEL, 0, (LPARAM) & sel); + } + else dat->bIsFirstAppend = TRUE; + + strcpy(szSep2, fAppend ? "\\par\\sl0" : "\\sl1000"); + strcpy(szSep2_RTL, fAppend ? "\\rtlpar\\rtlmark\\par\\sl1000" : "\\sl1000"); + + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_STREAMIN, fAppend ? SFF_SELECTION | SF_RTF : SFF_SELECTION | SF_RTF, (LPARAM) & stream); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXSETSEL, 0, (LPARAM) & oldSel); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_HIDESELECTION, FALSE, 0); + dat->hDbEventLast = streamData.hDbEventLast; + if (GetWindowLong(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL) + PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); +} + +#define RTFPICTHEADERMAXSIZE 78 +void LoadMsgLogIcons(void) +{ + HICON hIcon; + HBITMAP hBmp, hoBmp; + HDC hdc, hdcMem; + BITMAPINFOHEADER bih = { 0 }; + int widthBytes, i; + RECT rc; + HBRUSH hBkgBrush; + int rtfHeaderSize; + PBYTE pBmpBits; + + g_hImageList = ImageList_Create(10, 10, IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR8 | ILC_MASK, SIZEOF(pLogIconBmpBits), 0); + hBkgBrush = CreateSolidBrush(DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); + bih.biSize = sizeof(bih); + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + bih.biHeight = 10; + bih.biPlanes = 1; + bih.biWidth = 10; + widthBytes = ((bih.biWidth * bih.biBitCount + 31) >> 5) * 4; + rc.top = rc.left = 0; + rc.right = bih.biWidth; + rc.bottom = bih.biHeight; + hdc = GetDC(NULL); + hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight); + hdcMem = CreateCompatibleDC(hdc); + pBmpBits = (PBYTE) malloc(widthBytes * bih.biHeight); + for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) { + switch (i) { + case LOGICON_MSG_IN: + hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_INCOMING)); + ImageList_AddIcon(g_hImageList, hIcon); + hIcon = ImageList_GetIcon(g_hImageList, LOGICON_MSG_IN, ILD_NORMAL); + break; + case LOGICON_MSG_OUT: + hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_OUTGOING)); + ImageList_AddIcon(g_hImageList, hIcon); + hIcon = ImageList_GetIcon(g_hImageList, LOGICON_MSG_OUT, ILD_NORMAL); + break; + case LOGICON_MSG_NOTICE: + hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_NOTICE)); + ImageList_AddIcon(g_hImageList, hIcon); + hIcon = ImageList_GetIcon(g_hImageList, LOGICON_MSG_NOTICE, ILD_NORMAL); + break; + } + pLogIconBmpBits[i] = (PBYTE) malloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2); + //I can't seem to get binary mode working. No matter. + rtfHeaderSize = sprintf(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, 0, hIcon, bih.biWidth, bih.biHeight, 0, NULL, DI_NORMAL); + SelectObject(hdcMem, hoBmp); + GetDIBits(hdc, hBmp, 0, bih.biHeight, pBmpBits, (BITMAPINFO *) & bih, DIB_RGB_COLORS); + DestroyIcon(hIcon); + { + int n; + for (n = 0; n < sizeof(BITMAPINFOHEADER); n++) + sprintf(pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]); + for (n = 0; n < widthBytes * bih.biHeight; n += 4) + sprintf(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] = '}'; + } + free(pBmpBits); + DeleteDC(hdcMem); + DeleteObject(hBmp); + ReleaseDC(NULL, hdc); + DeleteObject(hBkgBrush); +} + +void FreeMsgLogIcons(void) +{ + int i; + for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) + free(pLogIconBmpBits[i]); + ImageList_RemoveAll(g_hImageList); + ImageList_Destroy(g_hImageList); +} diff --git a/miranda-wine/plugins/srmm/msgoptions.c b/miranda-wine/plugins/srmm/msgoptions.c new file mode 100644 index 0000000..4bb89e7 --- /dev/null +++ b/miranda-wine/plugins/srmm/msgoptions.c @@ -0,0 +1,723 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#include "commonheaders.h" +#pragma hdrstop + +extern HINSTANCE g_hInst; + +#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; +} +static fontOptionsList[] = { + {_T("Outgoing messages"), RGB(106, 106, 106), _T("Arial"), DEFAULT_CHARSET, 0, -12}, + {_T("Incoming messages"), RGB(0, 0, 0), _T("Arial"), DEFAULT_CHARSET, 0, -12}, + {_T("Outgoing name"), RGB(89, 89, 89), _T("Arial"), DEFAULT_CHARSET, FONTF_BOLD, -12}, + {_T("Outgoing time"), RGB(0, 0, 0), _T("Terminal"), DEFAULT_CHARSET, FONTF_BOLD, -9}, + {_T("Outgoing colon"), RGB(89, 89, 89), _T("Arial"), DEFAULT_CHARSET, 0, -11}, + {_T("Incoming name"), RGB(215, 0, 0), _T("Arial"), DEFAULT_CHARSET, FONTF_BOLD, -12}, + {_T("Incoming time"), RGB(0, 0, 0), _T("Terminal"), DEFAULT_CHARSET, FONTF_BOLD, -9}, + {_T("Incoming colon"), RGB(215, 0, 0), _T("Arial"), DEFAULT_CHARSET, 0, -11}, + {_T("Message area"), RGB(0, 0, 0), _T("Arial"), DEFAULT_CHARSET, 0, -12}, + {_T("Notices"), RGB(90, 90, 160), _T("Arial"), DEFAULT_CHARSET, 0, -12}, +}; +const int msgDlgFontCount = SIZEOF(fontOptionsList); + +void LoadMsgDlgFont(int i, LOGFONT* lf, COLORREF * colour) +{ + char str[32]; + int style; + DBVARIANT dbv; + + if (colour) { + wsprintfA(str, "SRMFont%dCol", i); + *colour = DBGetContactSettingDword(NULL, SRMMMOD, str, fontOptionsList[i].defColour); + } + if (lf) { + wsprintfA(str, "SRMFont%dSize", i); + lf->lfHeight = (char) DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defSize); + lf->lfWidth = 0; + lf->lfEscapement = 0; + lf->lfOrientation = 0; + wsprintfA(str, "SRMFont%dSty", i); + style = DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defStyle); + lf->lfWeight = style & FONTF_BOLD ? FW_BOLD : FW_NORMAL; + lf->lfItalic = style & FONTF_ITALIC ? 1 : 0; + lf->lfUnderline = 0; + lf->lfStrikeOut = 0; + wsprintfA(str, "SRMFont%dSet", i); + lf->lfCharSet = DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defCharset); + lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf->lfQuality = DEFAULT_QUALITY; + lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + wsprintfA(str, "SRMFont%d", i); + if (DBGetContactSettingTString(NULL, SRMMMOD, str, &dbv)) + lstrcpy(lf->lfFaceName, fontOptionsList[i].szDefFace); + else { + lstrcpyn(lf->lfFaceName, dbv.ptszVal, SIZEOF(lf->lfFaceName)); + DBFreeVariant(&dbv); + } + } +} +struct CheckBoxValues_t +{ + DWORD style; + TCHAR* szDescr; +} +static const statusValues[] = +{ + { PF2_ONLINE, _T("Online") }, + { PF2_SHORTAWAY, _T("Away") }, + { PF2_LONGAWAY, _T("NA") }, + { PF2_LIGHTDND, _T("Occupied") }, + { PF2_HEAVYDND, _T("DND") }, + { PF2_FREECHAT, _T("Free for chat") }, + { PF2_INVISIBLE, _T("Invisible") }, + { PF2_OUTTOLUNCH, _T("Out to lunch") }, + { PF2_ONTHEPHONE, _T("On the phone") } +}; + +static void FillCheckBoxTree(HWND hwndTree, const struct CheckBoxValues_t *values, int nValues, DWORD style) +{ + TVINSERTSTRUCT tvis; + int i; + + tvis.hParent = NULL; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE; + for (i = 0; i < nValues; i++) { + tvis.item.lParam = values[i].style; + tvis.item.pszText = TranslateTS(values[i].szDescr); + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.state = INDEXTOSTATEIMAGEMASK((style & tvis.item.lParam) != 0 ? 2 : 1); + TreeView_InsertItem( hwndTree, &tvis ); +} } + +static DWORD MakeCheckBoxTreeFlags(HWND hwndTree) +{ + DWORD flags = 0; + TVITEM tvi; + + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE; + tvi.hItem = TreeView_GetRoot(hwndTree); + while (tvi.hItem) { + TreeView_GetItem(hwndTree, &tvi); + if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2)) + flags |= tvi.lParam; + tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); + } + return flags; +} + +static BOOL CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + DWORD msgTimeout, avatarHeight; + + TranslateDialogDefault(hwndDlg); + SetWindowLong(GetDlgItem(hwndDlg, IDC_POPLIST), GWL_STYLE, GetWindowLong(GetDlgItem(hwndDlg, IDC_POPLIST), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); + FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_POPLIST), statusValues, SIZEOF(statusValues), + DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, SRMSGDEFSET_POPFLAGS)); + CheckDlgButton(hwndDlg, IDC_SHOWBUTTONLINE, g_dat->flags&SMF_SHOWBTNS); + CheckDlgButton(hwndDlg, IDC_SHOWINFOLINE, g_dat->flags&SMF_SHOWINFO); + CheckDlgButton(hwndDlg, IDC_AUTOMIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)); + CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)); + CheckDlgButton(hwndDlg, IDC_SAVEPERCONTACT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)); + CheckDlgButton(hwndDlg, IDC_CASCADE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE)); + CheckDlgButton(hwndDlg, IDC_SENDONENTER, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER)); + CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)); + CheckDlgButton(hwndDlg, IDC_STATUSWIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)); + + CheckDlgButton(hwndDlg, IDC_AVATARSUPPORT, g_dat->flags&SMF_AVATAR); + CheckDlgButton(hwndDlg, IDC_LIMITAVATARH, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)); + avatarHeight = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT); + SetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, avatarHeight, FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMITAVATARH), IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); + if (!IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)) + EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), FALSE); + else EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); + CheckDlgButton(hwndDlg, IDC_SHOWSENDBTN, g_dat->flags&SMF_SENDBTN); + CheckDlgButton(hwndDlg, IDC_CHARCOUNT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT)); + CheckDlgButton(hwndDlg, IDC_CTRLSUPPORT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT)); + CheckDlgButton(hwndDlg, IDC_DELTEMP, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP)); + msgTimeout = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT); + SetDlgItemInt(hwndDlg, IDC_SECONDS, msgTimeout >= SRMSGSET_MSGTIMEOUT_MIN ? msgTimeout / 1000 : SRMSGDEFSET_MSGTIMEOUT / 1000, FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CASCADE), !IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CTRLSUPPORT), !IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); + return TRUE; + } + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_AUTOMIN: + CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, BST_UNCHECKED); + break; + case IDC_AUTOCLOSE: + CheckDlgButton(hwndDlg, IDC_AUTOMIN, BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_CTRLSUPPORT), !IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); + break; + case IDC_SENDONENTER: + CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, BST_UNCHECKED); + break; + case IDC_SENDONDBLENTER: + CheckDlgButton(hwndDlg, IDC_SENDONENTER, BST_UNCHECKED); + break; + case IDC_SAVEPERCONTACT: + EnableWindow(GetDlgItem(hwndDlg, IDC_CASCADE), !IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); + break; + case IDC_SECONDS: + if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return 0; + break; + case IDC_AVATARSUPPORT: + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMITAVATARH), IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); + if (!IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)) + EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), FALSE); + else EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); + break; + case IDC_LIMITAVATARH: + EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); + break; + case IDC_AVATARHEIGHT: + if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return 0; + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_POPLIST: + if (((LPNMHDR) lParam)->code == NM_CLICK) { + TVHITTESTINFO hti; + hti.pt.x = (short) LOWORD(GetMessagePos()); + hti.pt.y = (short) HIWORD(GetMessagePos()); + ScreenToClient(((LPNMHDR) lParam)->hwndFrom, &hti.pt); + if (TreeView_HitTest(((LPNMHDR) lParam)->hwndFrom, &hti)) + if (hti.flags & TVHT_ONITEMSTATEICON) { + TVITEM tvi; + tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.hItem = hti.hItem; + TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1; + TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + DWORD msgTimeout, avatarHeight; + + DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_POPLIST))); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWBUTTONLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWBUTTONLINE)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWINFOLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWINFOLINE)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOMIN)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CASCADE)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SENDONENTER)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SENDONDBLENTER)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_STATUSWIN)); + + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AVATARENABLE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); + avatarHeight = GetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, NULL, TRUE); + DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, avatarHeight<=0?SRMSGDEFSET_AVHEIGHT:avatarHeight); + + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDBUTTON, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSENDBTN)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CHARCOUNT)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CTRLSUPPORT)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DELTEMP)); + msgTimeout = GetDlgItemInt(hwndDlg, IDC_SECONDS, NULL, TRUE) >= SRMSGSET_MSGTIMEOUT_MIN / 1000 ? GetDlgItemInt(hwndDlg, IDC_SECONDS, NULL, TRUE) * 1000 : SRMSGDEFSET_MSGTIMEOUT; + DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, msgTimeout); + ReloadGlobals(); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); + return TRUE; + } + } + break; + } + break; + case WM_DESTROY: + break; + } + return FALSE; +} + +static BOOL CALLBACK DlgProcLogOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HBRUSH hBkgColourBrush; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + switch (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY)) { + case LOADHISTORY_UNREAD: + CheckDlgButton(hwndDlg, IDC_LOADUNREAD, BST_CHECKED); + break; + case LOADHISTORY_COUNT: + CheckDlgButton(hwndDlg, IDC_LOADCOUNT, BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), TRUE); + break; + case LOADHISTORY_TIME: + CheckDlgButton(hwndDlg, IDC_LOADTIME, BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), TRUE); + break; + } + SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); + SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT)); + SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETRANGE, 0, MAKELONG(12 * 60, 0)); + SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME)); + + CheckDlgButton(hwndDlg, IDC_SHOWLOGICONS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS)); + CheckDlgButton(hwndDlg, IDC_SHOWNAMES, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES)); + CheckDlgButton(hwndDlg, IDC_SHOWTIMES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + CheckDlgButton(hwndDlg, IDC_SHOWSECS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, SRMSGDEFSET_SHOWSECS)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + CheckDlgButton(hwndDlg, IDC_SHOWDATES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE)); + CheckDlgButton(hwndDlg, IDC_SHOWSTATUSCHANGES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, SRMSGDEFSET_BKGCOLOUR); + + hBkgColourBrush = CreateSolidBrush(SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0)); + + { int i; + LOGFONT lf; + for (i = 0; i < SIZEOF(fontOptionsList); i++) { + LoadMsgDlgFont(i, &lf, &fontOptionsList[i].colour); + lstrcpy(fontOptionsList[i].szFace, lf.lfFaceName); + fontOptionsList[i].size = (char) lf.lfHeight; + fontOptionsList[i].style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0); + fontOptionsList[i].charset = lf.lfCharSet; + //I *think* some OSs will fail LB_ADDSTRING if lParam==0 + SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_ADDSTRING, 0, i + 1); + } + SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_SETSEL, TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETCOLOUR, 0, fontOptionsList[0].colour); + SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETDEFAULTCOLOUR, 0, fontOptionsList[0].defColour); + } + return TRUE; + case WM_CTLCOLORLISTBOX: + SetBkColor((HDC) wParam, SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0)); + return (BOOL) hBkgColourBrush; + case WM_MEASUREITEM: + { + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *) lParam; + HFONT hFont, hoFont; + HDC hdc; + SIZE fontSize; + int iItem = mis->itemData - 1; + hFont = CreateFont(fontOptionsList[iItem].size, 0, 0, 0, + fontOptionsList[iItem].style & FONTF_BOLD ? FW_BOLD : FW_NORMAL, + fontOptionsList[iItem].style & FONTF_ITALIC ? 1 : 0, 0, 0, fontOptionsList[iItem].charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fontOptionsList[iItem].szFace); + hdc = GetDC(GetDlgItem(hwndDlg, mis->CtlID)); + hoFont = (HFONT) SelectObject(hdc, hFont); + GetTextExtentPoint32(hdc, fontOptionsList[iItem].szDescr, lstrlen(fontOptionsList[iItem].szDescr), &fontSize); + SelectObject(hdc, hoFont); + ReleaseDC(GetDlgItem(hwndDlg, mis->CtlID), hdc); + DeleteObject(hFont); + mis->itemWidth = fontSize.cx; + mis->itemHeight = fontSize.cy; + return TRUE; + } + case WM_DRAWITEM: + { + DRAWITEMSTRUCT* dis = (DRAWITEMSTRUCT *) lParam; + HFONT hFont, hoFont; + TCHAR* pszText; + int iItem = dis->itemData - 1; + hFont = CreateFont(fontOptionsList[iItem].size, 0, 0, 0, + fontOptionsList[iItem].style & FONTF_BOLD ? FW_BOLD : FW_NORMAL, + fontOptionsList[iItem].style & FONTF_ITALIC ? 1 : 0, 0, 0, fontOptionsList[iItem].charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fontOptionsList[iItem].szFace); + hoFont = (HFONT) SelectObject(dis->hDC, hFont); + SetBkMode(dis->hDC, TRANSPARENT); + FillRect(dis->hDC, &dis->rcItem, hBkgColourBrush); + if (dis->itemState & ODS_SELECTED) + FrameRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT)); + SetTextColor(dis->hDC, fontOptionsList[iItem].colour); + pszText = TranslateTS(fontOptionsList[iItem].szDescr); + TextOut(dis->hDC, dis->rcItem.left, dis->rcItem.top, pszText, lstrlen(pszText)); + SelectObject(dis->hDC, hoFont); + DeleteObject(hFont); + return TRUE; + } + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_LOADUNREAD: + case IDC_LOADCOUNT: + case IDC_LOADTIME: + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); + break; + case IDC_SHOWTIMES: + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + break; + case IDC_BKGCOLOUR: + DeleteObject(hBkgColourBrush); + hBkgColourBrush = CreateSolidBrush(SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0)); + InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, TRUE); + break; + case IDC_FONTLIST: + if (HIWORD(wParam) == LBN_SELCHANGE) { + if (SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELCOUNT, 0, 0) > 1) { + SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETCOLOUR, 0, GetSysColor(COLOR_3DFACE)); + SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT)); + } + else { + int i = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETCURSEL, 0, 0), 0) - 1; + SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETCOLOUR, 0, fontOptionsList[i].colour); + SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETDEFAULTCOLOUR, 0, fontOptionsList[i].defColour); + } + } + if (HIWORD(wParam) != LBN_DBLCLK) + return TRUE; + //fall through + case IDC_CHOOSEFONT: + { + CHOOSEFONT cf = { 0 }; + LOGFONT lf = { 0 }; + int i = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETCURSEL, 0, 0), + 0) - 1; + lf.lfHeight = fontOptionsList[i].size; + lf.lfWeight = fontOptionsList[i].style & FONTF_BOLD ? FW_BOLD : FW_NORMAL; + lf.lfItalic = fontOptionsList[i].style & FONTF_ITALIC ? 1 : 0; + lf.lfCharSet = fontOptionsList[i].charset; + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = DEFAULT_QUALITY; + lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + lstrcpy(lf.lfFaceName, fontOptionsList[i].szFace); + cf.lStructSize = sizeof(cf); + cf.hwndOwner = hwndDlg; + cf.lpLogFont = &lf; + cf.Flags = CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS; + if (ChooseFont(&cf)) { + int selItems[ SIZEOF(fontOptionsList) ]; + int sel, selCount; + + selCount = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELITEMS, SIZEOF(fontOptionsList), (LPARAM) selItems); + for (sel = 0; sel < selCount; sel++) { + i = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, selItems[sel], 0) - 1; + fontOptionsList[i].size = (char) lf.lfHeight; + fontOptionsList[i].style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0); + fontOptionsList[i].charset = lf.lfCharSet; + lstrcpy(fontOptionsList[i].szFace, lf.lfFaceName); + { + MEASUREITEMSTRUCT mis = { 0 }; + mis.CtlID = IDC_FONTLIST; + mis.itemData = i + 1; + SendMessage(hwndDlg, WM_MEASUREITEM, 0, (LPARAM) & mis); + SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_SETITEMHEIGHT, selItems[sel], mis.itemHeight); + } + } + InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, TRUE); + break; + } + return TRUE; + } + case IDC_FONTCOLOUR: + { + int selItems[ SIZEOF(fontOptionsList) ]; + int sel, selCount, i; + + selCount = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELITEMS, SIZEOF(fontOptionsList), (LPARAM) selItems); + for (sel = 0; sel < selCount; sel++) { + i = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, selItems[sel], 0) - 1; + fontOptionsList[i].colour = SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_GETCOLOUR, 0, 0); + } + InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, FALSE); + break; + } + case IDC_LOADCOUNTN: + case IDC_LOADTIMEN: + if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return TRUE; + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + if (IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)) + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_COUNT); + else if (IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)) + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_TIME); + else + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_UNREAD); + DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWLOGICONS)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_SHOWNAMES)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSECS)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSCHANGES)); + DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0)); + + { + int i; + char str[32]; + for (i = 0; i < SIZEOF(fontOptionsList); i++) { + wsprintfA(str, "SRMFont%d", i); + DBWriteContactSettingTString(NULL, SRMMMOD, str, fontOptionsList[i].szFace); + wsprintfA(str, "SRMFont%dSize", i); + DBWriteContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].size); + wsprintfA(str, "SRMFont%dSty", i); + DBWriteContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].style); + wsprintfA(str, "SRMFont%dSet", i); + DBWriteContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].charset); + wsprintfA(str, "SRMFont%dCol", i); + DBWriteContactSettingDword(NULL, SRMMMOD, str, fontOptionsList[i].colour); + } + } + + FreeMsgLogIcons(); + LoadMsgLogIcons(); + ReloadGlobals(); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); + return TRUE; + } + break; + } + break; + case WM_DESTROY: + DeleteObject(hBkgColourBrush); + break; + } + return FALSE; +} + +static ResetCList(HWND hwndDlg) +{ + int i; + + if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_DISABLEGROUPS && !DBGetContactSettingByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT)) + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) FALSE, 0); + else + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETGREYOUTFLAGS, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETLEFTMARGIN, 2, 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKBITMAP, 0, (LPARAM) (HBITMAP) NULL); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETINDENT, 10, 0); + for (i = 0; i <= FONTID_MAX; i++) + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT)); +} + +static void RebuildList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown) +{ + HANDLE hContact, hItem; + BYTE defType = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW); + + if (hItemNew && defType) { + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemNew, 1); + } + if (hItemUnknown && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN)) { + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemUnknown, 1); + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + do { + hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0); + if (hItem && DBGetContactSettingByte(hContact, SRMMMOD, SRMSGSET_TYPING, defType)) { + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItem, 1); + } + } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0)); +} + +static void SaveList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown) +{ + HANDLE hContact, hItem; + + if (hItemNew) { + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemNew, 0) ? 1 : 0)); + } + if (hItemUnknown) { + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemUnknown, 0) ? 1 : 0)); + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + do { + hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0); + if (hItem) { + DBWriteContactSettingByte(hContact, SRMMMOD, SRMSGSET_TYPING, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItem, 0) ? 1 : 0)); + } + } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0)); +} + +static BOOL CALLBACK DlgProcTypeOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hItemNew, hItemUnknown; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + CLCINFOITEM cii = { 0 }; + cii.cbSize = sizeof(cii); + cii.flags = CLCIIF_GROUPFONT | CLCIIF_CHECKBOX; + cii.pszText = TranslateT("** New contacts **"); + hItemNew = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii); + cii.pszText = TranslateT("** Unknown contacts **"); + hItemUnknown = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii); + } + SetWindowLong(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE, GetWindowLong(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE) | (CLS_SHOWHIDDEN) | (CLS_NOHIDEOFFLINE)); + ResetCList(hwndDlg); + RebuildList(hwndDlg, hItemNew, hItemUnknown); + CheckDlgButton(hwndDlg, IDC_SHOWNOTIFY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, SRMSGDEFSET_SHOWTYPING)); + CheckDlgButton(hwndDlg, IDC_TYPEWIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, SRMSGDEFSET_SHOWTYPINGWIN)); + CheckDlgButton(hwndDlg, IDC_TYPETRAY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, SRMSGDEFSET_SHOWTYPINGNOWIN)); + CheckDlgButton(hwndDlg, IDC_NOTIFYTRAY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)); + CheckDlgButton(hwndDlg, IDC_NOTIFYBALLOON, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEWIN), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPETRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); + if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), FALSE); + CheckDlgButton(hwndDlg, IDC_NOTIFYTRAY, BST_CHECKED); + SetWindowTextA(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), Translate("Show balloon popup (unsupported system)")); + } + break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_TYPETRAY: + if (IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)) { + if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), TRUE); + } + else { + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), TRUE); + } + } + else { + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), FALSE); + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_SHOWNOTIFY: + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEWIN), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPETRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY) + && ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)); + //fall-thru + case IDC_TYPEWIN: + case IDC_NOTIFYTRAY: + case IDC_NOTIFYBALLOON: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + break; + case WM_NOTIFY: + switch (((NMHDR *) lParam)->idFrom) { + case IDC_CLIST: + switch (((NMHDR *) lParam)->code) { + case CLN_OPTIONSCHANGED: + ResetCList(hwndDlg); + break; + case CLN_CHECKCHANGED: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + break; + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + SaveList(hwndDlg, hItemNew, hItemUnknown); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TYPEWIN)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_NOTIFYTRAY)); + ReloadGlobals(); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); + } + } + break; + } + break; + } + return FALSE; +} + +static int OptInitialise(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + + odp.cbSize = sizeof(odp); + odp.position = 910000000; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGDLG); + odp.pszTitle = "Messaging"; + odp.pszGroup = "Events"; + odp.pfnDlgProc = DlgProcOptions; + odp.flags = ODPF_BOLDGROUPS; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGLOG); + odp.pszTitle = "Messaging Log"; + odp.pfnDlgProc = DlgProcLogOptions; + odp.nIDBottomSimpleControl = IDC_STMSGLOGGROUP; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGTYPE); + odp.pszTitle = "Typing Notify"; + odp.pfnDlgProc = DlgProcTypeOptions; + odp.nIDBottomSimpleControl = 0; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) & odp); + return 0; +} + +int InitOptions(void) +{ + HookEvent(ME_OPT_INITIALISE, OptInitialise); + return 0; +} diff --git a/miranda-wine/plugins/srmm/msgs.c b/miranda-wine/plugins/srmm/msgs.c new file mode 100644 index 0000000..a8ac9ff --- /dev/null +++ b/miranda-wine/plugins/srmm/msgs.c @@ -0,0 +1,587 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#include "commonheaders.h" +#pragma hdrstop + +static void InitREOleCallback(void); + +HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand; +static HANDLE hEventDbEventAdded, hEventDbSettingChange, hEventContactDeleted; +HANDLE *hMsgMenuItem = NULL, hHookWinEvt=NULL; +int hMsgMenuItemCount = 0; + +extern HINSTANCE g_hInst; + +static int SRMMStatusToPf2(int status) +{ + switch (status) { + case ID_STATUS_ONLINE: + return PF2_ONLINE; + case ID_STATUS_AWAY: + return PF2_SHORTAWAY; + case ID_STATUS_DND: + return PF2_HEAVYDND; + case ID_STATUS_NA: + return PF2_LONGAWAY; + case ID_STATUS_OCCUPIED: + return PF2_LIGHTDND; + case ID_STATUS_FREECHAT: + return PF2_FREECHAT; + case ID_STATUS_INVISIBLE: + return PF2_INVISIBLE; + case ID_STATUS_ONTHEPHONE: + return PF2_ONTHEPHONE; + case ID_STATUS_OUTTOLUNCH: + return PF2_OUTTOLUNCH; + case ID_STATUS_OFFLINE: + return MODEF_OFFLINE; + } + return 0; +} + +static int ReadMessageCommand(WPARAM wParam, LPARAM lParam) +{ + struct NewMessageWindowLParam newData = { 0 }; + HWND hwndExisting; + + hwndExisting = WindowList_Find(g_dat->hMessageWindowList, ((CLISTEVENT *) lParam)->hContact); + newData.hContact = ((CLISTEVENT *) lParam)->hContact; + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); + return 0; +} + +static int MessageEventAdded(WPARAM wParam, LPARAM lParam) +{ + CLISTEVENT cle; + DBEVENTINFO dbei; + HWND hwnd; + + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei); + + if (dbei.flags & DBEF_SENT || dbei.eventType != EVENTTYPE_MESSAGE || dbei.flags & DBEF_READ) + return 0; + + CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1); + /* does a window for the contact exist? */ + hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam); + if (hwnd) { + if (GetForegroundWindow()==hwnd) + SkinPlaySound("RecvMsgActive"); + else SkinPlaySound("RecvMsgInactive"); + return 0; + } + /* new message */ + SkinPlaySound("AlertMsg"); + { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) wParam, 0); + if (szProto && (g_dat->openFlags & SRMMStatusToPf2(CallProtoService(szProto, PS_GETSTATUS, 0, 0)))) { + struct NewMessageWindowLParam newData = { 0 }; + newData.hContact = (HANDLE) wParam; + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); + return 0; + } + } + { + TCHAR toolTip[256], *contactName; + ZeroMemory(&cle, sizeof(cle)); + cle.cbSize = sizeof(cle); + cle.hContact = (HANDLE) wParam; + cle.hDbEvent = (HANDLE) lParam; + cle.flags = CLEF_TCHAR; + cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + cle.pszService = "SRMsg/ReadMessage"; + contactName = (TCHAR*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, GCDNF_TCHAR); + mir_sntprintf(toolTip, SIZEOF(toolTip), TranslateT("Message from %s"), contactName); + cle.ptszTooltip = toolTip; + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle); + } + return 0; +} + +#if defined(_UNICODE) +static int SendMessageCommand_W(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd; + struct NewMessageWindowLParam newData = { 0 }; + + { + /* does the HCONTACT's protocol support IM messages? */ + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (szProto) { + if (!CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND) + return 1; + } + else { + /* unknown contact */ + return 1; + } //if + } + + if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) { + if (lParam) { + HWND hEdit; + hEdit = GetDlgItem(hwnd, IDC_MESSAGE); + SendMessage(hEdit, EM_SETSEL, -1, SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0)); + SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM) (char *) lParam); + } + ShowWindow(hwnd, SW_SHOWNORMAL); + SetForegroundWindow(hwnd); + SetFocus(hwnd); + } + else { + newData.hContact = (HANDLE) wParam; + newData.szInitialText = (const char *) lParam; + newData.isWchar = 1; + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); + } + return 0; +} +#endif + +static int SendMessageCommand(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd; + struct NewMessageWindowLParam newData = { 0 }; + + { + /* does the HCONTACT's protocol support IM messages? */ + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (szProto) { + if (!CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND) + return 1; + } + else { + /* unknown contact */ + return 1; + } //if + } + + if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) { + if (lParam) { + HWND hEdit; + hEdit = GetDlgItem(hwnd, IDC_MESSAGE); + SendMessage(hEdit, EM_SETSEL, -1, SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0)); + SendMessageA(hEdit, EM_REPLACESEL, FALSE, (LPARAM) (char *) lParam); + } + ShowWindow(hwnd, SW_SHOWNORMAL); + SetForegroundWindow(hwnd); + SetFocus(hwnd); + } + else { + newData.hContact = (HANDLE) wParam; + newData.szInitialText = (const char *) lParam; + newData.isWchar = 0; + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); + } + return 0; +} + +static int TypingMessageCommand(WPARAM wParam, LPARAM lParam) +{ + CLISTEVENT *cle = (CLISTEVENT *) lParam; + + if (!cle) + return 0; + SendMessageCommand((WPARAM) cle->hContact, 0); + return 0; +} + +static int TypingMessage(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd; + int foundWin = 0; + + if (!(g_dat->flags&SMF_SHOWTYPING)) + return 0; + if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) { + SendMessage(hwnd, DM_TYPING, 0, lParam); + foundWin = 1; + } + if ((int) lParam && !foundWin && (g_dat->flags&SMF_SHOWTYPINGTRAY)) { + char szTip[256]; + mir_snprintf(szTip, SIZEOF(szTip), Translate("%s is typing a message"), (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, 0)); + + if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY) && !(g_dat->flags&SMF_SHOWTYPINGCLIST)) { + MIRANDASYSTRAYNOTIFY tn; + tn.szProto = NULL; + tn.cbSize = sizeof(tn); + tn.szInfoTitle = Translate("Typing Notification"); + tn.szInfo = szTip; + tn.dwInfoFlags = NIIF_INFO; + tn.uTimeout = 1000 * 4; + CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM) & tn); + } + else { + CLISTEVENT cle; + + ZeroMemory(&cle, sizeof(cle)); + cle.cbSize = sizeof(cle); + cle.hContact = (HANDLE) wParam; + cle.hDbEvent = (HANDLE) 1; + cle.flags = CLEF_ONLYAFEW; + cle.hIcon = g_dat->hIcons[SMF_ICON_TYPING]; + cle.pszService = "SRMsg/TypingMessage"; + cle.pszTooltip = szTip; + CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1); + CallServiceSync(MS_CLIST_ADDEVENT, wParam, (LPARAM) & cle); + } + } + return 0; +} + +static int MessageSettingChanged(WPARAM wParam, LPARAM lParam) +{ + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; + char *szProto; + + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (lstrcmpA(cws->szModule, "CList") && (szProto == NULL || lstrcmpA(cws->szModule, szProto))) + return 0; + WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATETITLE, (WPARAM) cws, 0); + return 0; +} + +static int ContactDeleted(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd; + + if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) { + SendMessage(hwnd, WM_CLOSE, 0, 0); + } + return 0; +} + +static void RestoreUnreadMessageAlerts(void) +{ + CLISTEVENT cle = { 0 }; + DBEVENTINFO dbei = { 0 }; + char toolTip[256]; + int windowAlreadyExists; + HANDLE hDbEvent, hContact; + int autoPopup; + + dbei.cbSize = sizeof(dbei); + cle.cbSize = sizeof(cle); + cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + cle.pszService = "SRMsg/ReadMessage"; + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) { + hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0); + while (hDbEvent) { + autoPopup = 0; + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei); + if (!(dbei.flags & (DBEF_SENT | DBEF_READ)) && dbei.eventType == EVENTTYPE_MESSAGE) { + windowAlreadyExists = WindowList_Find(g_dat->hMessageWindowList, hContact) != NULL; + if (windowAlreadyExists) + continue; + { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto && (g_dat->openFlags & SRMMStatusToPf2(CallProtoService(szProto, PS_GETSTATUS, 0, 0)))) { + autoPopup = 1; + } + } + if (autoPopup && !windowAlreadyExists) { + struct NewMessageWindowLParam newData = { 0 }; + newData.hContact = hContact; + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); + } + else { + cle.hContact = hContact; + cle.hDbEvent = hDbEvent; + mir_snprintf(toolTip, SIZEOF(toolTip), Translate("Message from %s"), (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, 0)); + cle.pszTooltip = toolTip; + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle); + } + } + hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hDbEvent, 0); + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } +} + +static int SplitmsgModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + CLISTMENUITEM mi; + PROTOCOLDESCRIPTOR **protocol; + int protoCount, i; + + LoadMsgLogIcons(); + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.position = -2000090000; + mi.flags = 0; + mi.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + mi.pszName = Translate("&Message"); + mi.pszService = MS_MSG_SENDMESSAGE; + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM) & protoCount, (LPARAM) & protocol); + for (i = 0; i < protoCount; i++) { + if (protocol[i]->type != PROTOTYPE_PROTOCOL) + continue; + if (CallProtoService(protocol[i]->szName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND) { + mi.pszContactOwner = protocol[i]->szName; + hMsgMenuItem = realloc(hMsgMenuItem, (hMsgMenuItemCount + 1) * sizeof(HANDLE)); + hMsgMenuItem[hMsgMenuItemCount++] = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi); + } + } + HookEvent(ME_CLIST_DOUBLECLICKED, SendMessageCommand); + RestoreUnreadMessageAlerts(); + return 0; +} + +int PreshutdownSendRecv(WPARAM wParam, LPARAM lParam) +{ + WindowList_BroadcastAsync(g_dat->hMessageWindowList, WM_CLOSE, 0, 0); + return 0; +} + +int SplitmsgShutdown(void) +{ + DestroyCursor(hCurSplitNS); + DestroyCursor(hCurHyperlinkHand); + DestroyCursor(hCurSplitWE); + UnhookEvent(hEventDbEventAdded); + UnhookEvent(hEventDbSettingChange); + UnhookEvent(hEventContactDeleted); + FreeMsgLogIcons(); + FreeLibrary(GetModuleHandleA("riched20")); + OleUninitialize(); + if (hMsgMenuItem) { + free(hMsgMenuItem); + hMsgMenuItem = NULL; + hMsgMenuItemCount = 0; + } + RichUtil_Unload(); + FreeGlobals(); + return 0; +} + +static int IconsChanged(WPARAM wParam, LPARAM lParam) +{ + if (hMsgMenuItem) { + int j; + CLISTMENUITEM mi; + + mi.cbSize = sizeof(mi); + mi.flags = CMIM_ICON; + mi.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + + for (j = 0; j < hMsgMenuItemCount; j++) { + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hMsgMenuItem[j], (LPARAM) & mi); + } + } + FreeMsgLogIcons(); + LoadMsgLogIcons(); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_REMAKELOG, 0, 0); + // change all the icons + WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATEWINICON, 0, 0); + return 0; +} + +static int GetWindowAPI(WPARAM wParam, LPARAM lParam) +{ + return PLUGIN_MAKE_VERSION(0,0,0,3); +} + +static int GetWindowClass(WPARAM wParam, LPARAM lParam) +{ + char *szBuf = (char*)wParam; + int size = (int)lParam; + mir_snprintf(szBuf, size, SRMMMOD); + return 0; +} + +static int GetWindowData(WPARAM wParam, LPARAM lParam) +{ + MessageWindowInputData *mwid = (MessageWindowInputData*)wParam; + MessageWindowData *mwd = (MessageWindowData*)lParam; + HWND hwnd; + + if (mwid==NULL||mwd==NULL) return 1; + if (mwid->cbSize!=sizeof(MessageWindowInputData)||mwd->cbSize!=sizeof(MessageWindowData)) return 1; + if (mwid->hContact==NULL) return 1; + if (mwid->uFlags!=MSG_WINDOW_UFLAG_MSG_BOTH) return 1; + hwnd = WindowList_Find(g_dat->hMessageWindowList, mwid->hContact); + mwd->uFlags = MSG_WINDOW_UFLAG_MSG_BOTH; + mwd->hwndWindow = hwnd; + mwd->local = 0; + mwd->uState = SendMessage(hwnd, DM_GETWINDOWSTATE, 0, 0); + return 0; +} + +int LoadSendRecvMessageModule(void) +{ + if (LoadLibraryA("riched20.dll") == NULL) { + if (IDYES != + MessageBoxA(0, + Translate + ("Miranda could not load the built-in message module, riched20.dll is missing. If you are using Windows 95 or WINE please make sure you have riched20.dll installed. Press 'Yes' to continue loading Miranda."), + Translate("Information"), MB_YESNO | MB_ICONINFORMATION)) + return 1; + return 0; + } + InitGlobals(); + RichUtil_Load(); + OleInitialize(NULL); + InitREOleCallback(); + InitOptions(); + hEventDbEventAdded = HookEvent(ME_DB_EVENT_ADDED, MessageEventAdded); + hEventDbSettingChange = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, MessageSettingChanged); + hEventContactDeleted = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); + HookEvent(ME_SYSTEM_MODULESLOADED, SplitmsgModulesLoaded); + HookEvent(ME_SKIN_ICONSCHANGED, IconsChanged); + HookEvent(ME_PROTO_CONTACTISTYPING, TypingMessage); + HookEvent(ME_SYSTEM_PRESHUTDOWN, PreshutdownSendRecv); + CreateServiceFunction(MS_MSG_SENDMESSAGE, SendMessageCommand); +#if defined(_UNICODE) + CreateServiceFunction(MS_MSG_SENDMESSAGE "W", SendMessageCommand_W); +#endif + CreateServiceFunction(MS_MSG_GETWINDOWAPI, GetWindowAPI); + CreateServiceFunction(MS_MSG_GETWINDOWCLASS, GetWindowClass); + CreateServiceFunction(MS_MSG_GETWINDOWDATA, GetWindowData); + CreateServiceFunction("SRMsg/ReadMessage", ReadMessageCommand); + CreateServiceFunction("SRMsg/TypingMessage", TypingMessageCommand); + hHookWinEvt=CreateHookableEvent(ME_MSG_WINDOWEVENT); + SkinAddNewSoundEx("RecvMsgActive", Translate("Messages"), Translate("Incoming (Focused Window)")); + SkinAddNewSoundEx("RecvMsgInactive", Translate("Messages"), Translate("Incoming (Unfocused Window)")); + SkinAddNewSoundEx("AlertMsg", Translate("Messages"), Translate("Incoming (New Session)")); + SkinAddNewSoundEx("SendMsg", Translate("Messages"), Translate("Outgoing")); + hCurSplitNS = LoadCursor(NULL, IDC_SIZENS); + hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE); + hCurHyperlinkHand = LoadCursor(NULL, IDC_HAND); + if (hCurHyperlinkHand == NULL) + hCurHyperlinkHand = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_HYPERLINKHAND)); + return 0; +} + +static IRichEditOleCallbackVtbl reOleCallbackVtbl; +struct CREOleCallback reOleCallback; + +static STDMETHODIMP_(ULONG) CREOleCallback_QueryInterface(struct CREOleCallback *lpThis, REFIID riid, LPVOID * ppvObj) +{ + if (IsEqualIID(riid, &IID_IRichEditOleCallback)) { + *ppvObj = lpThis; + lpThis->lpVtbl->AddRef((IRichEditOleCallback *) lpThis); + return S_OK; + } + *ppvObj = NULL; + return E_NOINTERFACE; +} + +static STDMETHODIMP_(ULONG) CREOleCallback_AddRef(struct CREOleCallback *lpThis) +{ + if (lpThis->refCount == 0) { + if (S_OK != StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &lpThis->pictStg)) + lpThis->pictStg = NULL; + lpThis->nextStgId = 0; + } + return ++lpThis->refCount; +} + +static STDMETHODIMP_(ULONG) CREOleCallback_Release(struct CREOleCallback *lpThis) +{ + if (--lpThis->refCount == 0) { + if (lpThis->pictStg) + lpThis->pictStg->lpVtbl->Release(lpThis->pictStg); + } + return lpThis->refCount; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_ContextSensitiveHelp(struct CREOleCallback *lpThis, BOOL fEnterMode) +{ + return S_OK; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_DeleteObject(struct CREOleCallback *lpThis, LPOLEOBJECT lpoleobj) +{ + return S_OK; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_GetClipboardData(struct CREOleCallback *lpThis, CHARRANGE * lpchrg, DWORD reco, LPDATAOBJECT * lplpdataobj) +{ + return E_NOTIMPL; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_GetContextMenu(struct CREOleCallback *lpThis, WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE * lpchrg, HMENU * lphmenu) +{ + return E_INVALIDARG; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_GetDragDropEffect(struct CREOleCallback *lpThis, BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect) +{ + return S_OK; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_GetInPlaceContext(struct CREOleCallback *lpThis, LPOLEINPLACEFRAME * lplpFrame, LPOLEINPLACEUIWINDOW * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo) +{ + return E_INVALIDARG; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_GetNewStorage(struct CREOleCallback *lpThis, LPSTORAGE * lplpstg) +{ + WCHAR szwName[64]; + char szName[64]; + wsprintfA(szName, "s%u", lpThis->nextStgId); + MultiByteToWideChar(CP_ACP, 0, szName, -1, szwName, SIZEOF(szwName)); + if (lpThis->pictStg == NULL) + return STG_E_MEDIUMFULL; + return lpThis->pictStg->lpVtbl->CreateStorage(lpThis->pictStg, szwName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg); +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_QueryAcceptData(struct CREOleCallback *lpThis, LPDATAOBJECT lpdataobj, CLIPFORMAT * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict) +{ + return S_OK; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_QueryInsertObject(struct CREOleCallback *lpThis, LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp) +{ + return S_OK; +} + +static STDMETHODIMP_(HRESULT) CREOleCallback_ShowContainerUI(struct CREOleCallback *lpThis, BOOL fShow) +{ + return S_OK; +} + +static void InitREOleCallback(void) +{ + reOleCallback.lpVtbl = &reOleCallbackVtbl; + reOleCallback.lpVtbl->AddRef = (ULONG(__stdcall *) (IRichEditOleCallback *)) CREOleCallback_AddRef; + reOleCallback.lpVtbl->Release = (ULONG(__stdcall *) (IRichEditOleCallback *)) CREOleCallback_Release; + reOleCallback.lpVtbl->QueryInterface = (ULONG(__stdcall *) (IRichEditOleCallback *, REFIID, PVOID *)) CREOleCallback_QueryInterface; + reOleCallback.lpVtbl->ContextSensitiveHelp = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL)) CREOleCallback_ContextSensitiveHelp; + reOleCallback.lpVtbl->DeleteObject = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPOLEOBJECT)) CREOleCallback_DeleteObject; + reOleCallback.lpVtbl->GetClipboardData = (HRESULT(__stdcall *) (IRichEditOleCallback *, CHARRANGE *, DWORD, LPDATAOBJECT *)) CREOleCallback_GetClipboardData; + reOleCallback.lpVtbl->GetContextMenu = (HRESULT(__stdcall *) (IRichEditOleCallback *, WORD, LPOLEOBJECT, CHARRANGE *, HMENU *)) CREOleCallback_GetContextMenu; + reOleCallback.lpVtbl->GetDragDropEffect = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL, DWORD, LPDWORD)) CREOleCallback_GetDragDropEffect; + reOleCallback.lpVtbl->GetInPlaceContext = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPOLEINPLACEFRAME *, LPOLEINPLACEUIWINDOW *, LPOLEINPLACEFRAMEINFO)) + CREOleCallback_GetInPlaceContext; + reOleCallback.lpVtbl->GetNewStorage = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPSTORAGE *)) CREOleCallback_GetNewStorage; + reOleCallback.lpVtbl->QueryAcceptData = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPDATAOBJECT, CLIPFORMAT *, DWORD, BOOL, HGLOBAL)) CREOleCallback_QueryAcceptData; + reOleCallback.lpVtbl->QueryInsertObject = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPCLSID, LPSTORAGE, LONG)) CREOleCallback_QueryInsertObject; + reOleCallback.lpVtbl->ShowContainerUI = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL)) CREOleCallback_ShowContainerUI; + reOleCallback.refCount = 0; +} diff --git a/miranda-wine/plugins/srmm/msgs.h b/miranda-wine/plugins/srmm/msgs.h new file mode 100644 index 0000000..538f8b5 --- /dev/null +++ b/miranda-wine/plugins/srmm/msgs.h @@ -0,0 +1,211 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#ifndef SRMM_MSGS_H +#define SRMM_MSGS_H + +#include +#include +#define MSGERROR_CANCEL 0 +#define MSGERROR_RETRY 1 + +struct NewMessageWindowLParam +{ + HANDLE hContact; + const char *szInitialText; + int isWchar; +}; + +struct MessageWindowData +{ + HANDLE hContact; + HANDLE hDbEventFirst, hDbEventLast; + HANDLE hSendId; + int sendCount; + HBRUSH hBkgBrush; + int splitterPos, originalSplitterPos; + char *sendBuffer; + SIZE minEditBoxSize; + RECT minEditInit; + int lineHeight; + int windowWasCascaded; + int nFlash; + int nFlashMax; + int nLabelRight; + int nTypeSecs; + int nTypeMode; + int avatarWidth; + int avatarHeight; + int limitAvatarH; + HBITMAP avatarPic; + DWORD nLastTyping; + int showTyping; + HWND hwndStatus; + DWORD lastMessage; + char *szProto; + WORD wStatus; + WORD wOldStatus; + TCmdList *cmdList; + TCmdList *cmdListCurrent; + int bIsRtl, bIsFirstAppend, bIsAutoRTL; + int lastEventType; +}; + +#define HM_EVENTSENT (WM_USER+10) +#define DM_REMAKELOG (WM_USER+11) +#define HM_DBEVENTADDED (WM_USER+12) +#define DM_CASCADENEWWINDOW (WM_USER+13) +#define DM_OPTIONSAPPLIED (WM_USER+14) +#define DM_SPLITTERMOVED (WM_USER+15) +#define DM_UPDATETITLE (WM_USER+16) +#define DM_APPENDTOLOG (WM_USER+17) +#define DM_ERRORDECIDED (WM_USER+18) +#define DM_SCROLLLOGTOBOTTOM (WM_USER+19) +#define DM_TYPING (WM_USER+20) +#define DM_UPDATEWINICON (WM_USER+21) +#define DM_UPDATELASTMESSAGE (WM_USER+22) +#define DM_USERNAMETOCLIP (WM_USER+23) +#define DM_AVATARSIZECHANGE (WM_USER+24) +#define DM_AVATARCALCSIZE (WM_USER+25) +#define DM_GETAVATAR (WM_USER+26) +#define DM_UPDATESIZEBAR (WM_USER+27) +#define HM_AVATARACK (WM_USER+28) +#define HM_ACKEVENT (WM_USER+29) +#define DM_GETWINDOWSTATE (WM_USER+30) + +#define EVENTTYPE_STATUSCHANGE 25368 + +struct CREOleCallback +{ + IRichEditOleCallbackVtbl *lpVtbl; + unsigned refCount; + IStorage *pictStg; + int nextStgId; +}; + +BOOL CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int InitOptions(void); +BOOL CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int DbEventIsShown(DBEVENTINFO * dbei, struct MessageWindowData *dat); +void StreamInEvents(HWND hwndDlg, HANDLE hDbEventFirst, int count, int fAppend); +void LoadMsgLogIcons(void); +void FreeMsgLogIcons(void); + +#define MSGFONTID_MYMSG 0 +#define MSGFONTID_YOURMSG 1 +#define MSGFONTID_MYNAME 2 +#define MSGFONTID_MYTIME 3 +#define MSGFONTID_MYCOLON 4 +#define MSGFONTID_YOURNAME 5 +#define MSGFONTID_YOURTIME 6 +#define MSGFONTID_YOURCOLON 7 +#define MSGFONTID_MESSAGEAREA 8 +#define MSGFONTID_NOTICE 9 + +void LoadMsgDlgFont(int i, LOGFONT* lf, COLORREF* colour); +extern const int msgDlgFontCount; + +#define LOADHISTORY_UNREAD 0 +#define LOADHISTORY_COUNT 1 +#define LOADHISTORY_TIME 2 + +#define SRMMMOD "SRMM" + +#define SRMSGSET_POPFLAGS "PopupFlags" +#define SRMSGDEFSET_POPFLAGS 0 +#define SRMSGSET_SHOWBUTTONLINE "ShowButtonLine" +#define SRMSGDEFSET_SHOWBUTTONLINE 1 +#define SRMSGSET_SHOWINFOLINE "ShowInfoLine" +#define SRMSGDEFSET_SHOWINFOLINE 1 +#define SRMSGSET_AUTOMIN "AutoMin" +#define SRMSGDEFSET_AUTOMIN 0 +#define SRMSGSET_AUTOCLOSE "AutoClose" +#define SRMSGDEFSET_AUTOCLOSE 0 +#define SRMSGSET_SAVEPERCONTACT "SavePerContact" +#define SRMSGDEFSET_SAVEPERCONTACT 0 +#define SRMSGSET_CASCADE "Cascade" +#define SRMSGDEFSET_CASCADE 1 +#define SRMSGSET_SENDONENTER "SendOnEnter" +#define SRMSGDEFSET_SENDONENTER 1 +#define SRMSGSET_SENDONDBLENTER "SendOnDblEnter" +#define SRMSGDEFSET_SENDONDBLENTER 0 +#define SRMSGSET_STATUSICON "UseStatusWinIcon" +#define SRMSGDEFSET_STATUSICON 0 +#define SRMSGSET_SENDBUTTON "UseSendButton" +#define SRMSGDEFSET_SENDBUTTON 0 +#define SRMSGSET_CHARCOUNT "ShowCharCount" +#define SRMSGDEFSET_CHARCOUNT 0 +#define SRMSGSET_CTRLSUPPORT "SupportCtrlUpDn" +#define SRMSGDEFSET_CTRLSUPPORT 1 +#define SRMSGSET_DELTEMP "DeleteTempCont" +#define SRMSGDEFSET_DELTEMP 0 +#define SRMSGSET_MSGTIMEOUT "MessageTimeout" +#define SRMSGDEFSET_MSGTIMEOUT 10000 +#define SRMSGSET_MSGTIMEOUT_MIN 4000 // minimum value (4 seconds) +#define SRMSGSET_FLASHCOUNT "FlashMax" +#define SRMSGDEFSET_FLASHCOUNT 5 + +#define SRMSGSET_LOADHISTORY "LoadHistory" +#define SRMSGDEFSET_LOADHISTORY LOADHISTORY_UNREAD +#define SRMSGSET_LOADCOUNT "LoadCount" +#define SRMSGDEFSET_LOADCOUNT 10 +#define SRMSGSET_LOADTIME "LoadTime" +#define SRMSGDEFSET_LOADTIME 10 + +#define SRMSGSET_SHOWLOGICONS "ShowLogIcon" +#define SRMSGDEFSET_SHOWLOGICONS 1 +#define SRMSGSET_HIDENAMES "HideNames" +#define SRMSGDEFSET_HIDENAMES 1 +#define SRMSGSET_SHOWTIME "ShowTime" +#define SRMSGDEFSET_SHOWTIME 1 +#define SRMSGSET_SHOWSECS "ShowSeconds" +#define SRMSGDEFSET_SHOWSECS 1 +#define SRMSGSET_SHOWDATE "ShowDate" +#define SRMSGDEFSET_SHOWDATE 0 +#define SRMSGSET_SHOWSTATUSCH "ShowStatusChanges" +#define SRMSGDEFSET_SHOWSTATUSCH 1 +#define SRMSGSET_BKGCOLOUR "BkgColour" +#define SRMSGDEFSET_BKGCOLOUR GetSysColor(COLOR_WINDOW) + +#define SRMSGSET_TYPING "SupportTyping" +#define SRMSGSET_TYPINGNEW "DefaultTyping" +#define SRMSGDEFSET_TYPINGNEW 1 +#define SRMSGSET_TYPINGUNKNOWN "UnknownTyping" +#define SRMSGDEFSET_TYPINGUNKNOWN 0 +#define SRMSGSET_SHOWTYPING "ShowTyping" +#define SRMSGDEFSET_SHOWTYPING 1 +#define SRMSGSET_SHOWTYPINGWIN "ShowTypingWin" +#define SRMSGDEFSET_SHOWTYPINGWIN 1 +#define SRMSGSET_SHOWTYPINGNOWIN "ShowTypingTray" +#define SRMSGDEFSET_SHOWTYPINGNOWIN 0 +#define SRMSGSET_SHOWTYPINGCLIST "ShowTypingClist" +#define SRMSGDEFSET_SHOWTYPINGCLIST 1 + + +#define SRMSGSET_AVATARENABLE "AvatarEnable" +#define SRMSGDEFSET_AVATARENABLE 1 +#define SRMSGSET_LIMITAVHEIGHT "AvatarLimitHeight" +#define SRMSGDEFSET_LIMITAVHEIGHT 1 +#define SRMSGSET_AVHEIGHT "AvatarHeight" +#define SRMSGDEFSET_AVHEIGHT 60 +#define SRMSGSET_AVATAR "Avatar" + +#endif diff --git a/miranda-wine/plugins/srmm/msgtimedout.c b/miranda-wine/plugins/srmm/msgtimedout.c new file mode 100644 index 0000000..5539ff0 --- /dev/null +++ b/miranda-wine/plugins/srmm/msgtimedout.c @@ -0,0 +1,71 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ + +#include "commonheaders.h" +#pragma hdrstop +#include "msgs.h" + +BOOL CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + char* pszError = ( char* )GetWindowLong(hwndDlg, GWL_USERDATA); + + switch (msg) { + case WM_INITDIALOG: + { + RECT rc, rcParent; + + SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) pszError); + + TranslateDialogDefault(hwndDlg); + + if (lParam) { + pszError = (char *) lParam; + if (!pszError||!strlen(pszError)) + pszError = strdup(Translate("An unknown error has occured.")); + SetDlgItemTextA(hwndDlg, IDC_ERRORTEXT, pszError); + } + + GetWindowRect(hwndDlg, &rc); + GetWindowRect(GetParent(hwndDlg), &rcParent); + SetWindowPos(hwndDlg, 0, (rcParent.left + rcParent.right - (rc.right - rc.left)) / 2, (rcParent.top + rcParent.bottom - (rc.bottom - rc.top)) / 2, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + if (pszError) + free(pszError); + SendMessage(GetParent(hwndDlg), DM_ERRORDECIDED, MSGERROR_RETRY, 0); + DestroyWindow(hwndDlg); + break; + case IDCANCEL: + if (pszError) + free(pszError); + SendMessage(GetParent(hwndDlg), DM_ERRORDECIDED, MSGERROR_CANCEL, 0); + DestroyWindow(hwndDlg); + break; + } + break; + } + return FALSE; +} diff --git a/miranda-wine/plugins/srmm/res/add.ico b/miranda-wine/plugins/srmm/res/add.ico new file mode 100644 index 0000000..2efc4dc Binary files /dev/null and b/miranda-wine/plugins/srmm/res/add.ico differ diff --git a/miranda-wine/plugins/srmm/res/clock.ico b/miranda-wine/plugins/srmm/res/clock.ico new file mode 100644 index 0000000..83b8abf Binary files /dev/null and b/miranda-wine/plugins/srmm/res/clock.ico differ diff --git a/miranda-wine/plugins/srmm/res/details.ico b/miranda-wine/plugins/srmm/res/details.ico new file mode 100644 index 0000000..a2c16ae Binary files /dev/null and b/miranda-wine/plugins/srmm/res/details.ico differ diff --git a/miranda-wine/plugins/srmm/res/downarrow.ico b/miranda-wine/plugins/srmm/res/downarrow.ico new file mode 100644 index 0000000..76a473c Binary files /dev/null and b/miranda-wine/plugins/srmm/res/downarrow.ico differ diff --git a/miranda-wine/plugins/srmm/res/history.ico b/miranda-wine/plugins/srmm/res/history.ico new file mode 100644 index 0000000..2749b50 Binary files /dev/null and b/miranda-wine/plugins/srmm/res/history.ico differ diff --git a/miranda-wine/plugins/srmm/res/incoming.ico b/miranda-wine/plugins/srmm/res/incoming.ico new file mode 100644 index 0000000..fabbf97 Binary files /dev/null and b/miranda-wine/plugins/srmm/res/incoming.ico differ diff --git a/miranda-wine/plugins/srmm/res/notice.ico b/miranda-wine/plugins/srmm/res/notice.ico new file mode 100644 index 0000000..23527a9 Binary files /dev/null and b/miranda-wine/plugins/srmm/res/notice.ico differ diff --git a/miranda-wine/plugins/srmm/res/outgoing.ico b/miranda-wine/plugins/srmm/res/outgoing.ico new file mode 100644 index 0000000..f772ab3 Binary files /dev/null and b/miranda-wine/plugins/srmm/res/outgoing.ico differ diff --git a/miranda-wine/plugins/srmm/res/typing.ico b/miranda-wine/plugins/srmm/res/typing.ico new file mode 100644 index 0000000..6dd597e Binary files /dev/null and b/miranda-wine/plugins/srmm/res/typing.ico differ diff --git a/miranda-wine/plugins/srmm/resource.h b/miranda-wine/plugins/srmm/resource.h new file mode 100644 index 0000000..d1e7ce3 --- /dev/null +++ b/miranda-wine/plugins/srmm/resource.h @@ -0,0 +1,93 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDD_MSGSENDERROR 102 +#define IDI_USERDETAILS 160 +#define IDI_HISTORY 174 +#define IDR_CONTEXT 180 +#define IDC_DROP 183 +#define IDI_ADDCONTACT 210 +#define IDC_HYPERLINKHAND 214 +#define IDC_DROPUSER 215 +#define IDD_OPT_MSGDLG 243 +#define IDD_MSG 244 +#define IDD_OPT_MSGLOG 245 +#define IDI_DOWNARROW 264 +#define IDI_TYPING 268 +#define IDD_OPT_MSGTYPE 275 +#define IDI_INCOMING 276 +#define IDI_OUTGOING 277 +#define IDI_NOTICE 282 +#define IDC_LOG 1001 +#define IDC_MESSAGE 1002 +#define IDC_AUTOCLOSE 1004 +#define IDC_AUTOMIN 1005 +#define IDC_NAME 1009 +#define IDC_SPLITTER 1017 +#define IDC_SHOWNAMES 1024 +#define IDC_SHOWSENDBTN 1029 +#define IDC_SHOWLOGICONS 1032 +#define IDC_SHOWTIMES 1033 +#define IDC_SHOWDATES 1034 +#define IDC_CLIST 1035 +#define IDC_SHOWSTATUSCHANGES 1035 +#define IDC_SAVEPERCONTACT 1037 +#define IDC_LOADCOUNTN 1039 +#define IDC_LOADCOUNTSPIN 1040 +#define IDC_SHOWINFOLINE 1041 +#define IDC_SHOWBUTTONLINE 1042 +#define IDC_LOADUNREAD 1043 +#define IDC_SENDONENTER 1043 +#define IDC_LOADCOUNT 1044 +#define IDC_SENDONDBLENTER 1044 +#define IDC_LOADTIMEN 1045 +#define IDC_LOADTIMESPIN 1046 +#define IDC_LOADTIME 1047 +#define IDC_FONTLIST 1048 +#define IDC_CHOOSEFONT 1049 +#define IDC_STMINSOLD 1051 +#define IDC_DETAILS 1069 +#define IDC_ADD 1070 +#define IDC_USERMENU 1071 +#define IDC_HISTORY 1080 +#define IDC_BKGCOLOUR 1269 +#define IDC_FONTCOLOUR 1282 +#define IDC_STMSGLOGGROUP 1442 +#define IDC_PROTOCOL 1580 +#define IDC_ERRORTEXT 1596 +#define IDC_SHOWNOTIFY 1600 +#define IDC_STATUSWIN 1601 +#define IDC_TYPEWIN 1602 +#define IDC_CHARCOUNT 1603 +#define IDC_TYPETRAY 1603 +#define IDC_CASCADE 1604 +#define IDC_SECONDS 1605 +#define IDC_NOTIFYTRAY 1606 +#define IDC_NOTIFYBALLOON 1607 +#define IDC_CTRLSUPPORT 1608 +#define IDC_DELTEMP 1609 +#define IDC_AVATAR 1610 +#define IDC_AVATARSUPPORT 1611 +#define IDC_LIMITAVATARH 1612 +#define IDC_AVATARHEIGHT 1613 +#define IDC_SHOWSECS 1614 +#define IDC_POPLIST 1616 +#define IDM_COPY 40001 +#define IDM_COPYALL 40011 +#define IDM_SELECTALL 40012 +#define IDM_CLEAR 40013 +#define IDM_OPENNEW 40014 +#define IDM_OPENEXISTING 40015 +#define IDM_COPYLINK 40016 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 286 +#define _APS_NEXT_COMMAND_VALUE 40019 +#define _APS_NEXT_CONTROL_VALUE 1617 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/miranda-wine/plugins/srmm/resource.rc b/miranda-wine/plugins/srmm/resource.rc new file mode 100644 index 0000000..3dfc7e8 --- /dev/null +++ b/miranda-wine/plugins/srmm/resource.rc @@ -0,0 +1,356 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include +#include "../../include/statusmodes.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT_MSGDLG DIALOGEX 0, 0, 312, 234 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Message Window Options",IDC_STATIC,2,0,310,231 + CONTROL "Close the message window on send",IDC_AUTOCLOSE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,8,58,212,10 + CONTROL "Minimize the message window on send",IDC_AUTOMIN,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,8,70,221,10 + CONTROL "Use the contact's status icon as the window icon", + IDC_STATUSWIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,82, + 273,10 + CONTROL "Save the window size and location individually for each contact", + IDC_SAVEPERCONTACT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 8,94,300,10 + CONTROL "Cascade new windows",IDC_CASCADE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,8,106,136,10 + CONTROL "Show 'Send' button",IDC_SHOWSENDBTN,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,8,174,135,10 + CONTROL "Show username on top row",IDC_SHOWINFOLINE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,8,187,138,10 + CONTROL "Show toolbar buttons on top row",IDC_SHOWBUTTONLINE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,200,137,10 + CONTROL "Send message on double 'Enter'",IDC_SENDONDBLENTER, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,148,174,137,10 + CONTROL "Send message on 'Enter'",IDC_SENDONENTER,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,148,187,137,10 + CONTROL "Show character count",IDC_CHARCOUNT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,148,200,133,10 + LTEXT "Show warning when message has not been received after", + IDC_STATIC,8,216,211,8 + EDITTEXT IDC_SECONDS,223,214,25,12,ES_AUTOHSCROLL + LTEXT "seconds.",IDC_STATIC,253,216,44,8 + CONTROL "Support control up/down in message area to show previously sent messages", + IDC_CTRLSUPPORT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8, + 118,298,10 + CONTROL "Delete temporary contacts when closing message window", + IDC_DELTEMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,130, + 287,10 + CONTROL "Enable avatar support in the message window", + IDC_AVATARSUPPORT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 8,143,279,10 + CONTROL "Limit avatar height to ",IDC_LIMITAVATARH,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,157,106,10 + EDITTEXT IDC_AVATARHEIGHT,148,156,28,13,ES_AUTOHSCROLL + LTEXT "pixels.",IDC_STATIC,181,158,35,8 + CONTROL "Tree1",IDC_POPLIST,"SysTreeView32",TVS_DISABLEDRAGDROP | + TVS_NOTOOLTIPS | TVS_NONEVENHEIGHT | WS_BORDER | + WS_TABSTOP,163,14,98,42 + LTEXT "Automatically popup window when:",IDC_STATIC,10,15,141, + 13 +END + +IDD_MSGSENDERROR DIALOGEX 0, 0, 187, 97 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_SETFONT +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Send Error" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "An error has occured. The protocol reported the following error:", + IDC_STATIC,5,5,177,28 + DEFPUSHBUTTON "Try again",IDOK,22,78,63,14 + PUSHBUTTON "Cancel",IDCANCEL,104,78,61,14 + EDITTEXT IDC_ERRORTEXT,5,37,177,35,ES_MULTILINE | ES_READONLY | + WS_VSCROLL +END + +IDD_MSG DIALOGEX 0, 0, 184, 78 +STYLE DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | + WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | DS_SETFONT +EXSTYLE WS_EX_ACCEPTFILES +CAPTION "Message Session" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_MESSAGE,1,49,141,13,ES_MULTILINE | ES_AUTOVSCROLL | + ES_WANTRETURN | WS_VSCROLL,WS_EX_ACCEPTFILES + DEFPUSHBUTTON "&Send",IDOK,143,48,39,15 + PUSHBUTTON "Close",IDCANCEL,129,0,54,15,NOT WS_VISIBLE + CONTROL "",IDC_PROTOCOL,"Button",BS_OWNERDRAW,2,5,12,12 + CONTROL "",IDC_NAME,"MButtonClass",WS_TABSTOP,15,2,95,14, + 0x18000000L + CONTROL "",IDC_ADD,"MButtonClass",WS_TABSTOP,110,2,16,14, + 0x18000000L + CONTROL "",IDC_USERMENU,"MButtonClass",WS_TABSTOP,128,2,16,14, + 0x18000000L + CONTROL "&D",IDC_DETAILS,"MButtonClass",WS_TABSTOP,146,2,16,14, + 0x18000000L + CONTROL "&H",IDC_HISTORY,"MButtonClass",WS_TABSTOP,164,2,16,14, + 0x18000000L + CONTROL "",IDC_LOG,"RichEdit20A",WS_VSCROLL | WS_TABSTOP | 0x844, + 1,18,181,26,WS_EX_CLIENTEDGE + CONTROL "",IDC_SPLITTER,"Static",SS_ENHMETAFILE,0,45,183,2 + CONTROL "",IDC_AVATAR,"Button",BS_OWNERDRAW | NOT WS_VISIBLE,1, + 50,1,13 +END + +IDD_OPT_MSGLOG DIALOGEX 0, 0, 306, 229 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Message Window Event Log",IDC_STMSGLOGGROUP,0,0,158,158 + CONTROL "Show icons",IDC_SHOWLOGICONS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,12,146,10 + CONTROL "Show names",IDC_SHOWNAMES,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,28,146,10 + CONTROL "Show timestamp",IDC_SHOWTIMES,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,44,146,10 + CONTROL "Show dates",IDC_SHOWDATES,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,21,75,135,10 + GROUPBOX "Fonts",IDC_STATIC,163,0,143,158 + LTEXT "Background colour:",IDC_STATIC,169,16,81,8 + CONTROL "",IDC_BKGCOLOUR,"ColourPicker",WS_TABSTOP,261,14,39,12 + LISTBOX IDC_FONTLIST,169,31,131,82,LBS_OWNERDRAWVARIABLE | + LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | + WS_TABSTOP + CONTROL "",IDC_FONTCOLOUR,"ColourPicker",WS_TABSTOP,169,117,57, + 14 + PUSHBUTTON "Choose font...",IDC_CHOOSEFONT,243,117,57,14 + GROUPBOX "Load History Events",IDC_STATIC,0,163,306,66 + CONTROL "Load unread events only",IDC_LOADUNREAD,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,10,177,138,10 + CONTROL "Load number of previous events",IDC_LOADCOUNT,"Button", + BS_AUTORADIOBUTTON,10,193,138,10 + EDITTEXT IDC_LOADCOUNTN,148,192,33,12,ES_RIGHT | ES_NUMBER | + WS_DISABLED + CONTROL "Spin1",IDC_LOADCOUNTSPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK | + WS_DISABLED,170,191,10,14 + CONTROL "Load previous events less than",IDC_LOADTIME,"Button", + BS_AUTORADIOBUTTON,10,209,138,10 + EDITTEXT IDC_LOADTIMEN,148,208,33,12,ES_RIGHT | ES_NUMBER | + WS_DISABLED + CONTROL "Spin1",IDC_LOADTIMESPIN,"msctls_updown32", + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK | + WS_DISABLED,170,207,10,14 + LTEXT "minutes old",IDC_STMINSOLD,185,210,90,8,WS_DISABLED + CTEXT "Select multiple fonts by dragging or by using the control key", + IDC_STATIC,169,135,131,16 + CONTROL "Show status changes",IDC_SHOWSTATUSCHANGES,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,92,146,10 + CONTROL "Show seconds",IDC_SHOWSECS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,21,59,127,10 +END + +IDD_OPT_MSGTYPE DIALOGEX 0, 0, 283, 252 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Typing Notification Options",IDC_STATIC,7,7,269,238 + CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x348,18,42,248, + 131,WS_EX_CLIENTEDGE + LTEXT "Send typing notifications to the following users when you are typing a message to them:", + IDC_STATIC,19,18,245,19 + CONTROL "Show typing notifications when a user is typing a message", + IDC_SHOWNOTIFY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18, + 178,233,13 + CONTROL "Update inactive message window icons when a user is typing", + IDC_TYPEWIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,29,193, + 230,10 + CONTROL "Show typing notification when no message dialog is open", + IDC_TYPETRAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,29, + 206,230,10 + CONTROL "Flash in the system tray and in the contact list", + IDC_NOTIFYTRAY,"Button",BS_AUTORADIOBUTTON,44,219,206,10 + CONTROL "Show balloon popup",IDC_NOTIFYBALLOON,"Button", + BS_AUTORADIOBUTTON,44,231,206,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_OPT_MSGDLG, DIALOG + BEGIN + VERTGUIDE, 10 + VERTGUIDE, 22 + VERTGUIDE, 51 + VERTGUIDE, 148 + VERTGUIDE, 300 + VERTGUIDE, 310 + BOTTOMMARGIN, 231 + END + + IDD_MSGSENDERROR, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 182 + TOPMARGIN, 5 + BOTTOMMARGIN, 92 + END + + IDD_MSG, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 179 + TOPMARGIN, 5 + HORZGUIDE, 16 + HORZGUIDE, 53 + END + + IDD_OPT_MSGLOG, DIALOG + BEGIN + VERTGUIDE, 10 + VERTGUIDE, 148 + VERTGUIDE, 156 + VERTGUIDE, 169 + VERTGUIDE, 300 + HORZGUIDE, 183 + HORZGUIDE, 199 + END + + IDD_OPT_MSGTYPE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 276 + TOPMARGIN, 7 + BOTTOMMARGIN, 245 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "#include \r\n" + "#include ""../../include/statusmodes.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_USERDETAILS ICON DISCARDABLE "res/Details.ico" +IDI_ADDCONTACT ICON DISCARDABLE "res\\add.ico" +IDI_HISTORY ICON DISCARDABLE "res/History.ico" +IDI_DOWNARROW ICON DISCARDABLE "res/Downarrow.ico" +IDI_TYPING ICON DISCARDABLE "res/Typing.ico" +IDI_OUTGOING ICON DISCARDABLE "res\\outgoing.ico" +IDI_INCOMING ICON DISCARDABLE "res\\incoming.ico" +IDI_NOTICE ICON DISCARDABLE "res\\notice.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_HYPERLINKHAND CURSOR DISCARDABLE "../../src/res/hyperlin.cur" +IDC_DROP CURSOR DISCARDABLE "../../src/res/dragcopy.cur" +IDC_DROPUSER CURSOR DISCARDABLE "../../src/res/dropuser.cur" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_CONTEXT MENU DISCARDABLE +BEGIN + POPUP "Log" + BEGIN + MENUITEM "C&lear Log", IDM_CLEAR + MENUITEM SEPARATOR + MENUITEM "&Copy", IDM_COPY + MENUITEM "Co&py All", IDM_COPYALL + MENUITEM SEPARATOR + MENUITEM "Select &All", IDM_SELECTALL + END + POPUP "LogLink" + BEGIN + MENUITEM "Open in &new window", IDM_OPENNEW + MENUITEM "&Open in existing window", IDM_OPENEXISTING + MENUITEM "&Copy link", IDM_COPYLINK + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/miranda-wine/plugins/srmm/richutil.c b/miranda-wine/plugins/srmm/richutil.c new file mode 100644 index 0000000..d803af8 --- /dev/null +++ b/miranda-wine/plugins/srmm/richutil.c @@ -0,0 +1,234 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#include "commonheaders.h" +#include "richutil.h" + +/* + To initialize this library, call: + RichUtil_Load(); + Before the application exits, call: + RichUtil_Unload(); + + Then to use the library (it draws the xp border around it), you need + to make sure you control has the WS_EX_CLIENTEDGE flag. Then you just + subclass it with: + RichUtil_SubClass(hwndEdit); + + If no xptheme is present, the window isn't subclassed the SubClass function + just returns. And if WS_EX_CLIENTEDGE isn't present, the subclass does nothing. + Otherwise it removes the border and draws it by itself. +*/ + +static struct LIST_INTERFACE li; +static SortedList sListInt; + +static int RichUtil_CmpVal(void *p1, void *p2) { + TRichUtil *tp1 = (TRichUtil*)p1; + TRichUtil *tp2 = (TRichUtil*)p2; + if (tp1->hwnd==tp2->hwnd) + return 0; + return (int)((int)tp1->hwnd-(int)tp2->hwnd); +} + +// UxTheme Stuff +static HMODULE mTheme = 0; +static HANDLE (WINAPI *MyOpenThemeData)(HWND,LPCWSTR) = 0; +static HRESULT (WINAPI *MyCloseThemeData)(HANDLE) = 0; +static BOOL (WINAPI *MyIsThemeActive)() = 0; +static HRESULT (WINAPI *MyDrawThemeBackground)(HANDLE,HDC,int,int,const RECT*,const RECT *) = 0; +static HRESULT (WINAPI *MyGetThemeBackgroundContentRect)(HANDLE,HDC,int,int,const RECT *,RECT *) = 0; +static HRESULT (WINAPI *MyDrawThemeParentBackground)(HWND,HDC,RECT*) = 0; +static BOOL (WINAPI *MyIsThemeBackgroundPartiallyTransparent)(HANDLE,int,int) = 0; + +static CRITICAL_SECTION csRich; + +static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +static RichUtil_ClearUglyBorder(TRichUtil *ru); + +void RichUtil_Load() { + li.cbSize = sizeof(li); + CallService(MS_SYSTEM_GET_LI,0,(LPARAM)&li); + ZeroMemory(&sListInt, sizeof(sListInt)); + sListInt.increment = 10; + sListInt.sortFunc = RichUtil_CmpVal; + mTheme = RIsWinVerXPPlus()?LoadLibraryA("uxtheme.dll"):0; + InitializeCriticalSection(&csRich); + if (!mTheme) return; + MyOpenThemeData = (HANDLE (WINAPI *)(HWND, LPCWSTR))GetProcAddress(mTheme, "OpenThemeData"); + MyCloseThemeData = (HRESULT (WINAPI *)(HANDLE))GetProcAddress(mTheme, "CloseThemeData"); + MyIsThemeActive = (BOOL (WINAPI *)())GetProcAddress(mTheme, "IsThemeActive"); + MyDrawThemeBackground = (HRESULT (WINAPI *)(HANDLE, HDC, int, int, const RECT*, const RECT *))GetProcAddress(mTheme, "DrawThemeBackground"); + MyGetThemeBackgroundContentRect = (HRESULT (WINAPI *)(HANDLE, HDC, int, int, const RECT *, RECT *))GetProcAddress(mTheme, "GetThemeBackgroundContentRect"); + MyDrawThemeParentBackground = (HRESULT (WINAPI *)(HWND, HDC, RECT*))GetProcAddress(mTheme, "DrawThemeParentBackground"); + MyIsThemeBackgroundPartiallyTransparent = (BOOL (WINAPI *)(HANDLE, int, int))GetProcAddress(mTheme, "IsThemeBackgroundPartiallyTransparent"); + if (!MyOpenThemeData|| + !MyCloseThemeData|| + !MyIsThemeActive|| + !MyDrawThemeBackground|| + !MyGetThemeBackgroundContentRect|| + !MyDrawThemeParentBackground|| + !MyIsThemeBackgroundPartiallyTransparent) { + FreeLibrary(mTheme); + mTheme=NULL; + } +} + +void RichUtil_Unload() { + li.List_Destroy(&sListInt); + DeleteCriticalSection(&csRich); + if (mTheme) { + FreeLibrary(mTheme); + } +} + +int RichUtil_SubClass(HWND hwndEdit) { + if (IsWindow(hwndEdit)) { + int idx; + + TRichUtil *ru = (TRichUtil*)malloc(sizeof(TRichUtil)); + + ZeroMemory(ru, sizeof(TRichUtil)); + ru->hwnd = hwndEdit; + ru->hasUglyBorder = 0; + EnterCriticalSection(&csRich); + if (!li.List_GetIndex(&sListInt, ru, &idx)) + li.List_Insert(&sListInt, ru, idx); + LeaveCriticalSection(&csRich); + SetWindowLong(ru->hwnd, GWL_USERDATA, (LONG)ru); // Ugly hack + ru->origProc = (WNDPROC)SetWindowLong(ru->hwnd, GWL_WNDPROC, (LONG)&RichUtil_Proc); + RichUtil_ClearUglyBorder(ru); + return 1; + } + return 0; +} + +static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + TRichUtil *ru = 0, tru; + int idx; + + EnterCriticalSection(&csRich); + tru.hwnd = hwnd; + if (li.List_GetIndex(&sListInt, &tru, &idx)) + ru = (TRichUtil*)sListInt.items[idx]; + LeaveCriticalSection(&csRich); + switch(msg) { + case WM_THEMECHANGED: + case WM_STYLECHANGED: + { + RichUtil_ClearUglyBorder(ru); + break; + } + case WM_NCPAINT: + { + LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); + if (ru->hasUglyBorder&&MyIsThemeActive()) { + HANDLE hTheme = MyOpenThemeData(ru->hwnd, L"EDIT"); + + if (hTheme) { + RECT rcBorder; + RECT rcClient; + int nState; + HDC hdc = GetWindowDC(ru->hwnd); + + GetWindowRect(hwnd, &rcBorder); + rcBorder.right -= rcBorder.left; rcBorder.bottom -= rcBorder.top; + rcBorder.left = rcBorder.top = 0; + CopyRect(&rcClient, &rcBorder); + rcClient.left += ru->rect.left; + rcClient.top += ru->rect.top; + rcClient.right -= ru->rect.right; + rcClient.bottom -= ru->rect.bottom; + ExcludeClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); + if(MyIsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL)) + MyDrawThemeParentBackground(hwnd, hdc, &rcBorder); + if(!IsWindowEnabled(hwnd)) + nState = ETS_DISABLED; + else if(SendMessage(hwnd, EM_GETOPTIONS, 0, 0) & ECO_READONLY) + nState = ETS_READONLY; + else nState = ETS_NORMAL; + MyDrawThemeBackground(hTheme, hdc, EP_EDITTEXT, nState, &rcBorder, NULL); + MyCloseThemeData(hTheme); + ReleaseDC(hwnd, hdc); + return 0; + } + } + return ret; + } + case WM_NCCALCSIZE: + { + LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); + NCCALCSIZE_PARAMS *ncsParam = (NCCALCSIZE_PARAMS*)lParam; + + if (ru->hasUglyBorder&&MyIsThemeActive()) { + HANDLE hTheme = MyOpenThemeData(hwnd, L"EDIT"); + + if (hTheme) { + RECT rcClient; + HDC hdc = GetDC(GetParent(hwnd)); + + ZeroMemory(&rcClient, sizeof(RECT)); + if(MyGetThemeBackgroundContentRect(hTheme, hdc, EP_EDITTEXT, ETS_NORMAL, &ncsParam->rgrc[0], &rcClient) == S_OK) { + ru->rect.left = rcClient.left-ncsParam->rgrc[0].left; + ru->rect.top = rcClient.top-ncsParam->rgrc[0].top; + ru->rect.right = ncsParam->rgrc[0].right-rcClient.right; + ru->rect.bottom = ncsParam->rgrc[0].bottom-rcClient.bottom; + CopyRect(&ncsParam->rgrc[0], &rcClient); + MyCloseThemeData(hTheme); + ReleaseDC(GetParent(hwnd), hdc); + return WVR_REDRAW; + } + ReleaseDC(GetParent(hwnd), hdc); + MyCloseThemeData(hTheme); + } + } + return ret; + } + case WM_ENABLE: + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_NOCHILDREN|RDW_UPDATENOW|RDW_FRAME); + break; + case WM_DESTROY: + { + LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); + + if(IsWindow(hwnd)) { + if((WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC) == &RichUtil_Proc) + SetWindowLong(hwnd, GWL_WNDPROC, (LONG)ru->origProc); + } + EnterCriticalSection(&csRich); + li.List_Remove(&sListInt, idx); + LeaveCriticalSection(&csRich); + if (ru) free(ru); + return ret; + } + } + return CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); +} + +static RichUtil_ClearUglyBorder(TRichUtil *ru) { + if (mTheme&&MyIsThemeActive()&&GetWindowLong(ru->hwnd, GWL_EXSTYLE)&WS_EX_CLIENTEDGE) { + ru->hasUglyBorder = 1; + SetWindowLong(ru->hwnd, GWL_EXSTYLE, GetWindowLong(ru->hwnd, GWL_EXSTYLE)^WS_EX_CLIENTEDGE); + } + // Redraw window since the style may have changed + SetWindowPos(ru->hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED); + RedrawWindow(ru->hwnd, NULL, NULL, RDW_INVALIDATE|RDW_NOCHILDREN|RDW_UPDATENOW|RDW_FRAME); +} diff --git a/miranda-wine/plugins/srmm/richutil.h b/miranda-wine/plugins/srmm/richutil.h new file mode 100644 index 0000000..dff6a53 --- /dev/null +++ b/miranda-wine/plugins/srmm/richutil.h @@ -0,0 +1,55 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ +#ifndef SRMM_RICHUTIL_H +#define SRMM_RICHUTIL_H + +#define RWinVerMajor() LOBYTE(LOWORD(GetVersion())) +#define RIsWinVerXPPlus() (RWinVerMajor()>=5 && LOWORD(GetVersion())!=5) + +#ifndef WM_THEMECHANGED +#define WM_THEMECHANGED 0x031A +#endif +#ifndef EP_EDITTEXT +#define EP_EDITTEXT 1 +#endif +#ifndef ETS_NORMAL +#define ETS_NORMAL 1 +#endif +#ifndef ETS_DISABLED +#define ETS_DISABLED 4 +#endif +#ifndef ETS_READONLY +#define ETS_READONLY 6 +#endif + +typedef struct { + HWND hwnd; + RECT rect; + int hasUglyBorder; + WNDPROC origProc; +} TRichUtil; + +void RichUtil_Load(); +void RichUtil_Unload(); +int RichUtil_SubClass(HWND hwndEdit); + +#endif diff --git a/miranda-wine/plugins/srmm/srmm.c b/miranda-wine/plugins/srmm/srmm.c new file mode 100644 index 0000000..f416ef6 --- /dev/null +++ b/miranda-wine/plugins/srmm/srmm.c @@ -0,0 +1,71 @@ +/* +SRMM + +Copyright 2000-2005 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. +*/ + +#include "commonheaders.h" + +int LoadSendRecvMessageModule(void); +int SplitmsgShutdown(void); + +PLUGINLINK *pluginLink; +HINSTANCE g_hInst; + +PLUGININFO pluginInfo = { + sizeof(PLUGININFO), +#ifdef _UNICODE + "Send/Receive Messages (Unicode)", +#else + "Send/Receive Messages", +#endif + PLUGIN_MAKE_VERSION(3, 0, 0, 0), + "Send and receive instant messages", + "Miranda IM Development Team", + "rainwater@miranda-im.org", + "Copyright 2000-2006 Miranda IM project", + "http://www.miranda-im.org", + 0, + DEFMOD_SRMESSAGE // replace internal version (if any) +}; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + g_hInst = hinstDLL; + return TRUE; +} + +__declspec(dllexport) + PLUGININFO *MirandaPluginInfo(DWORD mirandaVersion) +{ + if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 4, 0, 0)) + return NULL; + return &pluginInfo; +} + +int __declspec(dllexport) Load(PLUGINLINK * link) +{ + pluginLink = link; + return LoadSendRecvMessageModule(); +} + +int __declspec(dllexport) Unload(void) +{ + return SplitmsgShutdown(); +} -- cgit v1.2.3