summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorghazan <ghazan@miranda.im>2021-11-07 16:48:40 +0300
committerghazan <ghazan@miranda.im>2021-11-07 16:48:40 +0300
commit3d88a792fb2f3950989d95d91e7de57fa1b74923 (patch)
tree4804c598f708690666dffc9f9bf4a37961f20706
parent27dab93c710a72ed363b5e0a543827b210ea71af (diff)
first version of mir_core that builds under Linux
-rw-r--r--.gitignore1
-rw-r--r--codeblocks/Miranda.workspace6
-rw-r--r--codeblocks/Miranda.workspace.layout6
-rw-r--r--include/m_clc.h562
-rw-r--r--include/m_core.h1260
-rw-r--r--include/m_database.h1586
-rw-r--r--include/m_db_int.h810
-rw-r--r--include/m_gui.h3169
-rw-r--r--include/m_netlib.h1730
-rw-r--r--include/m_protoint.h620
-rw-r--r--include/m_string.h1998
-rw-r--r--include/m_string.inl2932
-rw-r--r--include/m_system.h1306
-rw-r--r--include/m_timezones.h273
-rw-r--r--include/m_types.h170
-rw-r--r--include/m_xml.h389
-rw-r--r--include/newpluginapi.h1015
-rw-r--r--libs/Pcre16/pcre16.cbp11
-rw-r--r--libs/Pcre16/pcre16.layout5
-rw-r--r--libs/freeimage/freeimage.cbp11
-rw-r--r--libs/freeimage/freeimage.layout5
-rw-r--r--libs/libjson/libjson.cbp11
-rw-r--r--libs/libjson/libjson.layout5
-rw-r--r--libs/libsignal/libsignal.cbp11
-rw-r--r--libs/libsignal/libsignal.layout5
-rw-r--r--libs/sqlite3/sqlite3.cbp11
-rw-r--r--libs/sqlite3/sqlite3.layout5
-rw-r--r--libs/zlib/zlib.cbp11
-rw-r--r--libs/zlib/zlib.layout5
-rw-r--r--plugins/AVS/avs.cbp11
-rw-r--r--plugins/AVS/avs.layout5
-rw-r--r--plugins/Clist_modern/clist_modern.cbp11
-rw-r--r--plugins/Clist_modern/clist_modern.layout5
-rw-r--r--plugins/Clist_modern/icons_pack/Toolbar_icons.cbp11
-rw-r--r--plugins/Clist_modern/icons_pack/Toolbar_icons.layout5
-rw-r--r--plugins/Cln_skinedit/skinedit.cbp11
-rw-r--r--plugins/Cln_skinedit/skinedit.layout5
-rw-r--r--plugins/DbChecker/dbchecker.cbp11
-rw-r--r--plugins/DbChecker/dbchecker.layout5
-rw-r--r--plugins/Dbx_sqlite/dbx_sqlite.cbp11
-rw-r--r--plugins/Dbx_sqlite/dbx_sqlite.layout5
-rw-r--r--plugins/Import/import.cbp11
-rw-r--r--plugins/Import/import.layout5
-rw-r--r--plugins/PluginUpdater/PluginUpdater.cbp11
-rw-r--r--plugins/PluginUpdater/PluginUpdater.layout5
-rw-r--r--plugins/TabSRMM/TabSRMM_icons/NOVA/ICONS_NOVA_16.cbp138
-rw-r--r--plugins/TabSRMM/TabSRMM_icons/NOVA/ICONS_NOVA_16.layout5
-rw-r--r--plugins/TabSRMM/tabsrmm.cbp11
-rw-r--r--plugins/TabSRMM/tabsrmm.layout5
-rw-r--r--plugins/TopToolBar/TopToolBar.cbp11
-rw-r--r--plugins/TopToolBar/TopToolBar.layout5
-rw-r--r--protocols/Facebook/facebook.cbp11
-rw-r--r--protocols/Facebook/facebook.layout5
-rw-r--r--protocols/Facebook/proto_facebook/Proto_Facebook.cbp11
-rw-r--r--protocols/Facebook/proto_facebook/Proto_Facebook.layout5
-rw-r--r--protocols/Gadu-Gadu/gadugadu.cbp11
-rw-r--r--protocols/Gadu-Gadu/gadugadu.layout5
-rw-r--r--protocols/Gadu-Gadu/proto_gg/Proto_GG.cbp11
-rw-r--r--protocols/Gadu-Gadu/proto_gg/Proto_GG.layout5
-rw-r--r--protocols/ICQ-WIM/ICQ-WIM.cbp11
-rw-r--r--protocols/ICQ-WIM/ICQ-WIM.layout5
-rw-r--r--protocols/ICQ-WIM/proto_icq/Proto_ICQ.cbp11
-rw-r--r--protocols/ICQ-WIM/proto_icq/Proto_ICQ.layout5
-rw-r--r--protocols/IRCG/IRC.cbp11
-rw-r--r--protocols/IRCG/IRC.layout5
-rw-r--r--protocols/IRCG/proto_irc/Proto_IRC.cbp11
-rw-r--r--protocols/IRCG/proto_irc/Proto_IRC.layout5
-rw-r--r--protocols/JabberG/jabber.cbp11
-rw-r--r--protocols/JabberG/jabber.layout5
-rw-r--r--protocols/JabberG/jabber_xstatus/xStatus_Jabber.cbp11
-rw-r--r--protocols/JabberG/jabber_xstatus/xStatus_Jabber.layout5
-rw-r--r--protocols/JabberG/proto_jabber/Proto_Jabber.cbp11
-rw-r--r--protocols/JabberG/proto_jabber/Proto_Jabber.layout5
-rw-r--r--src/core/stdautoaway/stdautoaway.cbp11
-rw-r--r--src/core/stdautoaway/stdautoaway.layout5
-rw-r--r--src/core/stdaway/stdaway.cbp11
-rw-r--r--src/core/stdaway/stdaway.layout5
-rw-r--r--src/core/stdclist/stdclist.cbp11
-rw-r--r--src/core/stdclist/stdclist.layout5
-rw-r--r--src/core/stdcrypt/stdcrypt.cbp11
-rw-r--r--src/core/stdcrypt/stdcrypt.layout5
-rw-r--r--src/core/stdemail/stdemail.cbp11
-rw-r--r--src/core/stdemail/stdemail.layout5
-rw-r--r--src/core/stdfile/stdfile.cbp11
-rw-r--r--src/core/stdfile/stdfile.layout5
-rw-r--r--src/core/stdmsg/stdmsg.cbp11
-rw-r--r--src/core/stdmsg/stdmsg.layout5
-rw-r--r--src/core/stdpopup/stdpopup.cbp11
-rw-r--r--src/core/stdpopup/stdpopup.layout5
-rw-r--r--src/core/stduihist/stduihist.cbp11
-rw-r--r--src/core/stduihist/stduihist.layout5
-rw-r--r--src/core/stduserinfo/stduserinfo.cbp11
-rw-r--r--src/core/stduserinfo/stduserinfo.layout5
-rw-r--r--src/core/stduseronline/stduseronline.cbp11
-rw-r--r--src/core/stduseronline/stduseronline.layout5
-rw-r--r--src/icons/proto_metacontacts/Proto_MetaContacts.cbp11
-rw-r--r--src/icons/proto_metacontacts/Proto_MetaContacts.layout5
-rw-r--r--src/mir_app/mir_app.cbp11
-rw-r--r--src/mir_app/mir_app.layout5
-rw-r--r--src/mir_core/main.cpp1
-rw-r--r--src/mir_core/mir_core.cbp75
-rw-r--r--src/mir_core/mir_core.depend231
-rw-r--r--src/mir_core/mir_core.layout10
-rw-r--r--src/mir_core/src/Linux/fileutil.cpp23
-rw-r--r--src/mir_core/src/db.cpp1071
-rw-r--r--src/mir_core/src/logger.cpp424
-rw-r--r--src/mir_core/src/md5.cpp716
-rw-r--r--src/mir_core/src/memory.cpp580
-rw-r--r--src/mir_core/src/miranda.h186
-rw-r--r--src/mir_core/src/mstring.cpp282
-rw-r--r--src/mir_core/src/sha256.cpp578
-rw-r--r--src/mir_core/src/stdafx.h152
-rw-r--r--src/mir_core/src/utf.cpp878
-rw-r--r--src/mir_core/src/utils.cpp1126
-rw-r--r--src/miranda32/miranda32.cbp11
-rw-r--r--src/miranda32/miranda32.layout5
116 files changed, 13172 insertions, 11793 deletions
diff --git a/.gitignore b/.gitignore
index 9e5fe41ad1..c723e4e5e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,4 @@ vsbuild.cmd
#Langpacks Tools Template
langpacks/tool/VersionInfo.txt
+/.project
diff --git a/codeblocks/Miranda.workspace b/codeblocks/Miranda.workspace
new file mode 100644
index 0000000000..0cbe23aca2
--- /dev/null
+++ b/codeblocks/Miranda.workspace
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_workspace_file>
+ <Workspace title="Miranda">
+ <Project filename="../../../../var/www/miranda-ng/src/mir_core/mir_core.cbp" />
+ </Workspace>
+</CodeBlocks_workspace_file>
diff --git a/codeblocks/Miranda.workspace.layout b/codeblocks/Miranda.workspace.layout
new file mode 100644
index 0000000000..b94ee8d407
--- /dev/null
+++ b/codeblocks/Miranda.workspace.layout
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_workspace_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveProject path="../../../../var/www/miranda-ng/src/mir_core/mir_core.cbp" />
+ <PreferredTarget name="Debug" />
+</CodeBlocks_workspace_layout_file>
diff --git a/include/m_clc.h b/include/m_clc.h
index c087d085a6..dd4e697d70 100644
--- a/include/m_clc.h
+++ b/include/m_clc.h
@@ -1,280 +1,282 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-Copyright (c) 2000-08 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 M_CLC_H__
-#define M_CLC_H__ 1
-
-#define CLISTCONTROL_CLASS "CListControl"
-#define CLISTCONTROL_CLASSW L"CListControl"
-
-//styles
-#define CLS_MANUALUPDATE 0x0001 //todo
-#define CLS_SHOWHIDDEN 0x0002
-#define CLS_HIDEOFFLINE 0x0004 //hides all offline users
-#define CLS_CHECKBOXES 0x0008
-#define CLS_MULTICOLUMN 0x0010 //not true multi-column, just for ignore/vis options
-#define CLS_HIDEEMPTYGROUPS 0x0020 //note: this flag will be spontaneously removed if the 'new subgroup' menu item is clicked, for obvious reasons
-#define CLS_USEGROUPS 0x0040
-#define CLS_NOHIDEOFFLINE 0x0080 //overrides CLS_HIDEOFFLINE and the per-group hideoffline setting
-#define CLS_GREYALTERNATE 0x0100 //make every other line slightly grey
-#define CLS_GROUPCHECKBOXES 0x0200 //put checkboxes on groups too (managed by CLC)
-#define CLS_CONTACTLIST 0x0400 //this control will be the main contact list (v. 0.3.4.3+ 2004/11/02)
-
-#define CLS_EX_DISABLEDRAGDROP 0x00000001
-#define CLS_EX_EDITLABELS 0x00000002
-#define CLS_EX_SHOWSELALWAYS 0x00000004
-#define CLS_EX_TRACKSELECT 0x00000008
-#define CLS_EX_SHOWGROUPCOUNTS 0x00000010
-#define CLS_EX_DIVIDERONOFF 0x00000020
-#define CLS_EX_HIDECOUNTSWHENEMPTY 0x00000040
-#define CLS_EX_NOTRANSLUCENTSEL 0x00000080
-#define CLS_EX_LINEWITHGROUPS 0x00000100
-#define CLS_EX_QUICKSEARCHVISONLY 0x00000200
-#define CLS_EX_SORTGROUPSALPHA 0x00000400
-#define CLS_EX_NOSMOOTHSCROLLING 0x00000800
-
-#define CLM_FIRST 0x1000 //this is the same as LVM_FIRST
-#define CLM_LAST 0x1100
-
-//messages, compare with equivalent TVM_s in the MSDN
-#define CLM_ADDCONTACT (CLM_FIRST+0) //wParam = hContact
-#define CLM_ADDGROUP (CLM_FIRST+1) //wParam = hGroup
-#define CLM_AUTOREBUILD (CLM_FIRST+2)
-#define CLM_DELETEITEM (CLM_FIRST+3) //wParam = hItem
-#define CLM_EDITLABEL (CLM_FIRST+4) //wParam = hItem
-#define CLM_ENDEDITLABELNOW (CLM_FIRST+5) //wParam = cancel, 0 to save
-#define CLM_ENSUREVISIBLE (CLM_FIRST+6) //wParam = hItem, lParam = partialOk
-#define CLE_TOGGLE -1
-#define CLE_COLLAPSE 0
-#define CLE_EXPAND 1
-#define CLE_INVALID 0xFFFF
-#define CLM_EXPAND (CLM_FIRST+7) //wParam = hItem, lParam = CLE_
-#define CLM_FINDCONTACT (CLM_FIRST+8) //wParam = hContact, returns an hItem
-#define CLM_FINDGROUP (CLM_FIRST+9) //wParam = hGroup, returns an hItem
-#define CLM_GETBKCOLOR (CLM_FIRST+10) //returns a COLORREF
-#define CLM_GETCHECKMARK (CLM_FIRST+11) //wParam = hItem, returns 1 or 0
-#define CLM_GETCOUNT (CLM_FIRST+12) //returns the total number of items
-#define CLM_GETEDITCONTROL (CLM_FIRST+13) //returns the HWND, or NULL
-#define CLM_GETEXPAND (CLM_FIRST+14) //wParam = hItem, returns a CLE_, CLE_INVALID if not a group
-#define CLM_GETEXTRACOLUMNS (CLM_FIRST+15) //returns number of extra columns
-#define CLM_GETEXTRAIMAGE (CLM_FIRST+16) //wParam = hItem, lParam = MAKELPARAM(iColumn (0 based),0), returns iImage or EMPTY_EXTRA_ICON
-#define CLM_GETEXTRAIMAGELIST (CLM_FIRST+17) //returns HIMAGELIST
-#define CLM_GETFONT (CLM_FIRST+18) //wParam = fontId, see clm_setfont. returns hFont.
-#define CLM_GETINDENT (CLM_FIRST+19) //wParam = new group indent
-#define CLM_GETISEARCHSTRING (CLM_FIRST+20) //lParam = (char*)pszStr, max 120 bytes, returns number of chars in string
-#define CLM_GETITEMTEXT (CLM_FIRST+21) //wParam = hItem, lParam = (wchar_t*)pszStr, max 120 bytes
-#define CLM_GETSCROLLTIME (CLM_FIRST+22) //returns time in ms
-#define CLM_GETSELECTION (CLM_FIRST+23) //returns hItem
-#define CLM_SETEXTRASPACE (CLM_FIRST+24) //wParam=extra space between icons
-
-#define CLCHT_ABOVE 0x0001 //above client area
-#define CLCHT_BELOW 0x0002 //below client area
-#define CLCHT_TOLEFT 0x0004 //left of client area
-#define CLCHT_TORIGHT 0x0008 //right of client area
-#define CLCHT_NOWHERE 0x0010 //in client area, not on an item
-#define CLCHT_ONITEMICON 0x0020
-#define CLCHT_ONITEMCHECK 0x0040
-#define CLCHT_ONITEMLABEL 0x0080
-#define CLCHT_ONITEMINDENT 0x0100 //to the left of an item icon
-#define CLCHT_ONITEMEXTRA 0x0200 //on an extra icon, HIBYTE(HIWORD()) says which
-#define CLCHT_ONITEM 0x03E0
-#define CLCHT_INLEFTMARGIN 0x0400
-#define CLCHT_BELOWITEMS 0x0800 //in client area but below last item
-#define CLM_HITTEST (CLM_FIRST+25) //lParam = MAKELPARAM(x,y) (relative to control), wParam = (PDWORD)&hitTest (see encoding of HitTest() in clc.h, can be NULL) returns hItem or NULL
-#define CLM_SELECTITEM (CLM_FIRST+26) //wParam = hItem
-#define CLB_TOPLEFT 0
-#define CLB_STRETCHV 1
-#define CLB_STRETCHH 2 //and tile vertically
-#define CLB_STRETCH 3
-#define CLBM_TYPE 0x00FF
-#define CLBF_TILEH 0x1000
-#define CLBF_TILEV 0x2000
-#define CLBF_PROPORTIONAL 0x4000
-#define CLBF_SCROLL 0x8000
-
-#define CLM_SETBKCOLOR (CLM_FIRST+28) //wParam = a COLORREF, default is GetSysColor(COLOR_3DFACE)
-#define CLM_SETCHECKMARK (CLM_FIRST+29) //wParam = hItem, lParam = 1 or 0
-#define CLM_SETEXTRACOLUMNS (CLM_FIRST+30) //wParam = number of extra columns (zero to EXTRA_ICON_COUNT from clc.h, currently 16)
-#define CLM_SETEXTRAIMAGE (CLM_FIRST+31) //wParam = hItem, lParam = MAKELPARAM(iColumn (0 based),iImage). iImage = EMPTY_EXTRA_ICON is a blank
-#define CLM_SETEXTRAIMAGELIST (CLM_FIRST+32) //lParam = HIMAGELIST
-
-#define FONTID_CONTACTS 0
-#define FONTID_INVIS 1
-#define FONTID_OFFLINE 2
-#define FONTID_NOTONLIST 3
-#define FONTID_GROUPS 4
-#define FONTID_GROUPCOUNTS 5
-#define FONTID_DIVIDERS 6
-#define FONTID_OFFINVIS 7
-#define FONTID_STATUSMSG 8
-#define FONTID_GROUPSCLOSED 9
-#define FONTID_CONTACTSHOVER 10
-#define FONTID_MAX 18
-
-#define CLM_SETFONT (CLM_FIRST+33) //wParam = hFont, lParam = MAKELPARAM(fRedraw,fontId)
-#define CLM_SETITEMTEXT (CLM_FIRST+35) //wParam = hItem, lParam = (char*)pszNewText
-#define CLM_SETSCROLLTIME (CLM_FIRST+36) //wParam = time in ms, default 200
-
-#define CLM_SETHIDEEMPTYGROUPS (CLM_FIRST+38) //wParam = TRUE/FALSE
-#define GREYF_UNFOCUS 0x80000000
-#define MODEF_OFFLINE 0x40000000
-//and use the PF2_ #defines from m_protosvc.h
-
-#define CLM_GETHIDEOFFLINEROOT (CLM_FIRST+40) //returns TRUE/FALSE
-#define CLM_SETHIDEOFFLINEROOT (CLM_FIRST+41) //wParam = TRUE/FALSE
-#define CLM_SETUSEGROUPS (CLM_FIRST+42) //wParam = TRUE/FALSE
-#define CLM_SETOFFLINEMODES (CLM_FIRST+43) //for 'hide offline', wParam = PF2_ flags and MODEF_OFFLINE
-#define CLM_GETEXSTYLE (CLM_FIRST+44) //returns CLS_EX_ flags
-#define CLM_SETEXSTYLE (CLM_FIRST+45) //wParam = CLS_EX_ flags
-
-typedef struct {
- int cbSize;
- const wchar_t *pszText;
- HANDLE hParentGroup;
- DWORD flags;
- HICON hIcon; //todo
-} CLCINFOITEM;
-#define CLCIIF_BELOWGROUPS 1 //put it between groups and contacts, default is at top
-#define CLCIIF_BELOWCONTACTS 2 //put it at the bottom
-#define CLCIIF_CHECKBOX 0x40 //give this item a check box
-#define CLCIIF_GROUPFONT 0x80 //draw the item using FONTID_GROUPS
-
-#define CLM_ADDINFOITEMA (CLM_FIRST+48) //lParam = &cii, returns hItem
-#define CLM_ADDINFOITEMW (CLM_FIRST+53) //lParam = &cii, returns hItem
-#if defined(_UNICODE)
- #define CLM_ADDINFOITEM CLM_ADDINFOITEMW
-#else
- #define CLM_ADDINFOITEM CLM_ADDINFOITEMA
-#endif
-
- //the order of info items is never changed, so make sure you add them in the
- // order you want them to remain
-#define CLCIT_INVALID -1
-#define CLCIT_GROUP 0
-#define CLCIT_CONTACT 1
-#define CLCIT_DIVIDER 2
-#define CLCIT_INFO 3
-#define CLM_GETITEMTYPE (CLM_FIRST+49) //wParam = hItem, returns a CLCIT_
-#define CLGN_ROOT 0
-#define CLGN_CHILD 1
-#define CLGN_PARENT 2
-#define CLGN_NEXT 3
-#define CLGN_PREVIOUS 4
-#define CLGN_NEXTCONTACT 5
-#define CLGN_PREVIOUSCONTACT 6
-#define CLGN_NEXTGROUP 7
-#define CLGN_PREVIOUSGROUP 8
-
-#define CLM_GETNEXTITEM (CLM_FIRST+50) //wParam = flag, lParam = hItem, returns an hItem
-#define CLM_GETTEXTCOLOR (CLM_FIRST+51) //wParam = FONTID_, returns COLORREF
-#define CLM_SETTEXTCOLOR (CLM_FIRST+52) //wParam = FONTID_, lParam = COLORREF
-
-//notifications (most are omitted because the control processes everything)
-#define CLNF_ISGROUP 1
-#define CLNF_ISINFO 2
-typedef struct {
- NMHDR hdr;
- HANDLE hItem;
- int action;
- int iColumn; //-1 if not on an extra column
- DWORD flags;
- POINT pt;
-} NMCLISTCONTROL;
-#define CLN_FIRST (0U-100U)
-#define CLN_EXPANDED (CLN_FIRST-0) //hItem = hGroup, action = CLE_*
-#define CLN_LISTREBUILT (CLN_FIRST-1)
-#define CLN_ITEMCHECKED (CLN_FIRST-2) //todo //hItem, action, flags valid
-#define CLN_DRAGGING (CLN_FIRST-3) //hItem, pt, flags valid. only sent when cursor outside window, return nonzero if processed
-#define CLN_DROPPED (CLN_FIRST-4) //hItem, pt, flags valid. only sent when cursor outside window, return nonzero if processed
-#define CLN_LISTSIZECHANGE (CLN_FIRST-5) //pt.y valid. the vertical height of the visible items in the list has changed.
-#define CLN_OPTIONSCHANGED (CLN_FIRST-6) //nothing valid. If you set some extended options they have been overwritten and should be re-set
-#define CLN_DRAGSTOP (CLN_FIRST-7) //hItem, flags valid. sent when cursor goes back in to the window having been outside, return nonzero if processed
-#define CLN_NEWCONTACT (CLN_FIRST-8) //hItem, flags valid. sent when a new contact is added without a full list rebuild
-#define CLN_CONTACTMOVED (CLN_FIRST-9) //hItem, flags valid. sent when contact is moved without a full list rebuild
-#define CLN_CHECKCHANGED (CLN_FIRST-10) //hItem, flags valid. sent when any check mark is changed, but only for one change if there are many
-//NM_CLICK //hItem, iColumn, pt, flags valid
-//NM_KEYDOWN //NMKEY structure, only sent when key is not already processed, return nonzero to prevent further processing
-
-// clist window tree messages
-#define M_CREATECLC (WM_USER+1)
-#define M_SETALLEXTRAICONS (WM_USER+2)
-
-//an infotip for an item should be shown now
-//wParam = 0
-//lParam = (LPARAM)(CLCINFOTIP*)&it
-//Return nonzero if you process this, because it makes no sense for more than
-//one plugin to grab it.
-//It is up to the plugin to decide the best place to put the infotip. Normally
-//it's a few pixels below and to the right of the cursor
-//This event is called after the mouse has been stationary over a contact for
-//(by default) 200ms, but see below.
-//Everything is in screen coordinates.
-typedef struct {
- int cbSize;
- int isTreeFocused; //so the plugin can provide an option
- int isGroup; //0 if it's a contact, 1 if it's a group
- HANDLE hItem; //handle to group or contact
- POINT ptCursor;
- RECT rcItem;
-} CLCINFOTIP;
-#define ME_CLC_SHOWINFOTIP "CLC/ShowInfoTip"
-
-typedef struct {
- int cbSize;
- int isTreeFocused; //so the plugin can provide an option
- HANDLE hItem; //handle to group or contact
- POINT ptCursor;
- RECT rcItem;
- int extraIndex;
- HWND hwnd;
-} CLCEXTRAINFOTIP;
-#define ME_CLC_SHOWEXTRAINFOTIP "CLC/ShowExtraInfoTip"
-
-//it's time to destroy an infotip
-//wParam = 0
-//lParam = (LPARAM)(CLCINFOTIP*)&it
-//Only cbSize, isGroup and hItem are set
-//Return nonzero if you process this.
-//This is sent when the mouse moves off a contact when clc/showinfotip has
-//previously been called.
-//If you don't want this behaviour, you should have grabbed the mouse capture
-//yourself and made your own arrangements.
-#define ME_CLC_HIDEINFOTIP "CLC/HideInfoTip"
-
-//set the hover time before the infotip hooks are called
-//wParam = newTime
-//lParam = 0
-//Returns 0 on success or nonzero on failure
-//The value of this setting is applied to all current CLC windows, and saved
-//to be applied to all future windows, including after restarts.
-//newTime is in ms.
-//The default is 750ms.
-#define MS_CLC_SETINFOTIPHOVERTIME "CLC/SetInfoTipHoverTime"
-
-//get the hover time before the infotip hooks are called
-//wParam = lParam = 0
-//Returns the time in ms
-#define MS_CLC_GETINFOTIPHOVERTIME "CLC/GetInfoTipHoverTime"
-
-#endif // M_CLC_H__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+Copyright (c) 2000-08 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 M_CLC_H__
+#define M_CLC_H__ 1
+
+#define CLISTCONTROL_CLASS "CListControl"
+#define CLISTCONTROL_CLASSW L"CListControl"
+
+//styles
+#define CLS_MANUALUPDATE 0x0001 //todo
+#define CLS_SHOWHIDDEN 0x0002
+#define CLS_HIDEOFFLINE 0x0004 //hides all offline users
+#define CLS_CHECKBOXES 0x0008
+#define CLS_MULTICOLUMN 0x0010 //not true multi-column, just for ignore/vis options
+#define CLS_HIDEEMPTYGROUPS 0x0020 //note: this flag will be spontaneously removed if the 'new subgroup' menu item is clicked, for obvious reasons
+#define CLS_USEGROUPS 0x0040
+#define CLS_NOHIDEOFFLINE 0x0080 //overrides CLS_HIDEOFFLINE and the per-group hideoffline setting
+#define CLS_GREYALTERNATE 0x0100 //make every other line slightly grey
+#define CLS_GROUPCHECKBOXES 0x0200 //put checkboxes on groups too (managed by CLC)
+#define CLS_CONTACTLIST 0x0400 //this control will be the main contact list (v. 0.3.4.3+ 2004/11/02)
+
+#define CLS_EX_DISABLEDRAGDROP 0x00000001
+#define CLS_EX_EDITLABELS 0x00000002
+#define CLS_EX_SHOWSELALWAYS 0x00000004
+#define CLS_EX_TRACKSELECT 0x00000008
+#define CLS_EX_SHOWGROUPCOUNTS 0x00000010
+#define CLS_EX_DIVIDERONOFF 0x00000020
+#define CLS_EX_HIDECOUNTSWHENEMPTY 0x00000040
+#define CLS_EX_NOTRANSLUCENTSEL 0x00000080
+#define CLS_EX_LINEWITHGROUPS 0x00000100
+#define CLS_EX_QUICKSEARCHVISONLY 0x00000200
+#define CLS_EX_SORTGROUPSALPHA 0x00000400
+#define CLS_EX_NOSMOOTHSCROLLING 0x00000800
+
+#define CLM_FIRST 0x1000 //this is the same as LVM_FIRST
+#define CLM_LAST 0x1100
+
+//messages, compare with equivalent TVM_s in the MSDN
+#define CLM_ADDCONTACT (CLM_FIRST+0) //wParam = hContact
+#define CLM_ADDGROUP (CLM_FIRST+1) //wParam = hGroup
+#define CLM_AUTOREBUILD (CLM_FIRST+2)
+#define CLM_DELETEITEM (CLM_FIRST+3) //wParam = hItem
+#define CLM_EDITLABEL (CLM_FIRST+4) //wParam = hItem
+#define CLM_ENDEDITLABELNOW (CLM_FIRST+5) //wParam = cancel, 0 to save
+#define CLM_ENSUREVISIBLE (CLM_FIRST+6) //wParam = hItem, lParam = partialOk
+#define CLE_TOGGLE -1
+#define CLE_COLLAPSE 0
+#define CLE_EXPAND 1
+#define CLE_INVALID 0xFFFF
+#define CLM_EXPAND (CLM_FIRST+7) //wParam = hItem, lParam = CLE_
+#define CLM_FINDCONTACT (CLM_FIRST+8) //wParam = hContact, returns an hItem
+#define CLM_FINDGROUP (CLM_FIRST+9) //wParam = hGroup, returns an hItem
+#define CLM_GETBKCOLOR (CLM_FIRST+10) //returns a COLORREF
+#define CLM_GETCHECKMARK (CLM_FIRST+11) //wParam = hItem, returns 1 or 0
+#define CLM_GETCOUNT (CLM_FIRST+12) //returns the total number of items
+#define CLM_GETEDITCONTROL (CLM_FIRST+13) //returns the HWND, or NULL
+#define CLM_GETEXPAND (CLM_FIRST+14) //wParam = hItem, returns a CLE_, CLE_INVALID if not a group
+#define CLM_GETEXTRACOLUMNS (CLM_FIRST+15) //returns number of extra columns
+#define CLM_GETEXTRAIMAGE (CLM_FIRST+16) //wParam = hItem, lParam = MAKELPARAM(iColumn (0 based),0), returns iImage or EMPTY_EXTRA_ICON
+#define CLM_GETEXTRAIMAGELIST (CLM_FIRST+17) //returns HIMAGELIST
+#define CLM_GETFONT (CLM_FIRST+18) //wParam = fontId, see clm_setfont. returns hFont.
+#define CLM_GETINDENT (CLM_FIRST+19) //wParam = new group indent
+#define CLM_GETISEARCHSTRING (CLM_FIRST+20) //lParam = (char*)pszStr, max 120 bytes, returns number of chars in string
+#define CLM_GETITEMTEXT (CLM_FIRST+21) //wParam = hItem, lParam = (wchar_t*)pszStr, max 120 bytes
+#define CLM_GETSCROLLTIME (CLM_FIRST+22) //returns time in ms
+#define CLM_GETSELECTION (CLM_FIRST+23) //returns hItem
+#define CLM_SETEXTRASPACE (CLM_FIRST+24) //wParam=extra space between icons
+
+#define CLCHT_ABOVE 0x0001 //above client area
+#define CLCHT_BELOW 0x0002 //below client area
+#define CLCHT_TOLEFT 0x0004 //left of client area
+#define CLCHT_TORIGHT 0x0008 //right of client area
+#define CLCHT_NOWHERE 0x0010 //in client area, not on an item
+#define CLCHT_ONITEMICON 0x0020
+#define CLCHT_ONITEMCHECK 0x0040
+#define CLCHT_ONITEMLABEL 0x0080
+#define CLCHT_ONITEMINDENT 0x0100 //to the left of an item icon
+#define CLCHT_ONITEMEXTRA 0x0200 //on an extra icon, HIBYTE(HIWORD()) says which
+#define CLCHT_ONITEM 0x03E0
+#define CLCHT_INLEFTMARGIN 0x0400
+#define CLCHT_BELOWITEMS 0x0800 //in client area but below last item
+#define CLM_HITTEST (CLM_FIRST+25) //lParam = MAKELPARAM(x,y) (relative to control), wParam = (PDWORD)&hitTest (see encoding of HitTest() in clc.h, can be NULL) returns hItem or NULL
+#define CLM_SELECTITEM (CLM_FIRST+26) //wParam = hItem
+#define CLB_TOPLEFT 0
+#define CLB_STRETCHV 1
+#define CLB_STRETCHH 2 //and tile vertically
+#define CLB_STRETCH 3
+#define CLBM_TYPE 0x00FF
+#define CLBF_TILEH 0x1000
+#define CLBF_TILEV 0x2000
+#define CLBF_PROPORTIONAL 0x4000
+#define CLBF_SCROLL 0x8000
+
+#define CLM_SETBKCOLOR (CLM_FIRST+28) //wParam = a COLORREF, default is GetSysColor(COLOR_3DFACE)
+#define CLM_SETCHECKMARK (CLM_FIRST+29) //wParam = hItem, lParam = 1 or 0
+#define CLM_SETEXTRACOLUMNS (CLM_FIRST+30) //wParam = number of extra columns (zero to EXTRA_ICON_COUNT from clc.h, currently 16)
+#define CLM_SETEXTRAIMAGE (CLM_FIRST+31) //wParam = hItem, lParam = MAKELPARAM(iColumn (0 based),iImage). iImage = EMPTY_EXTRA_ICON is a blank
+#define CLM_SETEXTRAIMAGELIST (CLM_FIRST+32) //lParam = HIMAGELIST
+
+#define FONTID_CONTACTS 0
+#define FONTID_INVIS 1
+#define FONTID_OFFLINE 2
+#define FONTID_NOTONLIST 3
+#define FONTID_GROUPS 4
+#define FONTID_GROUPCOUNTS 5
+#define FONTID_DIVIDERS 6
+#define FONTID_OFFINVIS 7
+#define FONTID_STATUSMSG 8
+#define FONTID_GROUPSCLOSED 9
+#define FONTID_CONTACTSHOVER 10
+#define FONTID_MAX 18
+
+#define CLM_SETFONT (CLM_FIRST+33) //wParam = hFont, lParam = MAKELPARAM(fRedraw,fontId)
+#define CLM_SETITEMTEXT (CLM_FIRST+35) //wParam = hItem, lParam = (char*)pszNewText
+#define CLM_SETSCROLLTIME (CLM_FIRST+36) //wParam = time in ms, default 200
+
+#define CLM_SETHIDEEMPTYGROUPS (CLM_FIRST+38) //wParam = TRUE/FALSE
+#define GREYF_UNFOCUS 0x80000000
+#define MODEF_OFFLINE 0x40000000
+//and use the PF2_ #defines from m_protosvc.h
+
+#define CLM_GETHIDEOFFLINEROOT (CLM_FIRST+40) //returns TRUE/FALSE
+#define CLM_SETHIDEOFFLINEROOT (CLM_FIRST+41) //wParam = TRUE/FALSE
+#define CLM_SETUSEGROUPS (CLM_FIRST+42) //wParam = TRUE/FALSE
+#define CLM_SETOFFLINEMODES (CLM_FIRST+43) //for 'hide offline', wParam = PF2_ flags and MODEF_OFFLINE
+#define CLM_GETEXSTYLE (CLM_FIRST+44) //returns CLS_EX_ flags
+#define CLM_SETEXSTYLE (CLM_FIRST+45) //wParam = CLS_EX_ flags
+
+typedef struct {
+ int cbSize;
+ const wchar_t *pszText;
+ HANDLE hParentGroup;
+ DWORD flags;
+ HICON hIcon; //todo
+} CLCINFOITEM;
+#define CLCIIF_BELOWGROUPS 1 //put it between groups and contacts, default is at top
+#define CLCIIF_BELOWCONTACTS 2 //put it at the bottom
+#define CLCIIF_CHECKBOX 0x40 //give this item a check box
+#define CLCIIF_GROUPFONT 0x80 //draw the item using FONTID_GROUPS
+
+#define CLM_ADDINFOITEMA (CLM_FIRST+48) //lParam = &cii, returns hItem
+#define CLM_ADDINFOITEMW (CLM_FIRST+53) //lParam = &cii, returns hItem
+#if defined(_UNICODE)
+ #define CLM_ADDINFOITEM CLM_ADDINFOITEMW
+#else
+ #define CLM_ADDINFOITEM CLM_ADDINFOITEMA
+#endif
+
+ //the order of info items is never changed, so make sure you add them in the
+ // order you want them to remain
+#define CLCIT_INVALID -1
+#define CLCIT_GROUP 0
+#define CLCIT_CONTACT 1
+#define CLCIT_DIVIDER 2
+#define CLCIT_INFO 3
+#define CLM_GETITEMTYPE (CLM_FIRST+49) //wParam = hItem, returns a CLCIT_
+#define CLGN_ROOT 0
+#define CLGN_CHILD 1
+#define CLGN_PARENT 2
+#define CLGN_NEXT 3
+#define CLGN_PREVIOUS 4
+#define CLGN_NEXTCONTACT 5
+#define CLGN_PREVIOUSCONTACT 6
+#define CLGN_NEXTGROUP 7
+#define CLGN_PREVIOUSGROUP 8
+
+#define CLM_GETNEXTITEM (CLM_FIRST+50) //wParam = flag, lParam = hItem, returns an hItem
+#define CLM_GETTEXTCOLOR (CLM_FIRST+51) //wParam = FONTID_, returns COLORREF
+#define CLM_SETTEXTCOLOR (CLM_FIRST+52) //wParam = FONTID_, lParam = COLORREF
+
+//notifications (most are omitted because the control processes everything)
+#define CLNF_ISGROUP 1
+#define CLNF_ISINFO 2
+#ifdef _MSC_VER
+typedef struct {
+ NMHDR hdr;
+ HANDLE hItem;
+ int action;
+ int iColumn; //-1 if not on an extra column
+ DWORD flags;
+ POINT pt;
+} NMCLISTCONTROL;
+#endif
+#define CLN_FIRST (0U-100U)
+#define CLN_EXPANDED (CLN_FIRST-0) //hItem = hGroup, action = CLE_*
+#define CLN_LISTREBUILT (CLN_FIRST-1)
+#define CLN_ITEMCHECKED (CLN_FIRST-2) //todo //hItem, action, flags valid
+#define CLN_DRAGGING (CLN_FIRST-3) //hItem, pt, flags valid. only sent when cursor outside window, return nonzero if processed
+#define CLN_DROPPED (CLN_FIRST-4) //hItem, pt, flags valid. only sent when cursor outside window, return nonzero if processed
+#define CLN_LISTSIZECHANGE (CLN_FIRST-5) //pt.y valid. the vertical height of the visible items in the list has changed.
+#define CLN_OPTIONSCHANGED (CLN_FIRST-6) //nothing valid. If you set some extended options they have been overwritten and should be re-set
+#define CLN_DRAGSTOP (CLN_FIRST-7) //hItem, flags valid. sent when cursor goes back in to the window having been outside, return nonzero if processed
+#define CLN_NEWCONTACT (CLN_FIRST-8) //hItem, flags valid. sent when a new contact is added without a full list rebuild
+#define CLN_CONTACTMOVED (CLN_FIRST-9) //hItem, flags valid. sent when contact is moved without a full list rebuild
+#define CLN_CHECKCHANGED (CLN_FIRST-10) //hItem, flags valid. sent when any check mark is changed, but only for one change if there are many
+//NM_CLICK //hItem, iColumn, pt, flags valid
+//NM_KEYDOWN //NMKEY structure, only sent when key is not already processed, return nonzero to prevent further processing
+
+// clist window tree messages
+#define M_CREATECLC (WM_USER+1)
+#define M_SETALLEXTRAICONS (WM_USER+2)
+
+//an infotip for an item should be shown now
+//wParam = 0
+//lParam = (LPARAM)(CLCINFOTIP*)&it
+//Return nonzero if you process this, because it makes no sense for more than
+//one plugin to grab it.
+//It is up to the plugin to decide the best place to put the infotip. Normally
+//it's a few pixels below and to the right of the cursor
+//This event is called after the mouse has been stationary over a contact for
+//(by default) 200ms, but see below.
+//Everything is in screen coordinates.
+typedef struct {
+ int cbSize;
+ int isTreeFocused; //so the plugin can provide an option
+ int isGroup; //0 if it's a contact, 1 if it's a group
+ HANDLE hItem; //handle to group or contact
+ POINT ptCursor;
+ RECT rcItem;
+} CLCINFOTIP;
+#define ME_CLC_SHOWINFOTIP "CLC/ShowInfoTip"
+
+typedef struct {
+ int cbSize;
+ int isTreeFocused; //so the plugin can provide an option
+ HANDLE hItem; //handle to group or contact
+ POINT ptCursor;
+ RECT rcItem;
+ int extraIndex;
+ HWND hwnd;
+} CLCEXTRAINFOTIP;
+#define ME_CLC_SHOWEXTRAINFOTIP "CLC/ShowExtraInfoTip"
+
+//it's time to destroy an infotip
+//wParam = 0
+//lParam = (LPARAM)(CLCINFOTIP*)&it
+//Only cbSize, isGroup and hItem are set
+//Return nonzero if you process this.
+//This is sent when the mouse moves off a contact when clc/showinfotip has
+//previously been called.
+//If you don't want this behaviour, you should have grabbed the mouse capture
+//yourself and made your own arrangements.
+#define ME_CLC_HIDEINFOTIP "CLC/HideInfoTip"
+
+//set the hover time before the infotip hooks are called
+//wParam = newTime
+//lParam = 0
+//Returns 0 on success or nonzero on failure
+//The value of this setting is applied to all current CLC windows, and saved
+//to be applied to all future windows, including after restarts.
+//newTime is in ms.
+//The default is 750ms.
+#define MS_CLC_SETINFOTIPHOVERTIME "CLC/SetInfoTipHoverTime"
+
+//get the hover time before the infotip hooks are called
+//wParam = lParam = 0
+//Returns the time in ms
+#define MS_CLC_GETINFOTIPHOVERTIME "CLC/GetInfoTipHoverTime"
+
+#endif // M_CLC_H__
diff --git a/include/m_core.h b/include/m_core.h
index 6a9cda3b39..8726e189a1 100644
--- a/include/m_core.h
+++ b/include/m_core.h
@@ -1,600 +1,660 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-Copyright (c) 2000-08 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 M_CORE_H__
-#define M_CORE_H__ 1
-
-#ifdef _MSC_VER
- #include <sal.h>
-#endif
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifndef M_TYPES_H__
- #include <m_types.h>
-#endif
-
-#ifdef MIR_CORE_EXPORTS
- #define MIR_CORE_EXPORT __declspec(dllexport)
-#else
- #define MIR_CORE_EXPORT __declspec(dllimport)
-#endif
-
-#define MIR_CORE_DLL(T) MIR_CORE_EXPORT T __stdcall
-#define MIR_C_CORE_DLL(T) MIR_CORE_EXPORT T __cdecl
-
-#ifdef MIR_APP_EXPORTS
- #define MIR_APP_EXPORT __declspec(dllexport)
- typedef struct NetlibUser* HNETLIBUSER;
- typedef struct NetlibConnection* HNETLIBCONN;
- typedef struct NetlibBoundPort* HNETLIBBIND;
-#else
- #define MIR_APP_EXPORT __declspec(dllimport)
- DECLARE_HANDLE(HNETLIBUSER);
- DECLARE_HANDLE(HNETLIBCONN);
- DECLARE_HANDLE(HNETLIBBIND);
-#endif
-
-typedef struct TMO_IntMenuItem* HGENMENU;
-
-class CMPluginBase;
-typedef const CMPluginBase* HPLUGIN;
-
-#define MIR_APP_DLL(T) MIR_APP_EXPORT T __stdcall
-
-#pragma warning(disable:4201 4127 4312 4706)
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// command line support
-
-MIR_CORE_DLL(void) CmdLine_Parse(const wchar_t *ptszCmdLine);
-MIR_CORE_DLL(const wchar_t*) CmdLine_GetOption(const wchar_t *ptszParameter);
-
-///////////////////////////////////////////////////////////////////////////////
-// database functions
-
-typedef uint32_t MCONTACT;
-#define INVALID_CONTACT_ID (MCONTACT(-1))
-
-typedef uint32_t MEVENT;
-
-///////////////////////////////////////////////////////////////////////////////
-// events, hooks & services
-
-#define MAXMODULELABELLENGTH 64
-
-typedef int (*MIRANDAHOOK)(WPARAM, LPARAM);
-typedef int (*MIRANDAHOOKPARAM)(WPARAM, LPARAM, LPARAM);
-typedef int (*MIRANDAHOOKOBJ)(void*, WPARAM, LPARAM);
-typedef int (*MIRANDAHOOKOBJPARAM)(void*, WPARAM, LPARAM, LPARAM);
-
-typedef INT_PTR (*MIRANDASERVICE)(WPARAM, LPARAM);
-typedef INT_PTR (*MIRANDASERVICEPARAM)(WPARAM, LPARAM, LPARAM);
-typedef INT_PTR (*MIRANDASERVICEOBJ)(void*, WPARAM, LPARAM);
-typedef INT_PTR (*MIRANDASERVICEOBJPARAM)(void*, WPARAM, LPARAM, LPARAM);
-
-#ifdef _WIN64
- #define CALLSERVICE_NOTFOUND ((INT_PTR)0x8000000000000000)
-#else
- #define CALLSERVICE_NOTFOUND ((int)0x80000000)
-#endif
-
-MIR_CORE_DLL(HANDLE) CreateHookableEvent(const char *name);
-MIR_CORE_DLL(int) DestroyHookableEvent(HANDLE hEvent);
-MIR_CORE_DLL(int) SetHookDefaultForHookableEvent(HANDLE hEvent, MIRANDAHOOK pfnHook);
-MIR_CORE_DLL(int) CallPluginEventHook(HINSTANCE hInst, HANDLE hEvent, WPARAM wParam = 0, LPARAM lParam = 0);
-MIR_CORE_DLL(int) CallObjectEventHook(void *pObject, HANDLE hEvent, WPARAM wParam = 0, LPARAM lParam = 0);
-MIR_CORE_DLL(int) NotifyEventHooks(HANDLE hEvent, WPARAM wParam = 0, LPARAM lParam = 0);
-MIR_CORE_DLL(int) NotifyFastHook(HANDLE hEvent, WPARAM wParam = 0, LPARAM lParam = 0);
-
-MIR_CORE_DLL(HANDLE) HookEvent(const char *name, MIRANDAHOOK hookProc);
-MIR_CORE_DLL(HANDLE) HookEventParam(const char *name, MIRANDAHOOKPARAM hookProc, LPARAM lParam = 0);
-MIR_CORE_DLL(HANDLE) HookEventObj(const char *name, MIRANDAHOOKOBJ hookProc, void* object);
-MIR_CORE_DLL(HANDLE) HookEventObjParam(const char *name, MIRANDAHOOKOBJPARAM hookProc, void* object, LPARAM lParam);
-MIR_CORE_DLL(HANDLE) HookEventMessage(const char *name, HWND hwnd, UINT message);
-
-// executes the event handler if event is missing
-MIR_CORE_DLL(HANDLE) HookTemporaryEvent(const char *name, MIRANDAHOOK hookProc);
-
-MIR_CORE_DLL(int) UnhookEvent(HANDLE hHook);
-MIR_CORE_DLL(void) KillObjectEventHooks(void* pObject);
-MIR_CORE_DLL(void) KillModuleEventHooks(HINSTANCE pModule);
-
-MIR_CORE_DLL(HANDLE) CreateServiceFunction(const char *name, MIRANDASERVICE serviceProc);
-MIR_CORE_DLL(HANDLE) CreateServiceFunctionParam(const char *name, MIRANDASERVICEPARAM serviceProc, LPARAM lParam);
-MIR_CORE_DLL(HANDLE) CreateServiceFunctionObj(const char *name, MIRANDASERVICEOBJ serviceProc, void* object);
-MIR_CORE_DLL(HANDLE) CreateServiceFunctionObjParam(const char *name, MIRANDASERVICEOBJPARAM serviceProc, void* object, LPARAM lParam);
-MIR_CORE_DLL(HANDLE) CreateProtoServiceFunction(const char *szModule, const char *szService, MIRANDASERVICE serviceProc);
-MIR_CORE_DLL(int) DestroyServiceFunction(HANDLE hService);
-MIR_CORE_DLL(bool) ServiceExists(const char *name);
-
-MIR_CORE_DLL(INT_PTR) CallService(const char *name, WPARAM wParam = 0, LPARAM lParam = 0);
-MIR_CORE_DLL(INT_PTR) CallServiceSync(const char *name, WPARAM wParam = 0, LPARAM lParam = 0);
-
-MIR_CORE_DLL(INT_PTR) CallFunctionSync(INT_PTR(__stdcall *func)(void *), void *arg);
-MIR_CORE_DLL(int) CallFunctionAsync(void (__stdcall *func)(void *), void *arg);
-MIR_CORE_DLL(void) KillModuleServices(HINSTANCE hInst);
-MIR_CORE_DLL(void) KillObjectServices(void* pObject);
-
-MIR_APP_DLL(int) ProtoServiceExists(const char *szModule, const char *szService);
-MIR_APP_DLL(INT_PTR) CallProtoService(const char *szModule, const char *szService, WPARAM wParam = 0, LPARAM lParam = 0);
-
-///////////////////////////////////////////////////////////////////////////////
-// exceptions
-
-typedef DWORD (__cdecl *pfnExceptionFilter)(DWORD code, EXCEPTION_POINTERS* info);
-
-MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter(void);
-MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter pMirandaExceptFilter);
-
-///////////////////////////////////////////////////////////////////////////////
-// icons support
-
-struct IconItem
-{
- char *szDescr, *szName;
- int defIconID, size;
- HANDLE hIcolib;
-};
-
-struct IconItemT
-{
- wchar_t *tszDescr;
- char *szName;
- int defIconID, size;
- HANDLE hIcolib;
-};
-
-MIR_CORE_DLL(void) Icon_Register(HINSTANCE hInst, const char *szSection, IconItem *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin);
-MIR_CORE_DLL(void) Icon_RegisterT(HINSTANCE hInst, const wchar_t *szSection, IconItemT *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin);
-
-///////////////////////////////////////////////////////////////////////////////
-// language packs support
-
-MIR_CORE_DLL(unsigned int) mir_hash(const void *key, unsigned int len);
-
-#pragma optimize("gt", on)
-__forceinline unsigned int mir_hashstr(const char *key)
-{
- if (key == nullptr) return 0;
- else {
- unsigned int len = (unsigned int)strlen((const char*)key);
- return mir_hash(key, len);
-} }
-
-__forceinline unsigned int mir_hashstrW(const wchar_t *key)
-{
- if (key == nullptr) return 0;
- else {
- unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
- return mir_hash(key, len * sizeof(wchar_t));
-} }
-#pragma optimize("", on)
-
-#define mir_hashstrT mir_hashstrW
-
-///////////////////////////////////////////////////////////////////////////////
-// lists
-
-typedef int (*FSortFunc)(void*, void*); // sort function prototype
-
-// Assumes first 32 bit value of the data is the numeric key
-// and uses it to perform sort/search operations, this results
-// in much better performance as no compare function calls needed
-// Incredibly useful for Hash Tables
-#define NumericKeySort (FSortFunc)(void*) -1
-#define HandleKeySort (FSortFunc)(void*) -2
-#define PtrKeySort (FSortFunc)(void*) -3
-
-typedef struct
-{
- void** items;
- int realCount;
- int limit;
- int increment;
-
- FSortFunc sortFunc;
-}
- SortedList;
-
-MIR_CORE_DLL(SortedList*) List_Create(int p_limit, int p_increment);
-MIR_CORE_DLL(void) List_Destroy(SortedList* p_list);
-MIR_CORE_DLL(void*) List_Find(SortedList* p_list, void* p_value);
-MIR_CORE_DLL(int) List_GetIndex(SortedList* p_list, void* p_value, int* p_index);
-MIR_CORE_DLL(int) List_IndexOf(SortedList* p_list, void* p_value);
-MIR_CORE_DLL(int) List_Insert(SortedList* p_list, void* p_value, int p_index);
-MIR_CORE_DLL(int) List_InsertPtr(SortedList* list, void* p);
-MIR_CORE_DLL(int) List_Remove(SortedList* p_list, int index);
-MIR_CORE_DLL(int) List_RemovePtr(SortedList* list, void* p);
-MIR_CORE_DLL(void) List_Copy(SortedList* s, SortedList* d, size_t itemSize);
-MIR_CORE_DLL(void) List_ObjCopy(SortedList* s, SortedList* d, size_t itemSize);
-
-///////////////////////////////////////////////////////////////////////////////
-// logging functions
-
-MIR_CORE_DLL(HANDLE) mir_createLog(const char *pszName, const wchar_t *ptszDescr, const wchar_t *ptszFile, unsigned options);
-MIR_CORE_DLL(void) mir_closeLog(HANDLE hLogger);
-
-MIR_C_CORE_DLL(int) mir_writeLogA(HANDLE hLogger, const char *format, ...);
-MIR_C_CORE_DLL(int) mir_writeLogW(HANDLE hLogger, const wchar_t *format, ...);
-
-MIR_CORE_DLL(int) mir_writeLogVA(HANDLE hLogger, const char *format, va_list args);
-MIR_CORE_DLL(int) mir_writeLogVW(HANDLE hLogger, const wchar_t *format, va_list args);
-
-///////////////////////////////////////////////////////////////////////////////
-// md5 functions
-
-typedef struct mir_md5_state_s {
- UINT32 count[2]; /* message length in bits, lsw first */
- UINT32 abcd[4]; /* digest buffer */
- BYTE buf[64]; /* accumulate block */
-} mir_md5_state_t;
-
-MIR_CORE_DLL(void) mir_md5_init(mir_md5_state_t *pms);
-MIR_CORE_DLL(void) mir_md5_append(mir_md5_state_t *pms, const BYTE *data, size_t nbytes);
-MIR_CORE_DLL(void) mir_md5_finish(mir_md5_state_t *pms, BYTE digest[16]);
-MIR_CORE_DLL(void) mir_md5_hash(const BYTE *data, size_t len, BYTE digest[16]);
-
-///////////////////////////////////////////////////////////////////////////////
-// memory functions
-
-MIR_C_CORE_DLL(void*) mir_alloc(size_t);
-MIR_C_CORE_DLL(void*) mir_calloc(size_t);
-MIR_C_CORE_DLL(void*) mir_realloc(void* ptr, size_t);
-MIR_C_CORE_DLL(void) mir_free(void* ptr);
-
-MIR_CORE_DLL(size_t) mir_strlen(const char *p);
-MIR_CORE_DLL(size_t) mir_wstrlen(const wchar_t *p);
-
-MIR_CORE_DLL(char*) mir_strcpy(char *dest, const char *src);
-MIR_CORE_DLL(wchar_t*) mir_wstrcpy(wchar_t *dest, const wchar_t *src);
-
-MIR_CORE_DLL(char*) mir_strncpy(char *dest, const char *src, size_t len);
-MIR_CORE_DLL(wchar_t*) mir_wstrncpy(wchar_t *dest, const wchar_t *src, size_t len);
-
-MIR_CORE_DLL(char*) mir_strcat(char *dest, const char *src);
-MIR_CORE_DLL(wchar_t*) mir_wstrcat(wchar_t *dest, const wchar_t *src);
-
-MIR_CORE_DLL(char*) mir_strncat(char *dest, const char *src, size_t len);
-MIR_CORE_DLL(wchar_t*) mir_wstrncat(wchar_t *dest, const wchar_t *src, size_t len);
-
-MIR_CORE_DLL(int) mir_strcmp(const char *p1, const char *p2);
-MIR_CORE_DLL(int) mir_strncmp(const char *p1, const char *p2, size_t n);
-MIR_CORE_DLL(int) mir_wstrcmp(const wchar_t *p1, const wchar_t *p2);
-MIR_CORE_DLL(int) mir_wstrncmp(const wchar_t *p1, const wchar_t *p2, size_t n);
-
-MIR_CORE_DLL(int) mir_strcmpi(const char *p1, const char *p2);
-MIR_CORE_DLL(int) mir_strncmpi(const char *p1, const char *p2, size_t n);
-MIR_CORE_DLL(int) mir_wstrcmpi(const wchar_t *p1, const wchar_t *p2);
-MIR_CORE_DLL(int) mir_wstrncmpi(const wchar_t *p1, const wchar_t *p2, size_t n);
-
-MIR_CORE_DLL(char*) mir_strdup(const char* str);
-MIR_CORE_DLL(wchar_t*) mir_wstrdup(const wchar_t* str);
-
-MIR_CORE_DLL(char*) mir_strndup(const char* str, size_t len);
-MIR_CORE_DLL(wchar_t*) mir_wstrndup(const wchar_t *str, size_t len);
-
-MIR_CORE_DLL(const wchar_t*) mir_wstrstri(const wchar_t *s1, const wchar_t *s2);
-
-///////////////////////////////////////////////////////////////////////////////
-// print functions
-
-MIR_CORE_DLL(int) mir_snprintf(_Pre_notnull_ _Always_(_Post_z_) char *buffer, size_t count, _Printf_format_string_ const char* fmt, ...);
-MIR_CORE_DLL(int) mir_snwprintf(_Pre_notnull_ _Always_(_Post_z_) wchar_t *buffer, size_t count, _Printf_format_string_ const wchar_t* fmt, ...);
-MIR_CORE_DLL(int) mir_vsnprintf(_Pre_notnull_ _Always_(_Post_z_) char *buffer, size_t count, _Printf_format_string_ const char* fmt, va_list va);
-MIR_CORE_DLL(int) mir_vsnwprintf(_Pre_notnull_ _Always_(_Post_z_) wchar_t *buffer, size_t count, _Printf_format_string_ const wchar_t* fmt, va_list va);
-
-///////////////////////////////////////////////////////////////////////////////
-// protocol functions
-
-struct PROTO_INTERFACE;
-
-MIR_APP_DLL(INT_PTR) ProtoBroadcastAck(const char *szModule, MCONTACT hContact, int type, int result, HANDLE hProcess, LPARAM lParam = 0);
-MIR_APP_DLL(void) ProtoBroadcastAsync(const char *szModule, MCONTACT hContact, int type, int result, HANDLE hProcess, LPARAM lParam = 0);
-
-// avatar support functions
-
-// returns image extension by a PA_* constant or empty string for PA_FORMAT_UNKNOWN
-MIR_APP_DLL(const wchar_t*) ProtoGetAvatarExtension(int format);
-
-// detects image format by extension
-MIR_APP_DLL(int) ProtoGetAvatarFormat(const wchar_t *ptszFileName);
-
-// detects image format by its contents
-MIR_APP_DLL(int) ProtoGetAvatarFileFormat(const wchar_t *ptszFileName);
-
-// returns the mime type according to a picture type (PA_*) passed
-MIR_APP_DLL(const char*) ProtoGetAvatarMimeType(int iFileType);
-
-// returns the picture type (PA_*) according to a mime type passed
-MIR_APP_DLL(int) ProtoGetAvatarFormatByMimeType(const char *pwszMimeType);
-
-// returns the image format and extension by the first bytes of picture
-// ptszExtension might be NULL
-#if defined( __cplusplus )
- MIR_APP_DLL(int) ProtoGetBufferFormat(const void *buf, const wchar_t **ptszExtension = nullptr);
-#else
- MIR_APP_DLL(int) ProtoGetBufferFormat(const void *buf, const wchar_t **ptszExtension);
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// sha1 functions
-
-#define MIR_SHA1_HASH_SIZE 20
-#define MIR_SHA_BLOCKSIZE 64
-
-struct mir_sha1_ctx
-{
- ULONG H[5];
- ULONG W[80];
- int lenW;
- ULONG sizeHi, sizeLo;
-};
-
-MIR_CORE_DLL(void) mir_sha1_init(mir_sha1_ctx *ctx);
-MIR_CORE_DLL(void) mir_sha1_append(mir_sha1_ctx *ctx, const BYTE *dataIn, size_t len);
-MIR_CORE_DLL(void) mir_sha1_finish(mir_sha1_ctx *ctx, BYTE hashout[MIR_SHA1_HASH_SIZE]);
-MIR_CORE_DLL(void) mir_sha1_hash(BYTE *dataIn, size_t len, BYTE hashout[MIR_SHA1_HASH_SIZE]);
-
-///////////////////////////////////////////////////////////////////////////////
-// sha256 functions
-
-#define MIR_SHA256_HASH_SIZE 32
-
-struct SHA256_CONTEXT
-{
- UINT32 h0, h1, h2, h3, h4, h5, h6, h7;
- UINT32 nblocks;
- BYTE buf[MIR_SHA_BLOCKSIZE];
- int count;
-};
-
-MIR_CORE_DLL(void) mir_sha256_init(SHA256_CONTEXT *ctx);
-MIR_CORE_DLL(void) mir_sha256_write(SHA256_CONTEXT *ctx, const void *dataIn, size_t len);
-MIR_CORE_DLL(void) mir_sha256_final(SHA256_CONTEXT *ctx, BYTE hashout[MIR_SHA256_HASH_SIZE]);
-MIR_CORE_DLL(void) mir_sha256_hash(const void *dataIn, size_t len, BYTE hashout[MIR_SHA256_HASH_SIZE]);
-
-///////////////////////////////////////////////////////////////////////////////
-// strings
-
-MIR_CORE_DLL(void*) mir_base64_decode(const char *input, size_t *outputLen);
-MIR_CORE_DLL(char*) mir_base64_encode(const void *input, size_t inputLen);
-MIR_CORE_DLL(char*) mir_base64_encodebuf(const void *input, size_t inputLen, char *output, size_t outLen);
-
-__forceinline size_t mir_base64_encode_bufsize(size_t inputLen)
-{
- return 4 * ((inputLen + 2) / 3) + 1;
-}
-
-MIR_CORE_DLL(char*) rtrim(char *str);
-MIR_CORE_DLL(wchar_t*) rtrimw(wchar_t *str);
-
-MIR_CORE_DLL(char*) ltrim(char *str); // returns pointer to the beginning of string
-MIR_CORE_DLL(wchar_t*) ltrimw(wchar_t *str);
-
-MIR_CORE_DLL(char*) ltrimp(char *str); // returns pointer to the trimmed portion of string
-MIR_CORE_DLL(wchar_t*) ltrimpw(wchar_t *str);
-
-MIR_CORE_DLL(char*) strdel(char *str, size_t len);
-MIR_CORE_DLL(wchar_t*) strdelw(wchar_t *str, size_t len);
-
-MIR_CORE_DLL(int) wildcmp(const char *name, const char *mask);
-MIR_CORE_DLL(int) wildcmpw(const wchar_t *name, const wchar_t *mask);
-
-MIR_CORE_DLL(int) wildcmpi(const char *name, const char *mask);
-MIR_CORE_DLL(int) wildcmpiw(const wchar_t *name, const wchar_t *mask);
-
-MIR_CORE_DLL(char*) bin2hex(const void *pData, size_t len, char *dest);
-MIR_CORE_DLL(wchar_t*) bin2hexW(const void *pData, size_t len, wchar_t *dest);
-
-MIR_CORE_DLL(bool) hex2bin(const char *pSrc, void *pData, size_t len);
-MIR_CORE_DLL(bool) hex2binW(const wchar_t *pSrc, void *pData, size_t len);
-
-__forceinline char* lrtrim(char *str) { return ltrim(rtrim(str)); };
-__forceinline char* lrtrimp(char *str) { return ltrimp(rtrim(str)); };
-
-#if defined( __cplusplus )
- MIR_CORE_DLL(char*) replaceStr(char* &dest, const char *src);
- MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t* &dest, const wchar_t *src);
-#else
- MIR_CORE_DLL(char*) replaceStr(char **dest, const char *src);
- MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t **dest, const wchar_t *src);
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// text conversion functions
-
-union MAllStrings
-{
- char *a; // utf8 or ansi strings
- wchar_t *w; // strings of WCHARs
-};
-
-union MAllCStrings
-{
- const char *a; // utf8 or ansi strings
- const wchar_t *w; // strings of WCHARs
-};
-
-union MAllStringArray
-{
- char **a; // array of utf8 or ansi strings
- wchar_t **w; // array of strings of WCHARs
-};
-
-union MAllCStringArray
-{
- const char **a; // array of utf8 or ansi strings
- const wchar_t **w; // array of strings of WCHARs
-};
-
-MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage);
-MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src);
-MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage);
-MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src);
-
-///////////////////////////////////////////////////////////////////////////////
-// threads
-
-typedef void (__cdecl *pThreadFunc)(void *param);
-typedef unsigned (__stdcall *pThreadFuncEx)(void *param);
-typedef unsigned (__cdecl *pThreadFuncOwner)(void *owner, void *param);
-
-#if defined( __cplusplus )
- MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner = nullptr);
-#else
- MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner);
-#endif
-MIR_CORE_DLL(INT_PTR) Thread_Pop(void);
-MIR_CORE_DLL(void) Thread_Wait(void);
-
-#if defined( __cplusplus )
-MIR_CORE_DLL(HANDLE) mir_forkthread(pThreadFunc aFunc, void *arg = nullptr);
-MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void *arg = nullptr, unsigned *pThreadID = nullptr);
-MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg = nullptr, unsigned *pThreadID = nullptr);
-#else
-MIR_CORE_DLL(HANDLE) mir_forkthread(pThreadFunc aFunc, void *arg);
-MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void *arg, unsigned *pThreadID);
-MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg, unsigned *pThreadID);
-#endif
-
-MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName);
-
-MIR_CORE_DLL(void) KillObjectThreads(void* pObject);
-
-///////////////////////////////////////////////////////////////////////////////
-// utf8 interface
-
-MIR_CORE_DLL(BOOL) Utf8CheckString(const char* str);
-MIR_CORE_DLL(int) Utf8toUcs2(const char *src, size_t srclen, wchar_t *dst, size_t dstlen); // returns 0 on error
-
-MIR_CORE_DLL(char*) mir_utf8decode(char* str, wchar_t** ucs2);
-MIR_CORE_DLL(char*) mir_utf8decodecp(char* str, int codepage, wchar_t** ucs2);
-MIR_CORE_DLL(wchar_t*) mir_utf8decodeW(const char* str);
-
-MIR_CORE_DLL(char*) mir_utf8encode(const char* str);
-MIR_CORE_DLL(char*) mir_utf8encodecp(const char* src, int codepage);
-MIR_CORE_DLL(char*) mir_utf8encodeW(const wchar_t* str);
-
-MIR_CORE_DLL(int) mir_utf8lenW(const wchar_t *src);
-
-__forceinline char* mir_utf8decodeA(const char* src)
-{
- char *tmp = mir_strdup(src);
- mir_utf8decode(tmp, nullptr);
- return tmp;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Window subclassing
-
-MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc);
-MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC oldWndProc);
-MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam);
-MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc);
-
-MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst);
-
-///////////////////////////////////////////////////////////////////////////////
-// Windows utilities
-
-MIR_CORE_DLL(BOOL) IsWinVerVistaPlus();
-MIR_CORE_DLL(BOOL) IsWinVer7Plus();
-MIR_CORE_DLL(BOOL) IsWinVer8Plus();
-MIR_CORE_DLL(BOOL) IsWinVer81Plus();
-MIR_CORE_DLL(BOOL) IsWinVer10Plus();
-
-MIR_CORE_DLL(BOOL) IsFullScreen();
-MIR_CORE_DLL(BOOL) IsWorkstationLocked();
-MIR_CORE_DLL(BOOL) IsScreenSaverRunning();
-MIR_CORE_DLL(BOOL) IsTerminalDisconnected();
-
-// returns OS version in version of Windows NT xx.xx
-MIR_CORE_DLL(BOOL) OS_GetShortString(char *buf, size_t bufSize);
-
-// returns full OS version
-MIR_CORE_DLL(BOOL) OS_GetDisplayString(char *buf, size_t bufSize);
-
-///////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) UnloadCoreModule(void);
-
-#if defined(__cplusplus)
-}
-
-template <typename T>
-HANDLE mir_forkThread(void(__cdecl *pFunc)(T* param), T *arg)
-{
- return mir_forkthread((pThreadFunc)pFunc, arg);
-}
-
-template <size_t _Size>
-inline int mir_snprintf(_Pre_notnull_ _Always_(_Post_z_) char(&buffer)[_Size], _In_z_ _Printf_format_string_ const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- int ret = mir_vsnprintf(buffer, _Size, fmt, args);
- va_end(args);
- return ret;
-}
-
-template <size_t _Size>
-inline int mir_snwprintf(_Pre_notnull_ _Always_(_Post_z_) wchar_t(&buffer)[_Size], _In_z_ _Printf_format_string_ const wchar_t* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- int ret = mir_vsnwprintf(buffer, _Size, fmt, args);
- va_end(args);
- return ret;
-}
-
-template <size_t _Size>
-inline int mir_vsnprintf(_Pre_notnull_ _Always_(_Post_z_) char(&buffer)[_Size], _In_z_ _Printf_format_string_ const char* fmt, va_list va)
-{
- return mir_vsnprintf(buffer, _Size, fmt, va);
-}
-
-template <size_t _Size>
-inline int mir_vsnwprintf(_Pre_notnull_ _Always_(_Post_z_) wchar_t(&buffer)[_Size], _In_z_ _Printf_format_string_ const wchar_t* fmt, va_list va)
-{
- return mir_vsnwprintf(buffer, _Size, fmt, va);
-}
-
-#endif
-
-#ifndef MIR_CORE_EXPORTS
- #pragma comment(lib, "mir_core.lib")
-#endif
-
-#ifndef MIR_APP_EXPORTS
- #pragma comment(lib, "mir_app.lib")
-#endif
-
-#endif // M_CORE_H
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+Copyright (c) 2000-08 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 M_CORE_H__
+#define M_CORE_H__ 1
+
+#ifdef _MSC_VER
+ #include <sal.h>
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifndef M_TYPES_H__
+ #include <m_types.h>
+#endif
+
+#ifdef MIR_CORE_EXPORTS
+ #define MIR_CORE_EXPORT MIR_EXPORT
+#else
+ #define MIR_CORE_EXPORT MIR_IMPORT
+#endif
+
+#define MIR_CORE_DLL(T) MIR_CORE_EXPORT T MIR_SYSCALL
+#define MIR_C_CORE_DLL(T) MIR_CORE_EXPORT T MIR_CDECL
+
+#ifdef MIR_APP_EXPORTS
+ #define MIR_APP_EXPORT MIR_EXPORT
+ typedef struct NetlibUser* HNETLIBUSER;
+ typedef struct NetlibConnection* HNETLIBCONN;
+ typedef struct NetlibBoundPort* HNETLIBBIND;
+#else
+ #define MIR_APP_EXPORT MIR_IMPORT
+ DECLARE_HANDLE(HNETLIBUSER);
+ DECLARE_HANDLE(HNETLIBCONN);
+ DECLARE_HANDLE(HNETLIBBIND);
+#endif
+
+typedef struct TMO_IntMenuItem* HGENMENU;
+
+class CMPluginBase;
+typedef const CMPluginBase* HPLUGIN;
+
+#define MIR_APP_DLL(T) MIR_APP_EXPORT T MIR_SYSCALL
+
+#pragma warning(disable:4201 4127 4312 4706)
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// command line support
+
+MIR_CORE_DLL(void) CmdLine_Parse(const wchar_t *ptszCmdLine);
+MIR_CORE_DLL(const wchar_t*) CmdLine_GetOption(const wchar_t *ptszParameter);
+
+///////////////////////////////////////////////////////////////////////////////
+// database functions
+
+typedef uint32_t MCONTACT;
+#define INVALID_CONTACT_ID (MCONTACT(-1))
+
+typedef uint32_t MEVENT;
+
+///////////////////////////////////////////////////////////////////////////////
+// events, hooks & services
+
+#define MAXMODULELABELLENGTH 64
+
+typedef int (*MIRANDAHOOK)(WPARAM, LPARAM);
+typedef int (*MIRANDAHOOKPARAM)(WPARAM, LPARAM, LPARAM);
+typedef int (*MIRANDAHOOKOBJ)(void*, WPARAM, LPARAM);
+typedef int (*MIRANDAHOOKOBJPARAM)(void*, WPARAM, LPARAM, LPARAM);
+
+typedef INT_PTR (*MIRANDASERVICE)(WPARAM, LPARAM);
+typedef INT_PTR (*MIRANDASERVICEPARAM)(WPARAM, LPARAM, LPARAM);
+typedef INT_PTR (*MIRANDASERVICEOBJ)(void*, WPARAM, LPARAM);
+typedef INT_PTR (*MIRANDASERVICEOBJPARAM)(void*, WPARAM, LPARAM, LPARAM);
+
+#ifdef _WIN64
+ #define CALLSERVICE_NOTFOUND ((INT_PTR)0x8000000000000000)
+#else
+ #define CALLSERVICE_NOTFOUND ((int)0x80000000)
+#endif
+
+MIR_CORE_DLL(HANDLE) CreateHookableEvent(const char *name);
+MIR_CORE_DLL(int) DestroyHookableEvent(HANDLE hEvent);
+MIR_CORE_DLL(int) SetHookDefaultForHookableEvent(HANDLE hEvent, MIRANDAHOOK pfnHook);
+MIR_CORE_DLL(int) CallPluginEventHook(HINSTANCE hInst, HANDLE hEvent, WPARAM wParam = 0, LPARAM lParam = 0);
+MIR_CORE_DLL(int) CallObjectEventHook(void *pObject, HANDLE hEvent, WPARAM wParam = 0, LPARAM lParam = 0);
+MIR_CORE_DLL(int) NotifyEventHooks(HANDLE hEvent, WPARAM wParam = 0, LPARAM lParam = 0);
+MIR_CORE_DLL(int) NotifyFastHook(HANDLE hEvent, WPARAM wParam = 0, LPARAM lParam = 0);
+
+MIR_CORE_DLL(HANDLE) HookEvent(const char *name, MIRANDAHOOK hookProc);
+MIR_CORE_DLL(HANDLE) HookEventParam(const char *name, MIRANDAHOOKPARAM hookProc, LPARAM lParam = 0);
+MIR_CORE_DLL(HANDLE) HookEventObj(const char *name, MIRANDAHOOKOBJ hookProc, void* object);
+MIR_CORE_DLL(HANDLE) HookEventObjParam(const char *name, MIRANDAHOOKOBJPARAM hookProc, void* object, LPARAM lParam);
+MIR_CORE_DLL(HANDLE) HookEventMessage(const char *name, HWND hwnd, UINT message);
+
+// executes the event handler if event is missing
+MIR_CORE_DLL(HANDLE) HookTemporaryEvent(const char *name, MIRANDAHOOK hookProc);
+
+MIR_CORE_DLL(int) UnhookEvent(HANDLE hHook);
+MIR_CORE_DLL(void) KillObjectEventHooks(void* pObject);
+MIR_CORE_DLL(void) KillModuleEventHooks(HINSTANCE pModule);
+
+MIR_CORE_DLL(HANDLE) CreateServiceFunction(const char *name, MIRANDASERVICE serviceProc);
+MIR_CORE_DLL(HANDLE) CreateServiceFunctionParam(const char *name, MIRANDASERVICEPARAM serviceProc, LPARAM lParam);
+MIR_CORE_DLL(HANDLE) CreateServiceFunctionObj(const char *name, MIRANDASERVICEOBJ serviceProc, void* object);
+MIR_CORE_DLL(HANDLE) CreateServiceFunctionObjParam(const char *name, MIRANDASERVICEOBJPARAM serviceProc, void* object, LPARAM lParam);
+MIR_CORE_DLL(HANDLE) CreateProtoServiceFunction(const char *szModule, const char *szService, MIRANDASERVICE serviceProc);
+MIR_CORE_DLL(int) DestroyServiceFunction(HANDLE hService);
+MIR_CORE_DLL(bool) ServiceExists(const char *name);
+
+MIR_CORE_DLL(INT_PTR) CallService(const char *name, WPARAM wParam = 0, LPARAM lParam = 0);
+MIR_CORE_DLL(INT_PTR) CallServiceSync(const char *name, WPARAM wParam = 0, LPARAM lParam = 0);
+
+MIR_CORE_DLL(INT_PTR) CallFunctionSync(INT_PTR(MIR_SYSCALL *func)(void *), void *arg);
+MIR_CORE_DLL(int) CallFunctionAsync(void (MIR_SYSCALL *func)(void *), void *arg);
+MIR_CORE_DLL(void) KillModuleServices(HINSTANCE hInst);
+MIR_CORE_DLL(void) KillObjectServices(void* pObject);
+
+MIR_APP_DLL(int) ProtoServiceExists(const char *szModule, const char *szService);
+MIR_APP_DLL(INT_PTR) CallProtoService(const char *szModule, const char *szService, WPARAM wParam = 0, LPARAM lParam = 0);
+
+///////////////////////////////////////////////////////////////////////////////
+// exceptions
+
+typedef DWORD (MIR_CDECL *pfnExceptionFilter)(DWORD code, EXCEPTION_POINTERS *info);
+
+MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter(void);
+MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter pMirandaExceptFilter);
+
+///////////////////////////////////////////////////////////////////////////////
+// icons support
+
+struct IconItem
+{
+ char *szDescr, *szName;
+ int defIconID, size;
+ HANDLE hIcolib;
+};
+
+struct IconItemT
+{
+ wchar_t *tszDescr;
+ char *szName;
+ int defIconID, size;
+ HANDLE hIcolib;
+};
+
+MIR_CORE_DLL(void) Icon_Register(HINSTANCE hInst, const char *szSection, IconItem *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin);
+MIR_CORE_DLL(void) Icon_RegisterT(HINSTANCE hInst, const wchar_t *szSection, IconItemT *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin);
+
+///////////////////////////////////////////////////////////////////////////////
+// language packs support
+
+MIR_CORE_DLL(unsigned int) mir_hash(const void *key, unsigned int len);
+
+#pragma optimize("gt", on)
+__forceinline unsigned int mir_hashstr(const char *key)
+{
+ if (key == nullptr) return 0;
+ else {
+ unsigned int len = (unsigned int)strlen((const char*)key);
+ return mir_hash(key, len);
+} }
+
+__forceinline unsigned int mir_hashstrW(const wchar_t *key)
+{
+ if (key == nullptr) return 0;
+ else {
+ unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
+ return mir_hash(key, len * sizeof(wchar_t));
+} }
+#pragma optimize("", on)
+
+#define mir_hashstrT mir_hashstrW
+
+///////////////////////////////////////////////////////////////////////////////
+// lists
+
+typedef int (*FSortFunc)(void*, void*); // sort function prototype
+
+// Assumes first 32 bit value of the data is the numeric key
+// and uses it to perform sort/search operations, this results
+// in much better performance as no compare function calls needed
+// Incredibly useful for Hash Tables
+#define NumericKeySort (FSortFunc)(void*) -1
+#define HandleKeySort (FSortFunc)(void*) -2
+#define PtrKeySort (FSortFunc)(void*) -3
+
+typedef struct
+{
+ void** items;
+ int realCount;
+ int limit;
+ int increment;
+
+ FSortFunc sortFunc;
+}
+ SortedList;
+
+MIR_CORE_DLL(SortedList*) List_Create(int p_limit, int p_increment);
+MIR_CORE_DLL(void) List_Destroy(SortedList* p_list);
+MIR_CORE_DLL(void*) List_Find(SortedList* p_list, void* p_value);
+MIR_CORE_DLL(int) List_GetIndex(SortedList* p_list, void* p_value, int* p_index);
+MIR_CORE_DLL(int) List_IndexOf(SortedList* p_list, void* p_value);
+MIR_CORE_DLL(int) List_Insert(SortedList* p_list, void* p_value, int p_index);
+MIR_CORE_DLL(int) List_InsertPtr(SortedList* list, void* p);
+MIR_CORE_DLL(int) List_Remove(SortedList* p_list, int index);
+MIR_CORE_DLL(int) List_RemovePtr(SortedList* list, void* p);
+MIR_CORE_DLL(void) List_Copy(SortedList* s, SortedList* d, size_t itemSize);
+MIR_CORE_DLL(void) List_ObjCopy(SortedList* s, SortedList* d, size_t itemSize);
+
+///////////////////////////////////////////////////////////////////////////////
+// logging functions
+
+MIR_CORE_DLL(HANDLE) mir_createLog(const char *pszName, const wchar_t *ptszDescr, const wchar_t *ptszFile, unsigned options);
+MIR_CORE_DLL(void) mir_closeLog(HANDLE hLogger);
+
+MIR_C_CORE_DLL(int) mir_writeLogA(HANDLE hLogger, const char *format, ...);
+MIR_C_CORE_DLL(int) mir_writeLogW(HANDLE hLogger, const wchar_t *format, ...);
+
+MIR_CORE_DLL(int) mir_writeLogVA(HANDLE hLogger, const char *format, va_list args);
+MIR_CORE_DLL(int) mir_writeLogVW(HANDLE hLogger, const wchar_t *format, va_list args);
+
+///////////////////////////////////////////////////////////////////////////////
+// md5 functions
+
+typedef struct mir_md5_state_s {
+ uint32_t count[2]; /* message length in bits, lsw first */
+ uint32_t abcd[4]; /* digest buffer */
+ uint8_t buf[64]; /* accumulate block */
+} mir_md5_state_t;
+
+MIR_CORE_DLL(void) mir_md5_init(mir_md5_state_t *pms);
+MIR_CORE_DLL(void) mir_md5_append(mir_md5_state_t *pms, const BYTE *data, size_t nbytes);
+MIR_CORE_DLL(void) mir_md5_finish(mir_md5_state_t *pms, BYTE digest[16]);
+MIR_CORE_DLL(void) mir_md5_hash(const BYTE *data, size_t len, BYTE digest[16]);
+
+///////////////////////////////////////////////////////////////////////////////
+// memory functions
+
+MIR_C_CORE_DLL(void*) mir_alloc(size_t);
+MIR_C_CORE_DLL(void*) mir_calloc(size_t);
+MIR_C_CORE_DLL(void*) mir_realloc(void* ptr, size_t);
+MIR_C_CORE_DLL(void) mir_free(void* ptr);
+
+MIR_CORE_DLL(size_t) mir_strlen(const char *p);
+MIR_CORE_DLL(size_t) mir_wstrlen(const wchar_t *p);
+
+MIR_CORE_DLL(char*) mir_strcpy(char *dest, const char *src);
+MIR_CORE_DLL(wchar_t*) mir_wstrcpy(wchar_t *dest, const wchar_t *src);
+
+MIR_CORE_DLL(char*) mir_strncpy(char *dest, const char *src, size_t len);
+MIR_CORE_DLL(wchar_t*) mir_wstrncpy(wchar_t *dest, const wchar_t *src, size_t len);
+
+MIR_CORE_DLL(char*) mir_strcat(char *dest, const char *src);
+MIR_CORE_DLL(wchar_t*) mir_wstrcat(wchar_t *dest, const wchar_t *src);
+
+MIR_CORE_DLL(char*) mir_strncat(char *dest, const char *src, size_t len);
+MIR_CORE_DLL(wchar_t*) mir_wstrncat(wchar_t *dest, const wchar_t *src, size_t len);
+
+MIR_CORE_DLL(int) mir_strcmp(const char *p1, const char *p2);
+MIR_CORE_DLL(int) mir_strncmp(const char *p1, const char *p2, size_t n);
+MIR_CORE_DLL(int) mir_wstrcmp(const wchar_t *p1, const wchar_t *p2);
+MIR_CORE_DLL(int) mir_wstrncmp(const wchar_t *p1, const wchar_t *p2, size_t n);
+
+MIR_CORE_DLL(int) mir_strcmpi(const char *p1, const char *p2);
+MIR_CORE_DLL(int) mir_strncmpi(const char *p1, const char *p2, size_t n);
+MIR_CORE_DLL(int) mir_wstrcmpi(const wchar_t *p1, const wchar_t *p2);
+MIR_CORE_DLL(int) mir_wstrncmpi(const wchar_t *p1, const wchar_t *p2, size_t n);
+
+MIR_CORE_DLL(char*) mir_strdup(const char* str);
+MIR_CORE_DLL(wchar_t*) mir_wstrdup(const wchar_t* str);
+
+MIR_CORE_DLL(char*) mir_strndup(const char* str, size_t len);
+MIR_CORE_DLL(wchar_t*) mir_wstrndup(const wchar_t *str, size_t len);
+
+MIR_CORE_DLL(const wchar_t*) mir_wstrstri(const wchar_t *s1, const wchar_t *s2);
+
+///////////////////////////////////////////////////////////////////////////////
+// print functions
+
+MIR_CORE_DLL(int) mir_snprintf(_Pre_notnull_ _Always_(_Post_z_) char *buffer, size_t count, _Printf_format_string_ const char* fmt, ...);
+MIR_CORE_DLL(int) mir_snwprintf(_Pre_notnull_ _Always_(_Post_z_) wchar_t *buffer, size_t count, _Printf_format_string_ const wchar_t* fmt, ...);
+MIR_CORE_DLL(int) mir_vsnprintf(_Pre_notnull_ _Always_(_Post_z_) char *buffer, size_t count, _Printf_format_string_ const char* fmt, va_list va);
+MIR_CORE_DLL(int) mir_vsnwprintf(_Pre_notnull_ _Always_(_Post_z_) wchar_t *buffer, size_t count, _Printf_format_string_ const wchar_t* fmt, va_list va);
+
+///////////////////////////////////////////////////////////////////////////////
+// protocol functions
+
+struct PROTO_INTERFACE;
+
+MIR_APP_DLL(INT_PTR) ProtoBroadcastAck(const char *szModule, MCONTACT hContact, int type, int result, HANDLE hProcess, LPARAM lParam = 0);
+MIR_APP_DLL(void) ProtoBroadcastAsync(const char *szModule, MCONTACT hContact, int type, int result, HANDLE hProcess, LPARAM lParam = 0);
+
+// avatar support functions
+
+// returns image extension by a PA_* constant or empty string for PA_FORMAT_UNKNOWN
+MIR_APP_DLL(const wchar_t*) ProtoGetAvatarExtension(int format);
+
+// detects image format by extension
+MIR_APP_DLL(int) ProtoGetAvatarFormat(const wchar_t *ptszFileName);
+
+// detects image format by its contents
+MIR_APP_DLL(int) ProtoGetAvatarFileFormat(const wchar_t *ptszFileName);
+
+// returns the mime type according to a picture type (PA_*) passed
+MIR_APP_DLL(const char*) ProtoGetAvatarMimeType(int iFileType);
+
+// returns the picture type (PA_*) according to a mime type passed
+MIR_APP_DLL(int) ProtoGetAvatarFormatByMimeType(const char *pwszMimeType);
+
+// returns the image format and extension by the first bytes of picture
+// ptszExtension might be NULL
+#if defined( __cplusplus )
+ MIR_APP_DLL(int) ProtoGetBufferFormat(const void *buf, const wchar_t **ptszExtension = nullptr);
+#else
+ MIR_APP_DLL(int) ProtoGetBufferFormat(const void *buf, const wchar_t **ptszExtension);
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// sha1 functions
+
+#define MIR_SHA1_HASH_SIZE 20
+#define MIR_SHA_BLOCKSIZE 64
+
+struct mir_sha1_ctx
+{
+ uint32_t H[5];
+ uint32_t W[80];
+ int lenW;
+ uint32_t sizeHi, sizeLo;
+};
+
+MIR_CORE_DLL(void) mir_sha1_init(mir_sha1_ctx *ctx);
+MIR_CORE_DLL(void) mir_sha1_append(mir_sha1_ctx *ctx, const BYTE *dataIn, size_t len);
+MIR_CORE_DLL(void) mir_sha1_finish(mir_sha1_ctx *ctx, BYTE hashout[MIR_SHA1_HASH_SIZE]);
+MIR_CORE_DLL(void) mir_sha1_hash(BYTE *dataIn, size_t len, BYTE hashout[MIR_SHA1_HASH_SIZE]);
+
+///////////////////////////////////////////////////////////////////////////////
+// sha256 functions
+
+#define MIR_SHA256_HASH_SIZE 32
+
+struct SHA256_CONTEXT
+{
+ uint32_t h0, h1, h2, h3, h4, h5, h6, h7;
+ uint32_t nblocks;
+ BYTE buf[MIR_SHA_BLOCKSIZE];
+ int count;
+};
+
+MIR_CORE_DLL(void) mir_sha256_init(SHA256_CONTEXT *ctx);
+MIR_CORE_DLL(void) mir_sha256_write(SHA256_CONTEXT *ctx, const void *dataIn, size_t len);
+MIR_CORE_DLL(void) mir_sha256_final(SHA256_CONTEXT *ctx, BYTE hashout[MIR_SHA256_HASH_SIZE]);
+MIR_CORE_DLL(void) mir_sha256_hash(const void *dataIn, size_t len, BYTE hashout[MIR_SHA256_HASH_SIZE]);
+
+///////////////////////////////////////////////////////////////////////////////
+// strings
+
+MIR_CORE_DLL(void*) mir_base64_decode(const char *input, size_t *outputLen);
+MIR_CORE_DLL(char*) mir_base64_encode(const void *input, size_t inputLen);
+MIR_CORE_DLL(char*) mir_base64_encodebuf(const void *input, size_t inputLen, char *output, size_t outLen);
+
+__forceinline size_t mir_base64_encode_bufsize(size_t inputLen)
+{
+ return 4 * ((inputLen + 2) / 3) + 1;
+}
+
+MIR_CORE_DLL(char*) rtrim(char *str);
+MIR_CORE_DLL(wchar_t*) rtrimw(wchar_t *str);
+
+MIR_CORE_DLL(char*) ltrim(char *str); // returns pointer to the beginning of string
+MIR_CORE_DLL(wchar_t*) ltrimw(wchar_t *str);
+
+MIR_CORE_DLL(char*) ltrimp(char *str); // returns pointer to the trimmed portion of string
+MIR_CORE_DLL(wchar_t*) ltrimpw(wchar_t *str);
+
+MIR_CORE_DLL(char*) strdel(char *str, size_t len);
+MIR_CORE_DLL(wchar_t*) strdelw(wchar_t *str, size_t len);
+
+MIR_CORE_DLL(int) wildcmp(const char *name, const char *mask);
+MIR_CORE_DLL(int) wildcmpw(const wchar_t *name, const wchar_t *mask);
+
+MIR_CORE_DLL(int) wildcmpi(const char *name, const char *mask);
+MIR_CORE_DLL(int) wildcmpiw(const wchar_t *name, const wchar_t *mask);
+
+MIR_CORE_DLL(char*) bin2hex(const void *pData, size_t len, char *dest);
+MIR_CORE_DLL(wchar_t*) bin2hexW(const void *pData, size_t len, wchar_t *dest);
+
+MIR_CORE_DLL(bool) hex2bin(const char *pSrc, void *pData, size_t len);
+MIR_CORE_DLL(bool) hex2binW(const wchar_t *pSrc, void *pData, size_t len);
+
+__forceinline char* lrtrim(char *str) { return ltrim(rtrim(str)); };
+__forceinline char* lrtrimp(char *str) { return ltrimp(rtrim(str)); };
+
+#if defined( __cplusplus )
+ MIR_CORE_DLL(char*) replaceStr(char* &dest, const char *src);
+ MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t* &dest, const wchar_t *src);
+#else
+ MIR_CORE_DLL(char*) replaceStr(char **dest, const char *src);
+ MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t **dest, const wchar_t *src);
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// text conversion functions
+
+union MAllStrings
+{
+ char *a; // utf8 or ansi strings
+ wchar_t *w; // strings of WCHARs
+};
+
+union MAllCStrings
+{
+ const char *a; // utf8 or ansi strings
+ const wchar_t *w; // strings of WCHARs
+};
+
+union MAllStringArray
+{
+ char **a; // array of utf8 or ansi strings
+ wchar_t **w; // array of strings of WCHARs
+};
+
+union MAllCStringArray
+{
+ const char **a; // array of utf8 or ansi strings
+ const wchar_t **w; // array of strings of WCHARs
+};
+
+MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage);
+MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src);
+MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage);
+MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src);
+
+///////////////////////////////////////////////////////////////////////////////
+// threads
+
+typedef void (MIR_CDECL *pThreadFunc)(void *param);
+typedef unsigned (MIR_SYSCALL *pThreadFuncEx)(void *param);
+typedef unsigned (MIR_CDECL *pThreadFuncOwner)(void *owner, void *param);
+
+#if defined( __cplusplus )
+ MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner = nullptr);
+#else
+ MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner);
+#endif
+MIR_CORE_DLL(INT_PTR) Thread_Pop(void);
+MIR_CORE_DLL(void) Thread_Wait(void);
+
+#if defined( __cplusplus )
+MIR_CORE_DLL(HANDLE) mir_forkthread(pThreadFunc aFunc, void *arg = nullptr);
+MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void *arg = nullptr, unsigned *pThreadID = nullptr);
+MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg = nullptr, unsigned *pThreadID = nullptr);
+#else
+MIR_CORE_DLL(HANDLE) mir_forkthread(pThreadFunc aFunc, void *arg);
+MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void *arg, unsigned *pThreadID);
+MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg, unsigned *pThreadID);
+#endif
+
+MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName);
+
+MIR_CORE_DLL(void) KillObjectThreads(void* pObject);
+
+///////////////////////////////////////////////////////////////////////////////
+// utf8 interface
+
+MIR_CORE_DLL(BOOL) Utf8CheckString(const char* str);
+MIR_CORE_DLL(int) Utf8toUcs2(const char *src, size_t srclen, wchar_t *dst, size_t dstlen); // returns 0 on error
+
+MIR_CORE_DLL(char*) mir_utf8decode(char* str, wchar_t** ucs2);
+MIR_CORE_DLL(char*) mir_utf8decodecp(char* str, int codepage, wchar_t** ucs2);
+MIR_CORE_DLL(wchar_t*) mir_utf8decodeW(const char* str);
+
+MIR_CORE_DLL(char*) mir_utf8encode(const char* str);
+MIR_CORE_DLL(char*) mir_utf8encodecp(const char* src, int codepage);
+MIR_CORE_DLL(char*) mir_utf8encodeW(const wchar_t* str);
+
+MIR_CORE_DLL(int) mir_utf8lenW(const wchar_t *src);
+
+__forceinline char* mir_utf8decodeA(const char* src)
+{
+ char *tmp = mir_strdup(src);
+ mir_utf8decode(tmp, nullptr);
+ return tmp;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// The UUID structure below is used to for plugin UUID's and module type definitions
+
+struct MUUID
+{
+ unsigned long a;
+ unsigned short b;
+ unsigned short c;
+ unsigned char d[8];
+};
+
+__forceinline bool operator==(const MUUID &p1, const MUUID &p2)
+{
+ return memcmp(&p1, &p2, sizeof(MUUID)) == 0;
+}
+__forceinline bool operator!=(const MUUID &p1, const MUUID &p2)
+{
+ return memcmp(&p1, &p2, sizeof(MUUID)) != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Window subclassing
+
+#ifdef _MSC_VER
+
+MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc);
+MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC oldWndProc);
+MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam);
+MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc);
+
+MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst);
+
+///////////////////////////////////////////////////////////////////////////////
+// Windows utilities
+
+MIR_CORE_DLL(BOOL) IsWinVerVistaPlus();
+MIR_CORE_DLL(BOOL) IsWinVer7Plus();
+MIR_CORE_DLL(BOOL) IsWinVer8Plus();
+MIR_CORE_DLL(BOOL) IsWinVer81Plus();
+MIR_CORE_DLL(BOOL) IsWinVer10Plus();
+
+MIR_CORE_DLL(BOOL) IsFullScreen();
+MIR_CORE_DLL(BOOL) IsWorkstationLocked();
+MIR_CORE_DLL(BOOL) IsScreenSaverRunning();
+MIR_CORE_DLL(BOOL) IsTerminalDisconnected();
+
+#endif // _MSC_VER
+
+// returns OS version in version of Windows NT xx.xx
+MIR_CORE_DLL(BOOL) OS_GetShortString(char *buf, size_t bufSize);
+
+// returns full OS version
+MIR_CORE_DLL(BOOL) OS_GetDisplayString(char *buf, size_t bufSize);
+
+///////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) UnloadCoreModule(void);
+
+#if defined(__cplusplus)
+}
+
+template <typename T>
+HANDLE mir_forkThread(void(MIR_CDECL *pFunc)(T* param), T *arg)
+{
+ return mir_forkthread((pThreadFunc)pFunc, arg);
+}
+
+template <size_t _Size>
+inline int mir_snprintf(_Pre_notnull_ _Always_(_Post_z_) char(&buffer)[_Size], _In_z_ _Printf_format_string_ const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ int ret = mir_vsnprintf(buffer, _Size, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+template <size_t _Size>
+inline int mir_snwprintf(_Pre_notnull_ _Always_(_Post_z_) wchar_t(&buffer)[_Size], _In_z_ _Printf_format_string_ const wchar_t* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ int ret = mir_vsnwprintf(buffer, _Size, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+template <size_t _Size>
+inline int mir_vsnprintf(_Pre_notnull_ _Always_(_Post_z_) char(&buffer)[_Size], _In_z_ _Printf_format_string_ const char* fmt, va_list va)
+{
+ return mir_vsnprintf(buffer, _Size, fmt, va);
+}
+
+template <size_t _Size>
+inline int mir_vsnwprintf(_Pre_notnull_ _Always_(_Post_z_) wchar_t(&buffer)[_Size], _In_z_ _Printf_format_string_ const wchar_t* fmt, va_list va)
+{
+ return mir_vsnwprintf(buffer, _Size, fmt, va);
+}
+
+#endif
+
+#ifdef _MSC_VER
+ #ifndef MIR_CORE_EXPORTS
+ #pragma comment(lib, "mir_core.lib")
+ #endif
+
+ #ifndef MIR_APP_EXPORTS
+ #pragma comment(lib, "mir_app.lib")
+ #endif
+#else
+ MIR_CORE_DLL(FILE*) _wfopen(const wchar_t *pwszFileName, const wchar_t *pwszMode);
+
+ template <size_t _Size>
+ inline wchar_t* wcsncpy_s(wchar_t(&buffer)[_Size], const wchar_t *src, size_t len)
+ {
+ return wcsncpy(buffer, src, (len == _TRUNCATE) ? _Size : len);
+ }
+
+ inline wchar_t* wcsncpy_s(wchar_t *dst, size_t dstLen, const wchar_t *src, size_t len)
+ {
+ return wcsncpy(dst, src, (len == _TRUNCATE) ? dstLen : len);
+ }
+
+ inline wchar_t* wcsncat_s(wchar_t *dst, size_t dstLen, const wchar_t *src, size_t len)
+ {
+ return wcsncat(dst, src, (len == _TRUNCATE) ? dstLen : len);
+ }
+
+ template <size_t _Size>
+ inline char* strncpy_s(char(&buffer)[_Size], const char *src, size_t len)
+ {
+ return strncpy(buffer, src, (len == _TRUNCATE) ? _Size : len);
+ }
+
+ inline char* strncpy_s(char *dst, size_t dstLen, const char *src, size_t len)
+ {
+ return strncpy(dst, src, (len == _TRUNCATE) ? dstLen : len);
+ }
+
+ inline char* strncat_s(char *dst, size_t dstLen, const char *src, size_t len)
+ {
+ return strncat(dst, src, (len == _TRUNCATE) ? dstLen : len);
+ }
+#endif
+
+#endif // M_CORE_H
diff --git a/include/m_database.h b/include/m_database.h
index 5947ce1c4f..bf4e411815 100644
--- a/include/m_database.h
+++ b/include/m_database.h
@@ -1,793 +1,793 @@
-/////////////////////////////////////////////////////////////////////////////////////////
-// Miranda NG: the free IM client for Microsoft* Windows*
-//
-// Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-// Copyright (c) 2000-08 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 M_DATABASE_H__
-#define M_DATABASE_H__ 1
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// GENERALLY USEFUL STUFF
-
-#if !defined(M_SYSTEM_H__)
- #include "m_system.h"
-#endif
-
-#if !defined(M_UTILS_H__)
- #include "m_utils.h"
-#endif
-
-#ifdef _MSC_VER
- #pragma warning(disable:4201 4204)
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// database functions
-
-// Switches safety settings on or off
-// newSetting is TRUE initially.
-// Miranda's database is normally protected against corruption by agressively
-// flushing data to the disk on writes. If you're doing a lot of writes (eg in
-// an import plugin) it can sometimes be desirable to switch this feature off to
-// speed up the process. If you do switch it off, you must remember that crashes
-// are far more likely to be catastrophic, so switch it back on at the earliest
-// possible opportunity.
-// Note that if you're doing a lot of setting writes, the flush is already delayed
-// so you need not use this service for that purpose.
-
-EXTERN_C MIR_CORE_DLL(void) db_set_safety_mode(BOOL bNewMode);
-
-// Gets the number of contacts in the database, which does not count the user
-// Returns the number of contacts. They can be retrieved using contact/findfirst and contact/findnext
-
-EXTERN_C MIR_CORE_DLL(int) db_get_contact_count(void);
-
-// Removes all settings for the specified module.
-// hContact is 0 for global settings or matches the concrete contact
-
-EXTERN_C MIR_CORE_DLL(int) db_delete_module(MCONTACT hContact, const char *szModuleName);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// contact functions
-
-// Adds a new contact to the database. New contacts initially have no settings
-// whatsoever, they must all be added with db/contacts/writesetting.
-// Returns a handle to the newly created contact on success, or NULL otherwise.
-// Triggers a db/contact/added event just before it returns.
-
-EXTERN_C MIR_CORE_DLL(MCONTACT) db_add_contact(void);
-
-// Deletes the contact hContact from the database and all events and settings associated with it.
-// Returns 0 on success or nonzero if hContact was invalid
-// Please don't try to delete the user contact (hContact = NULL)
-// Triggers a db/contact/deleted event just *before* it removes anything
-// Because all events are deleted, lots of people may end up with invalid event
-// handles from this operation, which they should be prepared for.
-
-EXTERN_C MIR_CORE_DLL(int) db_delete_contact(MCONTACT hContact);
-
-// Checks if a given value is a valid contact handle, note that due
-// to the nature of multiple threading, a valid contact can still become
-// invalid after a call to this service.
-// Returns 1 if the contact is a contact, or 0 if the contact is not valid.
-
-EXTERN_C MIR_CORE_DLL(int) db_is_contact(MCONTACT hContact);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// enumerators
-
-// Enumerates the names of all modules that have stored or requested information from the database.
-// Returns the value returned by the last call to dbmep
-// This service is only really useful for debugging, in conjunction with db/contact/enumsettings
-// dbmep should return 0 to continue enumeration, or nonzero to stop.
-//
-// Modules names will be enumerated in no particular order
-// Writing to the database while module names are being enumerated will cause
-// unpredictable results in the enumeration, but the write will work.
-// szModuleName is only guaranteed to be valid for the duration of the callback.
-// If you want to keep it for longer you must allocation your own storage.
-
-typedef int(*DBMODULEENUMPROC)(const char *szModuleName, void *param);
-
-EXTERN_C MIR_CORE_DLL(int) db_enum_modules(DBMODULEENUMPROC dbmep, void *param = nullptr);
-
-// Lists all resident settings
-
-EXTERN_C MIR_CORE_DLL(int) db_enum_residents(DBMODULEENUMPROC pFunc, void *param = nullptr);
-
-// Lists all the settings a specific modules has stored in the database for a specific contact.
-// Returns the return value of the last call to pfnEnumProc, or -1 if there are
-// no settings for that module/contact pair
-// Writing to or deleting from the database while enumerating will have
-// unpredictable results for the enumeration, but the write will succeed.
-// Use db/modules/enum to get a complete list of module names
-// szSetting is only guaranteed to be valid for the duration of the callback. If
-// you want to keep it for longer you must allocation your own storage.
-
-typedef int (*DBSETTINGENUMPROC)(const char *szSetting, void *param);
-
-EXTERN_C MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param = nullptr);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DBVARIANT: used by db/contact/getsetting and db/contact/writesetting
-
-#define DBVT_DELETED 0 // this setting just got deleted, no other values are valid
-#define DBVT_BYTE 1 // bVal and cVal are valid
-#define DBVT_WORD 2 // wVal and sVal are valid
-#define DBVT_DWORD 4 // dVal and lVal are valid
-#define DBVT_ASCIIZ 255 // pszVal is valid
-#define DBVT_BLOB 254 // cpbVal and pbVal are valid
-#define DBVT_UTF8 253 // pszVal is valid
-#define DBVT_WCHAR 252 // pwszVal is valid
-#define DBVT_ENCRYPTED 250 // blob of encrypted bytesw
-
-
-#define DBVTF_VARIABLELENGTH 0x80
-
-struct DBVARIANT
-{
- BYTE type;
- union {
- BYTE bVal; char cVal;
- WORD wVal; short sVal;
- DWORD dVal; long lVal;
- struct {
- union {
- char *pszVal;
- wchar_t *pwszVal;
- };
- WORD cchVal; //only used for db/contact/getsettingstatic
- };
- struct {
- WORD cpbVal;
- BYTE *pbVal;
- };
- };
-};
-
-#define DBEF_TEMPORARY 0x0001 // disable notifications about temporary database events
-#define DBEF_SENT 0x0002 // this event was sent by the user. If not set this event was received.
-#define DBEF_READ 0x0004 // event has been read by the user. It does not need to be processed any more except for history.
-#define DBEF_RTL 0x0008 // event contains the right-to-left aligned text
-#define DBEF_UTF 0x0010 // event contains a text in utf-8
-#define DBEF_ENCRYPTED 0x0020 // event is encrypted (never reported outside a driver)
-#define DBEF_HAS_ID 0x0040 // event has unique server id
-
-struct DBEVENTINFO
-{
- const char *szModule; // pointer to name of the module that 'owns' this event
- DWORD timestamp; // seconds since 00:00, 01/01/1970. Gives us times until 2106
- // unless you use the standard C library which is
- // signed and can only do until 2038. In GMT.
- DWORD flags; // combination of DBEF_* flags
- WORD eventType; // module-defined event type field
- int cbBlob; // size of pBlob in bytes
- PBYTE pBlob; // pointer to buffer containing module-defined event data
- const char *szId; // server id
-
- bool __forceinline markedRead() const {
- return (flags & (DBEF_SENT | DBEF_READ)) != 0;
- }
-
- wchar_t* getString(const char *str) const {
- return (flags & DBEF_UTF) ? mir_utf8decodeW(str) : mir_a2u(str);
- }
-
- bool __forceinline operator==(const DBEVENTINFO &e) {
- return (timestamp == e.timestamp && eventType == e.eventType && cbBlob == e.cbBlob && (flags & DBEF_SENT) == (e.flags & DBEF_SENT));
- }
-};
-
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_free(DBVARIANT *dbv);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Database contacts
-
-// Gets the handle of the first contact in the database. This handle can be used
-// with loads of functions. It does not need to be closed.
-// You can specify szProto to find only its contacts
-// Returns a handle to the first contact in the db on success, or NULL if there
-// are no contacts in the db.
-
-EXTERN_C MIR_CORE_DLL(MCONTACT) db_find_first(const char *szProto = nullptr);
-
-// Gets the handle of the next contact after hContact in the database. This handle
-// can be used with loads of functions. It does not need to be closed.
-// You can specify szProto to find only its contacts
-// Returns a handle to the contact after hContact in the db on success or NULL if
-// hContact was the last contact in the db or hContact was invalid.
-
-EXTERN_C MIR_CORE_DLL(MCONTACT) db_find_next(MCONTACT hContact, const char *szProto = nullptr);
-
-class Contacts
-{
- const char *m_szModule;
-
-public:
- Contacts(const char *m = nullptr) :
- m_szModule(m)
- {}
-
- class iterator
- {
- MCONTACT hContact;
- const char *m_szModule;
-
- public:
- __inline iterator(const char *_m, MCONTACT _h) :
- hContact(_h),
- m_szModule(_m)
- {}
-
- __inline iterator operator++() { hContact = ::db_find_next(hContact, m_szModule); return *this; }
- __inline bool operator!=(const iterator &p) { return hContact != p.hContact; }
- __inline operator const MCONTACT*() const { return &hContact; }
- };
-
- __inline iterator begin() const { return iterator(m_szModule, ::db_find_first(m_szModule)); }
- __inline iterator end() const { return iterator(m_szModule, 0); }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Database events
-
-// Adds a new event to a contact's event list
-// Returns a handle to the newly added event, or NULL on failure
-// Triggers a db/event/added event just before it returns.
-// Events are sorted chronologically as they are entered, so you cannot guarantee
-// that the new hEvent is the last event in the chain, however if a new event is
-// added that has a timestamp less than 90 seconds *before* the event that should
-// be after it, it will be added afterwards, to allow for protocols that only
-// store times to the nearest minute, and slight delays in transports.
-// There are a few predefined eventTypes below for easier compatibility, but
-// modules are free to define their own, beginning at 2000
-// DBEVENTINFO.timestamp is in GMT, as returned by time(). There are services
-// db/time/x below with useful stuff for dealing with it.
-
-#define EVENTTYPE_MESSAGE 0
-#define EVENTTYPE_CONTACTS 2 //v0.1.2.2+
-#define EVENTTYPE_ADDED 1000 //v0.1.1.0+: these used to be module-
-#define EVENTTYPE_AUTHREQUEST 1001 //specific codes, hence the module-
-#define EVENTTYPE_FILE 1002 //specific limit has been raised to 2000
-
-EXTERN_C MIR_CORE_DLL(MEVENT) db_event_add(MCONTACT hContact, const DBEVENTINFO *dbei);
-
-// Gets the number of events in the chain belonging to a contact in the database.
-// Returns the number of events in the chain owned by hContact or -1 if hContact
-// is invalid. They can be retrieved using the db_event_first/last() services.
-
-EXTERN_C MIR_CORE_DLL(int) db_event_count(MCONTACT hContact);
-
-// Removes a single event from the database
-// hDbEvent should have been returned by db_event_add/first/last/next/prev()
-// Returns 0 on success, or nonzero if hDbEvent was invalid
-// Triggers a db/event/deleted event just *before* the event is deleted
-
-EXTERN_C MIR_CORE_DLL(int) db_event_delete(MEVENT hDbEvent);
-
-// Edits an event in the database
-// Returns 0 on success, or nonzero on error
-
-EXTERN_C MIR_CORE_DLL(int) db_event_edit(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO *dbei);
-
-// Retrieves a handle to the first event in the chain for hContact
-// Returns the handle, or NULL if hContact is invalid or has no events
-// Events in a chain are sorted chronologically automatically
-
-EXTERN_C MIR_CORE_DLL(MEVENT) db_event_first(MCONTACT hContact);
-
-// Retrieves a handle to the first unread event in the chain for hContact
-// Returns the handle, or NULL if hContact is invalid or all its events have been read
-//
-// Events in a chain are sorted chronologically automatically, but this does not
-// necessarily mean that all events after the first unread are unread too. They
-// should be checked individually with db_event_next() and db_event_get()
-// This service is designed for startup, reloading all the events that remained
-// unread from last time
-
-EXTERN_C MIR_CORE_DLL(MEVENT) db_event_firstUnread(MCONTACT hContact);
-
-// Retrieves all the information stored in hDbEvent
-// hDbEvent should have been returned by db_event_add/first/last/next/prev()
-// Returns 0 on success or nonzero if hDbEvent is invalid
-// Don't forget to set dbe.cbSize, dbe.pBlob and dbe.cbBlob before calling this function
-// The correct value dbe.cbBlob can be got using db_event_getBlobSize
-// If successful, all the fields of dbe are filled. dbe.cbBlob is set to the
-// actual number of bytes retrieved and put in dbe.pBlob
-// If dbe.cbBlob is too small, dbe.pBlob is filled up to the size of dbe.cbBlob
-// and then dbe.cbBlob is set to the required size of data to go in dbe.pBlob
-// On return, dbe.szModule is a pointer to the database module's own internal list
-// of modules. Look but don't touch.
-
-EXTERN_C MIR_CORE_DLL(int) db_event_get(MEVENT hDbEvent, DBEVENTINFO *dbei);
-
-// Retrieves the space in bytes required to store the blob in hDbEvent
-// hDbEvent should have been returned by db_event_add/first/last/next/prev()
-// Returns the space required in bytes, or -1 if hDbEvent is invalid
-
-EXTERN_C MIR_CORE_DLL(int) db_event_getBlobSize(MEVENT hDbEvent);
-
-// Retrieves a handle to the contact that owns hDbEvent.
-// hDbEvent should have been returned by db_event_add/first/last/next/prev()
-// NULL is a valid return value, meaning, as usual, the user.
-// Returns INVALID_CONTACT_ID if hDbEvent is invalid, or the handle to the contact on success
-
-EXTERN_C MIR_CORE_DLL(MCONTACT) db_event_getContact(MEVENT hDbEvent);
-
-// Retrieves a handle to the last event in the chain for hContact
-// Returns the handle, or NULL if hContact is invalid or has no events
-// Events in a chain are sorted chronologically automatically
-
-EXTERN_C MIR_CORE_DLL(MEVENT) db_event_last(MCONTACT hContact);
-
-// Changes the flags for an event to mark it as read.
-// hDbEvent should have been returned by db_event_add/first/last/next/prev()
-// Returns the entire flag DWORD for the event after the change, or -1 if hDbEvent is invalid.
-// This is the one database write operation that does not trigger an event.
-// Modules should not save flags states for any length of time.
-
-EXTERN_C MIR_CORE_DLL(int) db_event_markRead(MCONTACT hContact, MEVENT hDbEvent);
-
-// Retrieves a handle to the next event in a chain after hDbEvent
-// Returns the handle, or NULL if hDbEvent is invalid or is the last event
-// Events in a chain are sorted chronologically automatically
-
-EXTERN_C MIR_CORE_DLL(MEVENT) db_event_next(MCONTACT hContact, MEVENT hDbEvent);
-
-// Retrieves a handle to the previous event in a chain before hDbEvent
-// Returns the handle, or NULL if hDbEvent is invalid or is the first event
-// Events in a chain are sorted chronologically automatically
-
-EXTERN_C MIR_CORE_DLL(MEVENT) db_event_prev(MCONTACT hContact, MEVENT hDbEvent);
-
-// Retrieves a handle to the event identified by its module and unique identifier
-
-EXTERN_C MIR_CORE_DLL(MEVENT) db_event_getById(const char *szModule, const char *szId);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Database settings
-
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_get(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv);
-
-EXTERN_C MIR_CORE_DLL(int) db_get_b(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue = 0);
-EXTERN_C MIR_CORE_DLL(int) db_get_w(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue = 0);
-EXTERN_C MIR_CORE_DLL(DWORD) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD errorValue = 0);
-
-EXTERN_C MIR_CORE_DLL(char*) db_get_sa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue = nullptr);
-EXTERN_C MIR_CORE_DLL(char*) db_get_utfa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue = nullptr);
-EXTERN_C MIR_CORE_DLL(wchar_t*) db_get_wsa(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue = nullptr);
-
-MIR_CORE_DLL(CMStringA) db_get_sm(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue = nullptr);
-MIR_CORE_DLL(CMStringW) db_get_wsm(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue = nullptr);
-
-EXTERN_C MIR_CORE_DLL(int) db_get_static(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest);
-EXTERN_C MIR_CORE_DLL(int) db_get_static_utf(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest);
-EXTERN_C MIR_CORE_DLL(int) db_get_wstatic(MCONTACT hContact, const char *szModule, const char *szSetting, wchar_t *pDest, int cbDest);
-
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_set(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv);
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_b(MCONTACT hContact, const char *szModule, const char *szSetting, BYTE val);
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, WORD val);
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD val);
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_s(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val);
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_ws(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *val);
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_utf(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val);
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_blob(MCONTACT hContact, const char *szModule, const char *szSetting, void *val, unsigned len);
-
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_unset(MCONTACT hContact, const char *szModule, const char *szSetting);
-
-EXTERN_C MIR_CORE_DLL(BOOL) db_set_resident(const char *szModule, const char *szService, BOOL bEnable = true);
-
-EXTERN_C MIR_CORE_DLL(INT_PTR) db_get_s(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv, const int nType = DBVT_ASCIIZ);
-#define db_get_ws(a,b,c,d) db_get_s(a,b,c,d,DBVT_WCHAR)
-#define db_get_utf(a,b,c,d) db_get_s(a,b,c,d,DBVT_UTF8)
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Profile services
-
-// Gets the name of the profile currently being used by the database module.
-// This is the same as the filename of the database
-// Returns 0 on success or nonzero otherwise
-
-EXTERN_C MIR_APP_DLL(int) Profile_GetNameA(size_t cbLen, char *pszDest);
-EXTERN_C MIR_APP_DLL(int) Profile_GetNameW(size_t cbLen, wchar_t *pwszDest);
-
-// Get the path of the base folder where Miranda will store all individual profiles
-// The returned path does NOT include a trailing backslash.
-// Essentially this is what has been set in mirandaboot.ini as ProfileDir.
-// For more options to retrieve profile paths check MS_UTILS_REPLACEVARS
-// Returns 0 on success or nonzero otherwise
-
-EXTERN_C MIR_APP_DLL(int) Profile_GetPathA(size_t cbLen, char *pszDest);
-EXTERN_C MIR_APP_DLL(int) Profile_GetPathW(size_t cbLen, wchar_t *pwszDest);
-
-// Sets the default profile name programmatically
-// Analog of Database/DefaultProfile in mirandaboot.ini
-EXTERN_C MIR_APP_DLL(void) Profile_SetDefault(const wchar_t *pwszPath);
-
-// Checks if a profile is opened
-EXTERN_C MIR_APP_DLL(bool) Profile_CheckOpened(const wchar_t *pwszProfileName);
-
-// Read an option from mirandaboot.ini
-EXTERN_C MIR_APP_DLL(int) Profile_GetSettingInt(const wchar_t *pwszSetting, int iDefault = 0);
-EXTERN_C MIR_APP_DLL(bool) Profile_GetSetting(const wchar_t *pwszSetting, wchar_t *pwszBuf, size_t cbLen, const wchar_t *pwszDefault = nullptr);
-
-template <size_t _Size>
-bool Profile_GetSetting(const wchar_t *pwszSetting, wchar_t(&pwszBuf)[_Size], const wchar_t *pwszDefault = nullptr)
-{
- return Profile_GetSetting(pwszSetting, pwszBuf, _Size, pwszDefault);
-}
-
-// Checks the specified profile like dbtool did.
-// Implemented in the dbchecker plugins, thus it might not exist
-// wParam = (WPARAM)(wchar_t*)ptszProfileName
-// lParam = (BOOL)bConversionMode
-
-#define MS_DB_CHECKPROFILE "DB/CheckProfile"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Contact services
-
-struct DBCONTACTGETSETTING
-{
- const char *szModule; // pointer to name of the module that wrote the setting to get
- const char *szSetting; // pointer to name of the setting to get
- DBVARIANT *pValue; // pointer to variant to receive the value
-};
-
-struct DBCONTACTWRITESETTING
-{
- const char *szModule; // pointer to name of the module that wrote the setting to get
- const char *szSetting; // pointer to name of the setting to get
- DBVARIANT value; // variant containing the value to set
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Event services
-
-// Registers the specified database event type, with module, id & description.
-// When someone needs to retrieve an event's text, a service named Module/GetEventText<id>
-// will be called. For example, for module named 'foo' and event id 2000 a service
-// foo/GetEventText2000 should be defined to process this request. That handler should
-// decode a blob and return the event text in the required format, its prototype is identical
-// to a call of DbEvent_GetText (see below)
-//
-// Returns -1 on error (e.g., event type already registred), 0 on success
-
-struct DBEVENTTYPEDESCR
-{
- LPSTR module; // event module name
- DWORD flags; // flags, combination of the DETF_*
- int eventType; // event id, unique for this module
- LPSTR descr; // event type description (i.e. "File Transfer")
- LPSTR textService; // service name for MS_DB_EVENT_GETTEXT (0.8+, default Module+'/GetEventText'+EvtID)
- LPSTR iconService; // service name for MS_DB_EVENT_GETICON (0.8+, default Module+'/GetEventIcon'+EvtID)
- HANDLE eventIcon; // icolib handle to eventicon (0.8+, default 'eventicon_'+Module+EvtID)
-};
-
-// constants for default event behaviour
-#define DETF_HISTORY 1 // show event in history
-#define DETF_MSGWINDOW 2 // show event in message window
-#define DETF_NONOTIFY 4 // block event notify (e.g. Popups)
-
-EXTERN_C MIR_APP_DLL(int) DbEvent_RegisterType(DBEVENTTYPEDESCR*);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Retrieves the previously registered database event type, by module & id.
-// Returns DBEVENTTYPEDESCR* or NULL, if an event isn't found.
-
-EXTERN_C MIR_APP_DLL(DBEVENTTYPEDESCR*) DbEvent_GetType(const char *szModule, int eventType);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// macro to extract MCONTACT from the auth blob
-
-__forceinline MCONTACT DbGetAuthEventContact(DBEVENTINFO *dbei)
-{
- return (MCONTACT)(*(DWORD*)&dbei->pBlob[sizeof(DWORD)]);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Retrieves the event's text
-// * dbei should be the valid database event read via db_event_get()
-// * codepage is any valid codepage, CP_ACP by default.
-//
-// Function returns a pointer to a string in the required format.
-// This string should be freed by a call of mir_free
-
-EXTERN_C MIR_APP_DLL(char*) DbEvent_GetTextA(DBEVENTINFO *dbei, int codepage);
-EXTERN_C MIR_APP_DLL(wchar_t*) DbEvent_GetTextW(DBEVENTINFO *dbei, int codepage);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Retrieves the event's icon
-// * use LR_SHARED in flags for shared HICON
-// dbei should be a valid database event read via db_event_get()
-//
-// Function returns HICON (use DestroyIcon to release resources if not LR_SHARED)
-//
-// A plugin can register the standard event icon in IcoLib named
-// 'eventicon_'+Module+EvtID, like eventicon_ICQ2001. Otherwise, to declare an icon
-// with the non-standard name, you can declare the special service, Module/GetEventIcon<id>,
-// which will retrieve the custom icon handle (HICON). This service function has the
-// same parameters MS_DB_EVENT_GETICON does.
-
-EXTERN_C MIR_APP_DLL(HICON) DbEvent_GetIcon(DBEVENTINFO *dbei, int flags);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Converts the event's string to wchar_t* depending on the event's format
-// returns wchar_t* - the converted string
-// Caller must free the result using mir_free
-
-EXTERN_C MIR_APP_DLL(wchar_t*) DbEvent_GetString(DBEVENTINFO *dbei, const char *str);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Database events
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DB/Event/Added event
-// Called when a new event has been added to the event chain for a contact
-// wParam = (MCONTACT)hContact
-// lParam = (LPARAM)(HANDLE)hDbEvent
-// hDbEvent is a valid handle to the event. hContact is a valid handle to the
-// contact to which hDbEvent refers.
-// Since events are sorted chronologically, you cannot guarantee that hDbEvent is
-// at any particular position in the chain.
-
-#define ME_DB_EVENT_ADDED "DB/Event/Added"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DB/Event/Edited event
-// Called when the existing event was changed
-// wParam = (MCONTACT)hContact
-// lParam = (LPARAM)(HANDLE)hDbEvent
-// hDbEvent is a valid handle to the event. hContact is a valid handle to the
-// contact to which hDbEvent refers.
-
-#define ME_DB_EVENT_EDITED "DB/Event/Edited"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DB/Event/FilterAdd (NOTE: Added during 0.3.3+ development!)
-// Called **before** a new event is made of a DBEVENTINFO structure, this
-// hook is not SAFE unless you know what you're doing with it, the arguments
-// are passed as-is (with errors, pointer problems, if any) from any arguments
-// passed to db_event_add.
-
-// The point of this hook is to stop any unwanted database events, to stop
-// an event being added, return 1, to allow the event to pass through return 0.
-// wParam = (MCONTACT)hContact
-// lParam = (LPARAM)&DBEVENTINFO
-//
-// Any changed made to the said DBEVENTINFO are also passed along to the database,
-// therefore it is possible to shape the data, however DO NOT DO THIS.
-
-#define ME_DB_EVENT_FILTER_ADD "DB/Event/FilterAdd"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DB/Event/Marked/Read event
-// Called when an event is marked read
-// wParam = (MCONTACT)hContact
-// lParam = (LPARAM)(HANDLE)hDbEvent
-// hDbEvent is a valid handle to the event.
-// hContact is a valid handle to the contact to which hDbEvent refers, and will remain valid.
-
-#define ME_DB_EVENT_MARKED_READ "DB/Event/Marked/Read"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DB/Event/Deleted event
-// Called when an event is about to be deleted from the event chain for a contact
-// wParam = (MCONTACT)hContact
-// lParam = (LPARAM)(HANDLE)hDbEvent
-// hDbEvent is a valid handle to the event which is about to be deleted, but it
-// won't be once your hook has returned.
-// hContact is a valid handle to the contact to which hDbEvent refers, and will
-// remain valid.
-// Returning nonzero from your hook will not stop the deletion, but it will, as
-// usual, stop other hooks from being called.
-
-#define ME_DB_EVENT_DELETED "DB/Event/Deleted"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DB/Contact/Added event
-// Called when a new contact has been added to the database
-// wParam = (MCONTACT)hContact
-// lParam = 0
-// hContact is a valid handle to the new contact.
-// Contacts are initially created without any settings, so if you hook this event
-// you will almost certainly also want to hook db/contact/settingchanged as well.
-
-#define ME_DB_CONTACT_ADDED "DB/Contact/Added"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DB/Contact/Deleted event
-// Called when an contact is about to be deleted
-// wParam = (MCONTACT)hContact
-// lParam = 0
-// hContact is a valid handle to the contact which is about to be deleted, but it
-// won't be once your hook has returned.
-// Returning nonzero from your hook will not stop the deletion, but it will, as
-// usual, stop other hooks from being called.
-// Deleting a contact invalidates all events in its chain.
-
-#define ME_DB_CONTACT_DELETED "DB/Contact/Deleted"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// DB/Contact/SettingChanged event
-// Called when a contact has had one of its settings changed
-// wParam = (MCONTACT)hContact
-// lParam = (LPARAM)(DBCONTACTWRITESETTING*)&dbcws
-// hContact is a valid handle to the contact that has changed.
-// This event will be triggered many times rapidly when a whole bunch of values are set.
-// Modules which hook this should be aware of this fact and quickly return if they
-// are not interested in the value that has been changed.
-// Careful not to get into infinite loops with this event.
-// The structure dbcws is the same one as is passed to the original service, so
-// don't change any of the members.
-
-#define ME_DB_CONTACT_SETTINGCHANGED "DB/Contact/SettingChanged"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Settings helper functions
-
-#ifndef DB_NOHELPERFUNCTIONS
-
-///////////////////////////////////////////////////////////////////////////////////////// inlined range tolerate versions */
-
-__inline BYTE DBGetContactSettingRangedByte(MCONTACT hContact, const char *szModule, const char *szSetting, BYTE errorValue, BYTE minValue, BYTE maxValue)
-{
- BYTE bVal = db_get_b(hContact, szModule, szSetting, errorValue);
- return (bVal < minValue || bVal > maxValue) ? errorValue : bVal;
-}
-
-__inline WORD DBGetContactSettingRangedWord(MCONTACT hContact, const char *szModule, const char *szSetting, WORD errorValue, WORD minValue, WORD maxValue)
-{
- WORD wVal = db_get_w(hContact, szModule, szSetting, errorValue);
- return (wVal < minValue || wVal > maxValue) ? errorValue : wVal;
-}
-
-__inline DWORD DBGetContactSettingRangedDword(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD errorValue, DWORD minValue, DWORD maxValue)
-{
- DWORD dwVal = db_get_dw(hContact, szModule, szSetting, errorValue);
- return (dwVal < minValue || dwVal > maxValue) ? errorValue : dwVal;
-}
-
-#endif
-
-namespace DB
-{
-
- /////////////////////////////////////////////////////////////////////////////////////////
- // Helper to free event contents automatically
-
- struct EventInfo : public DBEVENTINFO
- {
- __forceinline explicit EventInfo()
- {
- memset(this, 0, sizeof(*this));
- }
-
- __forceinline ~EventInfo()
- {
- mir_free(pBlob);
- }
- };
-
- /////////////////////////////////////////////////////////////////////////////////////////
- // Helper to process the auth req body
- // blob is: 0(DWORD), hContact(DWORD), nick(UTF8), firstName(UTF8), lastName(UTF8), email(UTF8), reason(UTF8)
-
- #pragma warning(disable : 4251)
-
- class MIR_APP_EXPORT AUTH_BLOB
- {
- MCONTACT m_hContact;
- DWORD m_dwUin;
- ptrA m_szNick, m_szFirstName, m_szLastName, m_szEmail, m_szReason;
- DWORD m_size;
-
- PBYTE makeBlob();
-
- public:
- explicit AUTH_BLOB(MCONTACT hContact, const char *nick, const char *fname, const char *lname, const char *id, const char *reason);
- explicit AUTH_BLOB(PBYTE blob);
- ~AUTH_BLOB();
-
- __forceinline operator char*() { return (char*)makeBlob(); }
- __forceinline operator BYTE*() { return makeBlob(); }
-
- __forceinline DWORD size() const { return m_size; }
-
- __forceinline MCONTACT get_contact() const { return m_hContact; }
- __forceinline const char* get_nick() const { return m_szNick; }
- __forceinline const char* get_firstName() const { return m_szFirstName; }
- __forceinline const char* get_lastName() const { return m_szLastName; }
- __forceinline const char* get_email() const { return m_szEmail; }
- __forceinline const char* get_reason() const { return m_szReason; }
-
- __forceinline DWORD get_uin() const { return m_dwUin; }
- __forceinline void set_uin(DWORD dwValue) { m_dwUin = dwValue; }
- };
-
- /////////////////////////////////////////////////////////////////////////////////////////
- // Event cursors
-
- class MIR_CORE_EXPORT EventCursor : public MZeroedObject
- {
- friend class EventIterator;
-
- protected:
- MCONTACT hContact;
-
- public:
- EventCursor(MCONTACT _1) :
- hContact(_1)
- { }
-
- virtual ~EventCursor();
- virtual MEVENT FetchNext() = 0;
-
- __forceinline MEVENT begin() {
- return FetchNext();
- }
-
- __forceinline MEVENT end() {
- return 0;
- }
- };
-
- class MIR_CORE_EXPORT ECPTR : public MNonCopyable
- {
- EventCursor *m_cursor;
- MEVENT m_prevFetched, m_currEvent;
-
- public:
- ECPTR(EventCursor *_1);
- ~ECPTR();
-
- void DeleteEvent();
- MEVENT FetchNext();
- };
-
- class EventIterator
- {
- EventCursor *cursor;
- MEVENT hCurr = 0;
-
- public:
- EventIterator(EventCursor *_1) :
- cursor(_1)
- {}
-
- EventIterator operator++() {
- hCurr = cursor->FetchNext();
- return *this;
- }
-
- bool operator!=(const EventIterator &p) {
- return hCurr != p.hCurr;
- }
-
- operator MEVENT() const {
- return hCurr;
- }
- };
-
- MIR_CORE_DLL(EventCursor*) Events(MCONTACT, MEVENT iStartEvent = 0);
- MIR_CORE_DLL(EventCursor*) EventsRev(MCONTACT, MEVENT iStartEvent = 0);
-};
-
-#endif // M_DATABASE_H__
+/////////////////////////////////////////////////////////////////////////////////////////
+// Miranda NG: the free IM client for Microsoft* Windows*
+//
+// Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+// Copyright (c) 2000-08 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 M_DATABASE_H__
+#define M_DATABASE_H__ 1
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// GENERALLY USEFUL STUFF
+
+#if !defined(M_SYSTEM_H__)
+ #include "m_system.h"
+#endif
+
+#if !defined(M_UTILS_H__)
+ #include "m_utils.h"
+#endif
+
+#ifdef _MSC_VER
+ #pragma warning(disable:4201 4204)
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// database functions
+
+// Switches safety settings on or off
+// newSetting is TRUE initially.
+// Miranda's database is normally protected against corruption by agressively
+// flushing data to the disk on writes. If you're doing a lot of writes (eg in
+// an import plugin) it can sometimes be desirable to switch this feature off to
+// speed up the process. If you do switch it off, you must remember that crashes
+// are far more likely to be catastrophic, so switch it back on at the earliest
+// possible opportunity.
+// Note that if you're doing a lot of setting writes, the flush is already delayed
+// so you need not use this service for that purpose.
+
+EXTERN_C MIR_CORE_DLL(void) db_set_safety_mode(BOOL bNewMode);
+
+// Gets the number of contacts in the database, which does not count the user
+// Returns the number of contacts. They can be retrieved using contact/findfirst and contact/findnext
+
+EXTERN_C MIR_CORE_DLL(int) db_get_contact_count(void);
+
+// Removes all settings for the specified module.
+// hContact is 0 for global settings or matches the concrete contact
+
+EXTERN_C MIR_CORE_DLL(int) db_delete_module(MCONTACT hContact, const char *szModuleName);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// contact functions
+
+// Adds a new contact to the database. New contacts initially have no settings
+// whatsoever, they must all be added with db/contacts/writesetting.
+// Returns a handle to the newly created contact on success, or NULL otherwise.
+// Triggers a db/contact/added event just before it returns.
+
+EXTERN_C MIR_CORE_DLL(MCONTACT) db_add_contact(void);
+
+// Deletes the contact hContact from the database and all events and settings associated with it.
+// Returns 0 on success or nonzero if hContact was invalid
+// Please don't try to delete the user contact (hContact = NULL)
+// Triggers a db/contact/deleted event just *before* it removes anything
+// Because all events are deleted, lots of people may end up with invalid event
+// handles from this operation, which they should be prepared for.
+
+EXTERN_C MIR_CORE_DLL(int) db_delete_contact(MCONTACT hContact);
+
+// Checks if a given value is a valid contact handle, note that due
+// to the nature of multiple threading, a valid contact can still become
+// invalid after a call to this service.
+// Returns 1 if the contact is a contact, or 0 if the contact is not valid.
+
+EXTERN_C MIR_CORE_DLL(int) db_is_contact(MCONTACT hContact);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// enumerators
+
+// Enumerates the names of all modules that have stored or requested information from the database.
+// Returns the value returned by the last call to dbmep
+// This service is only really useful for debugging, in conjunction with db/contact/enumsettings
+// dbmep should return 0 to continue enumeration, or nonzero to stop.
+//
+// Modules names will be enumerated in no particular order
+// Writing to the database while module names are being enumerated will cause
+// unpredictable results in the enumeration, but the write will work.
+// szModuleName is only guaranteed to be valid for the duration of the callback.
+// If you want to keep it for longer you must allocation your own storage.
+
+typedef int(*DBMODULEENUMPROC)(const char *szModuleName, void *param);
+
+EXTERN_C MIR_CORE_DLL(int) db_enum_modules(DBMODULEENUMPROC dbmep, void *param = nullptr);
+
+// Lists all resident settings
+
+EXTERN_C MIR_CORE_DLL(int) db_enum_residents(DBMODULEENUMPROC pFunc, void *param = nullptr);
+
+// Lists all the settings a specific modules has stored in the database for a specific contact.
+// Returns the return value of the last call to pfnEnumProc, or -1 if there are
+// no settings for that module/contact pair
+// Writing to or deleting from the database while enumerating will have
+// unpredictable results for the enumeration, but the write will succeed.
+// Use db/modules/enum to get a complete list of module names
+// szSetting is only guaranteed to be valid for the duration of the callback. If
+// you want to keep it for longer you must allocation your own storage.
+
+typedef int (*DBSETTINGENUMPROC)(const char *szSetting, void *param);
+
+EXTERN_C MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param = nullptr);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DBVARIANT: used by db/contact/getsetting and db/contact/writesetting
+
+#define DBVT_DELETED 0 // this setting just got deleted, no other values are valid
+#define DBVT_BYTE 1 // bVal and cVal are valid
+#define DBVT_WORD 2 // wVal and sVal are valid
+#define DBVT_DWORD 4 // dVal and lVal are valid
+#define DBVT_ASCIIZ 255 // pszVal is valid
+#define DBVT_BLOB 254 // cpbVal and pbVal are valid
+#define DBVT_UTF8 253 // pszVal is valid
+#define DBVT_WCHAR 252 // pwszVal is valid
+#define DBVT_ENCRYPTED 250 // blob of encrypted bytesw
+
+
+#define DBVTF_VARIABLELENGTH 0x80
+
+struct DBVARIANT
+{
+ BYTE type;
+ union {
+ BYTE bVal; char cVal;
+ WORD wVal; short sVal;
+ DWORD dVal; long lVal;
+ struct {
+ union {
+ char *pszVal;
+ wchar_t *pwszVal;
+ };
+ WORD cchVal; //only used for db/contact/getsettingstatic
+ };
+ struct {
+ WORD cpbVal;
+ BYTE *pbVal;
+ };
+ };
+};
+
+#define DBEF_TEMPORARY 0x0001 // disable notifications about temporary database events
+#define DBEF_SENT 0x0002 // this event was sent by the user. If not set this event was received.
+#define DBEF_READ 0x0004 // event has been read by the user. It does not need to be processed any more except for history.
+#define DBEF_RTL 0x0008 // event contains the right-to-left aligned text
+#define DBEF_UTF 0x0010 // event contains a text in utf-8
+#define DBEF_ENCRYPTED 0x0020 // event is encrypted (never reported outside a driver)
+#define DBEF_HAS_ID 0x0040 // event has unique server id
+
+struct DBEVENTINFO
+{
+ const char *szModule; // pointer to name of the module that 'owns' this event
+ DWORD timestamp; // seconds since 00:00, 01/01/1970. Gives us times until 2106
+ // unless you use the standard C library which is
+ // signed and can only do until 2038. In GMT.
+ DWORD flags; // combination of DBEF_* flags
+ WORD eventType; // module-defined event type field
+ int cbBlob; // size of pBlob in bytes
+ uint8_t *pBlob; // pointer to buffer containing module-defined event data
+ const char *szId; // server id
+
+ bool __forceinline markedRead() const {
+ return (flags & (DBEF_SENT | DBEF_READ)) != 0;
+ }
+
+ wchar_t* getString(const char *str) const {
+ return (flags & DBEF_UTF) ? mir_utf8decodeW(str) : mir_a2u(str);
+ }
+
+ bool __forceinline operator==(const DBEVENTINFO &e) {
+ return (timestamp == e.timestamp && eventType == e.eventType && cbBlob == e.cbBlob && (flags & DBEF_SENT) == (e.flags & DBEF_SENT));
+ }
+};
+
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_free(DBVARIANT *dbv);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Database contacts
+
+// Gets the handle of the first contact in the database. This handle can be used
+// with loads of functions. It does not need to be closed.
+// You can specify szProto to find only its contacts
+// Returns a handle to the first contact in the db on success, or NULL if there
+// are no contacts in the db.
+
+EXTERN_C MIR_CORE_DLL(MCONTACT) db_find_first(const char *szProto = nullptr);
+
+// Gets the handle of the next contact after hContact in the database. This handle
+// can be used with loads of functions. It does not need to be closed.
+// You can specify szProto to find only its contacts
+// Returns a handle to the contact after hContact in the db on success or NULL if
+// hContact was the last contact in the db or hContact was invalid.
+
+EXTERN_C MIR_CORE_DLL(MCONTACT) db_find_next(MCONTACT hContact, const char *szProto = nullptr);
+
+class Contacts
+{
+ const char *m_szModule;
+
+public:
+ Contacts(const char *m = nullptr) :
+ m_szModule(m)
+ {}
+
+ class iterator
+ {
+ MCONTACT hContact;
+ const char *m_szModule;
+
+ public:
+ __inline iterator(const char *_m, MCONTACT _h) :
+ hContact(_h),
+ m_szModule(_m)
+ {}
+
+ __inline iterator operator++() { hContact = ::db_find_next(hContact, m_szModule); return *this; }
+ __inline bool operator!=(const iterator &p) { return hContact != p.hContact; }
+ __inline operator const MCONTACT*() const { return &hContact; }
+ };
+
+ __inline iterator begin() const { return iterator(m_szModule, ::db_find_first(m_szModule)); }
+ __inline iterator end() const { return iterator(m_szModule, 0); }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Database events
+
+// Adds a new event to a contact's event list
+// Returns a handle to the newly added event, or NULL on failure
+// Triggers a db/event/added event just before it returns.
+// Events are sorted chronologically as they are entered, so you cannot guarantee
+// that the new hEvent is the last event in the chain, however if a new event is
+// added that has a timestamp less than 90 seconds *before* the event that should
+// be after it, it will be added afterwards, to allow for protocols that only
+// store times to the nearest minute, and slight delays in transports.
+// There are a few predefined eventTypes below for easier compatibility, but
+// modules are free to define their own, beginning at 2000
+// DBEVENTINFO.timestamp is in GMT, as returned by time(). There are services
+// db/time/x below with useful stuff for dealing with it.
+
+#define EVENTTYPE_MESSAGE 0
+#define EVENTTYPE_CONTACTS 2 //v0.1.2.2+
+#define EVENTTYPE_ADDED 1000 //v0.1.1.0+: these used to be module-
+#define EVENTTYPE_AUTHREQUEST 1001 //specific codes, hence the module-
+#define EVENTTYPE_FILE 1002 //specific limit has been raised to 2000
+
+EXTERN_C MIR_CORE_DLL(MEVENT) db_event_add(MCONTACT hContact, const DBEVENTINFO *dbei);
+
+// Gets the number of events in the chain belonging to a contact in the database.
+// Returns the number of events in the chain owned by hContact or -1 if hContact
+// is invalid. They can be retrieved using the db_event_first/last() services.
+
+EXTERN_C MIR_CORE_DLL(int) db_event_count(MCONTACT hContact);
+
+// Removes a single event from the database
+// hDbEvent should have been returned by db_event_add/first/last/next/prev()
+// Returns 0 on success, or nonzero if hDbEvent was invalid
+// Triggers a db/event/deleted event just *before* the event is deleted
+
+EXTERN_C MIR_CORE_DLL(int) db_event_delete(MEVENT hDbEvent);
+
+// Edits an event in the database
+// Returns 0 on success, or nonzero on error
+
+EXTERN_C MIR_CORE_DLL(int) db_event_edit(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO *dbei);
+
+// Retrieves a handle to the first event in the chain for hContact
+// Returns the handle, or NULL if hContact is invalid or has no events
+// Events in a chain are sorted chronologically automatically
+
+EXTERN_C MIR_CORE_DLL(MEVENT) db_event_first(MCONTACT hContact);
+
+// Retrieves a handle to the first unread event in the chain for hContact
+// Returns the handle, or NULL if hContact is invalid or all its events have been read
+//
+// Events in a chain are sorted chronologically automatically, but this does not
+// necessarily mean that all events after the first unread are unread too. They
+// should be checked individually with db_event_next() and db_event_get()
+// This service is designed for startup, reloading all the events that remained
+// unread from last time
+
+EXTERN_C MIR_CORE_DLL(MEVENT) db_event_firstUnread(MCONTACT hContact);
+
+// Retrieves all the information stored in hDbEvent
+// hDbEvent should have been returned by db_event_add/first/last/next/prev()
+// Returns 0 on success or nonzero if hDbEvent is invalid
+// Don't forget to set dbe.cbSize, dbe.pBlob and dbe.cbBlob before calling this function
+// The correct value dbe.cbBlob can be got using db_event_getBlobSize
+// If successful, all the fields of dbe are filled. dbe.cbBlob is set to the
+// actual number of bytes retrieved and put in dbe.pBlob
+// If dbe.cbBlob is too small, dbe.pBlob is filled up to the size of dbe.cbBlob
+// and then dbe.cbBlob is set to the required size of data to go in dbe.pBlob
+// On return, dbe.szModule is a pointer to the database module's own internal list
+// of modules. Look but don't touch.
+
+EXTERN_C MIR_CORE_DLL(int) db_event_get(MEVENT hDbEvent, DBEVENTINFO *dbei);
+
+// Retrieves the space in bytes required to store the blob in hDbEvent
+// hDbEvent should have been returned by db_event_add/first/last/next/prev()
+// Returns the space required in bytes, or -1 if hDbEvent is invalid
+
+EXTERN_C MIR_CORE_DLL(int) db_event_getBlobSize(MEVENT hDbEvent);
+
+// Retrieves a handle to the contact that owns hDbEvent.
+// hDbEvent should have been returned by db_event_add/first/last/next/prev()
+// NULL is a valid return value, meaning, as usual, the user.
+// Returns INVALID_CONTACT_ID if hDbEvent is invalid, or the handle to the contact on success
+
+EXTERN_C MIR_CORE_DLL(MCONTACT) db_event_getContact(MEVENT hDbEvent);
+
+// Retrieves a handle to the last event in the chain for hContact
+// Returns the handle, or NULL if hContact is invalid or has no events
+// Events in a chain are sorted chronologically automatically
+
+EXTERN_C MIR_CORE_DLL(MEVENT) db_event_last(MCONTACT hContact);
+
+// Changes the flags for an event to mark it as read.
+// hDbEvent should have been returned by db_event_add/first/last/next/prev()
+// Returns the entire flag DWORD for the event after the change, or -1 if hDbEvent is invalid.
+// This is the one database write operation that does not trigger an event.
+// Modules should not save flags states for any length of time.
+
+EXTERN_C MIR_CORE_DLL(int) db_event_markRead(MCONTACT hContact, MEVENT hDbEvent);
+
+// Retrieves a handle to the next event in a chain after hDbEvent
+// Returns the handle, or NULL if hDbEvent is invalid or is the last event
+// Events in a chain are sorted chronologically automatically
+
+EXTERN_C MIR_CORE_DLL(MEVENT) db_event_next(MCONTACT hContact, MEVENT hDbEvent);
+
+// Retrieves a handle to the previous event in a chain before hDbEvent
+// Returns the handle, or NULL if hDbEvent is invalid or is the first event
+// Events in a chain are sorted chronologically automatically
+
+EXTERN_C MIR_CORE_DLL(MEVENT) db_event_prev(MCONTACT hContact, MEVENT hDbEvent);
+
+// Retrieves a handle to the event identified by its module and unique identifier
+
+EXTERN_C MIR_CORE_DLL(MEVENT) db_event_getById(const char *szModule, const char *szId);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Database settings
+
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_get(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv);
+
+EXTERN_C MIR_CORE_DLL(int) db_get_b(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue = 0);
+EXTERN_C MIR_CORE_DLL(int) db_get_w(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue = 0);
+EXTERN_C MIR_CORE_DLL(DWORD) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD errorValue = 0);
+
+EXTERN_C MIR_CORE_DLL(char*) db_get_sa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue = nullptr);
+EXTERN_C MIR_CORE_DLL(char*) db_get_utfa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue = nullptr);
+EXTERN_C MIR_CORE_DLL(wchar_t*) db_get_wsa(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue = nullptr);
+
+MIR_CORE_DLL(CMStringA) db_get_sm(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue = nullptr);
+MIR_CORE_DLL(CMStringW) db_get_wsm(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue = nullptr);
+
+EXTERN_C MIR_CORE_DLL(int) db_get_static(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest);
+EXTERN_C MIR_CORE_DLL(int) db_get_static_utf(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest);
+EXTERN_C MIR_CORE_DLL(int) db_get_wstatic(MCONTACT hContact, const char *szModule, const char *szSetting, wchar_t *pDest, int cbDest);
+
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_set(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv);
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_b(MCONTACT hContact, const char *szModule, const char *szSetting, BYTE val);
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, WORD val);
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD val);
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_s(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val);
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_ws(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *val);
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_utf(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val);
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_blob(MCONTACT hContact, const char *szModule, const char *szSetting, void *val, unsigned len);
+
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_unset(MCONTACT hContact, const char *szModule, const char *szSetting);
+
+EXTERN_C MIR_CORE_DLL(BOOL) db_set_resident(const char *szModule, const char *szService, BOOL bEnable = true);
+
+EXTERN_C MIR_CORE_DLL(INT_PTR) db_get_s(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv, const int nType = DBVT_ASCIIZ);
+#define db_get_ws(a,b,c,d) db_get_s(a,b,c,d,DBVT_WCHAR)
+#define db_get_utf(a,b,c,d) db_get_s(a,b,c,d,DBVT_UTF8)
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Profile services
+
+// Gets the name of the profile currently being used by the database module.
+// This is the same as the filename of the database
+// Returns 0 on success or nonzero otherwise
+
+EXTERN_C MIR_APP_DLL(int) Profile_GetNameA(size_t cbLen, char *pszDest);
+EXTERN_C MIR_APP_DLL(int) Profile_GetNameW(size_t cbLen, wchar_t *pwszDest);
+
+// Get the path of the base folder where Miranda will store all individual profiles
+// The returned path does NOT include a trailing backslash.
+// Essentially this is what has been set in mirandaboot.ini as ProfileDir.
+// For more options to retrieve profile paths check MS_UTILS_REPLACEVARS
+// Returns 0 on success or nonzero otherwise
+
+EXTERN_C MIR_APP_DLL(int) Profile_GetPathA(size_t cbLen, char *pszDest);
+EXTERN_C MIR_APP_DLL(int) Profile_GetPathW(size_t cbLen, wchar_t *pwszDest);
+
+// Sets the default profile name programmatically
+// Analog of Database/DefaultProfile in mirandaboot.ini
+EXTERN_C MIR_APP_DLL(void) Profile_SetDefault(const wchar_t *pwszPath);
+
+// Checks if a profile is opened
+EXTERN_C MIR_APP_DLL(bool) Profile_CheckOpened(const wchar_t *pwszProfileName);
+
+// Read an option from mirandaboot.ini
+EXTERN_C MIR_APP_DLL(int) Profile_GetSettingInt(const wchar_t *pwszSetting, int iDefault = 0);
+EXTERN_C MIR_APP_DLL(bool) Profile_GetSetting(const wchar_t *pwszSetting, wchar_t *pwszBuf, size_t cbLen, const wchar_t *pwszDefault = nullptr);
+
+template <size_t _Size>
+bool Profile_GetSetting(const wchar_t *pwszSetting, wchar_t(&pwszBuf)[_Size], const wchar_t *pwszDefault = nullptr)
+{
+ return Profile_GetSetting(pwszSetting, pwszBuf, _Size, pwszDefault);
+}
+
+// Checks the specified profile like dbtool did.
+// Implemented in the dbchecker plugins, thus it might not exist
+// wParam = (WPARAM)(wchar_t*)ptszProfileName
+// lParam = (BOOL)bConversionMode
+
+#define MS_DB_CHECKPROFILE "DB/CheckProfile"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Contact services
+
+struct DBCONTACTGETSETTING
+{
+ const char *szModule; // pointer to name of the module that wrote the setting to get
+ const char *szSetting; // pointer to name of the setting to get
+ DBVARIANT *pValue; // pointer to variant to receive the value
+};
+
+struct DBCONTACTWRITESETTING
+{
+ const char *szModule; // pointer to name of the module that wrote the setting to get
+ const char *szSetting; // pointer to name of the setting to get
+ DBVARIANT value; // variant containing the value to set
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Event services
+
+// Registers the specified database event type, with module, id & description.
+// When someone needs to retrieve an event's text, a service named Module/GetEventText<id>
+// will be called. For example, for module named 'foo' and event id 2000 a service
+// foo/GetEventText2000 should be defined to process this request. That handler should
+// decode a blob and return the event text in the required format, its prototype is identical
+// to a call of DbEvent_GetText (see below)
+//
+// Returns -1 on error (e.g., event type already registred), 0 on success
+
+struct DBEVENTTYPEDESCR
+{
+ LPSTR module; // event module name
+ DWORD flags; // flags, combination of the DETF_*
+ int eventType; // event id, unique for this module
+ LPSTR descr; // event type description (i.e. "File Transfer")
+ LPSTR textService; // service name for MS_DB_EVENT_GETTEXT (0.8+, default Module+'/GetEventText'+EvtID)
+ LPSTR iconService; // service name for MS_DB_EVENT_GETICON (0.8+, default Module+'/GetEventIcon'+EvtID)
+ HANDLE eventIcon; // icolib handle to eventicon (0.8+, default 'eventicon_'+Module+EvtID)
+};
+
+// constants for default event behaviour
+#define DETF_HISTORY 1 // show event in history
+#define DETF_MSGWINDOW 2 // show event in message window
+#define DETF_NONOTIFY 4 // block event notify (e.g. Popups)
+
+EXTERN_C MIR_APP_DLL(int) DbEvent_RegisterType(DBEVENTTYPEDESCR*);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Retrieves the previously registered database event type, by module & id.
+// Returns DBEVENTTYPEDESCR* or NULL, if an event isn't found.
+
+EXTERN_C MIR_APP_DLL(DBEVENTTYPEDESCR*) DbEvent_GetType(const char *szModule, int eventType);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// macro to extract MCONTACT from the auth blob
+
+__forceinline MCONTACT DbGetAuthEventContact(DBEVENTINFO *dbei)
+{
+ return (MCONTACT)(*(DWORD*)&dbei->pBlob[sizeof(DWORD)]);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Retrieves the event's text
+// * dbei should be the valid database event read via db_event_get()
+// * codepage is any valid codepage, CP_ACP by default.
+//
+// Function returns a pointer to a string in the required format.
+// This string should be freed by a call of mir_free
+
+EXTERN_C MIR_APP_DLL(char*) DbEvent_GetTextA(DBEVENTINFO *dbei, int codepage);
+EXTERN_C MIR_APP_DLL(wchar_t*) DbEvent_GetTextW(DBEVENTINFO *dbei, int codepage);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Retrieves the event's icon
+// * use LR_SHARED in flags for shared HICON
+// dbei should be a valid database event read via db_event_get()
+//
+// Function returns HICON (use DestroyIcon to release resources if not LR_SHARED)
+//
+// A plugin can register the standard event icon in IcoLib named
+// 'eventicon_'+Module+EvtID, like eventicon_ICQ2001. Otherwise, to declare an icon
+// with the non-standard name, you can declare the special service, Module/GetEventIcon<id>,
+// which will retrieve the custom icon handle (HICON). This service function has the
+// same parameters MS_DB_EVENT_GETICON does.
+
+EXTERN_C MIR_APP_DLL(HICON) DbEvent_GetIcon(DBEVENTINFO *dbei, int flags);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Converts the event's string to wchar_t* depending on the event's format
+// returns wchar_t* - the converted string
+// Caller must free the result using mir_free
+
+EXTERN_C MIR_APP_DLL(wchar_t*) DbEvent_GetString(DBEVENTINFO *dbei, const char *str);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Database events
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DB/Event/Added event
+// Called when a new event has been added to the event chain for a contact
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(HANDLE)hDbEvent
+// hDbEvent is a valid handle to the event. hContact is a valid handle to the
+// contact to which hDbEvent refers.
+// Since events are sorted chronologically, you cannot guarantee that hDbEvent is
+// at any particular position in the chain.
+
+#define ME_DB_EVENT_ADDED "DB/Event/Added"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DB/Event/Edited event
+// Called when the existing event was changed
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(HANDLE)hDbEvent
+// hDbEvent is a valid handle to the event. hContact is a valid handle to the
+// contact to which hDbEvent refers.
+
+#define ME_DB_EVENT_EDITED "DB/Event/Edited"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DB/Event/FilterAdd (NOTE: Added during 0.3.3+ development!)
+// Called **before** a new event is made of a DBEVENTINFO structure, this
+// hook is not SAFE unless you know what you're doing with it, the arguments
+// are passed as-is (with errors, pointer problems, if any) from any arguments
+// passed to db_event_add.
+
+// The point of this hook is to stop any unwanted database events, to stop
+// an event being added, return 1, to allow the event to pass through return 0.
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)&DBEVENTINFO
+//
+// Any changed made to the said DBEVENTINFO are also passed along to the database,
+// therefore it is possible to shape the data, however DO NOT DO THIS.
+
+#define ME_DB_EVENT_FILTER_ADD "DB/Event/FilterAdd"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DB/Event/Marked/Read event
+// Called when an event is marked read
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(HANDLE)hDbEvent
+// hDbEvent is a valid handle to the event.
+// hContact is a valid handle to the contact to which hDbEvent refers, and will remain valid.
+
+#define ME_DB_EVENT_MARKED_READ "DB/Event/Marked/Read"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DB/Event/Deleted event
+// Called when an event is about to be deleted from the event chain for a contact
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(HANDLE)hDbEvent
+// hDbEvent is a valid handle to the event which is about to be deleted, but it
+// won't be once your hook has returned.
+// hContact is a valid handle to the contact to which hDbEvent refers, and will
+// remain valid.
+// Returning nonzero from your hook will not stop the deletion, but it will, as
+// usual, stop other hooks from being called.
+
+#define ME_DB_EVENT_DELETED "DB/Event/Deleted"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DB/Contact/Added event
+// Called when a new contact has been added to the database
+// wParam = (MCONTACT)hContact
+// lParam = 0
+// hContact is a valid handle to the new contact.
+// Contacts are initially created without any settings, so if you hook this event
+// you will almost certainly also want to hook db/contact/settingchanged as well.
+
+#define ME_DB_CONTACT_ADDED "DB/Contact/Added"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DB/Contact/Deleted event
+// Called when an contact is about to be deleted
+// wParam = (MCONTACT)hContact
+// lParam = 0
+// hContact is a valid handle to the contact which is about to be deleted, but it
+// won't be once your hook has returned.
+// Returning nonzero from your hook will not stop the deletion, but it will, as
+// usual, stop other hooks from being called.
+// Deleting a contact invalidates all events in its chain.
+
+#define ME_DB_CONTACT_DELETED "DB/Contact/Deleted"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// DB/Contact/SettingChanged event
+// Called when a contact has had one of its settings changed
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(DBCONTACTWRITESETTING*)&dbcws
+// hContact is a valid handle to the contact that has changed.
+// This event will be triggered many times rapidly when a whole bunch of values are set.
+// Modules which hook this should be aware of this fact and quickly return if they
+// are not interested in the value that has been changed.
+// Careful not to get into infinite loops with this event.
+// The structure dbcws is the same one as is passed to the original service, so
+// don't change any of the members.
+
+#define ME_DB_CONTACT_SETTINGCHANGED "DB/Contact/SettingChanged"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Settings helper functions
+
+#ifndef DB_NOHELPERFUNCTIONS
+
+///////////////////////////////////////////////////////////////////////////////////////// inlined range tolerate versions */
+
+__inline BYTE DBGetContactSettingRangedByte(MCONTACT hContact, const char *szModule, const char *szSetting, BYTE errorValue, BYTE minValue, BYTE maxValue)
+{
+ BYTE bVal = db_get_b(hContact, szModule, szSetting, errorValue);
+ return (bVal < minValue || bVal > maxValue) ? errorValue : bVal;
+}
+
+__inline WORD DBGetContactSettingRangedWord(MCONTACT hContact, const char *szModule, const char *szSetting, WORD errorValue, WORD minValue, WORD maxValue)
+{
+ WORD wVal = db_get_w(hContact, szModule, szSetting, errorValue);
+ return (wVal < minValue || wVal > maxValue) ? errorValue : wVal;
+}
+
+__inline DWORD DBGetContactSettingRangedDword(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD errorValue, DWORD minValue, DWORD maxValue)
+{
+ DWORD dwVal = db_get_dw(hContact, szModule, szSetting, errorValue);
+ return (dwVal < minValue || dwVal > maxValue) ? errorValue : dwVal;
+}
+
+#endif
+
+namespace DB
+{
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Helper to free event contents automatically
+
+ struct EventInfo : public DBEVENTINFO
+ {
+ __forceinline explicit EventInfo()
+ {
+ memset(this, 0, sizeof(*this));
+ }
+
+ __forceinline ~EventInfo()
+ {
+ mir_free(pBlob);
+ }
+ };
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Helper to process the auth req body
+ // blob is: 0(DWORD), hContact(DWORD), nick(UTF8), firstName(UTF8), lastName(UTF8), email(UTF8), reason(UTF8)
+
+ #pragma warning(disable : 4251)
+
+ class MIR_APP_EXPORT AUTH_BLOB
+ {
+ MCONTACT m_hContact;
+ DWORD m_dwUin;
+ ptrA m_szNick, m_szFirstName, m_szLastName, m_szEmail, m_szReason;
+ DWORD m_size;
+
+ uint8_t* makeBlob();
+
+ public:
+ explicit AUTH_BLOB(MCONTACT hContact, const char *nick, const char *fname, const char *lname, const char *id, const char *reason);
+ explicit AUTH_BLOB(uint8_t *blob);
+ ~AUTH_BLOB();
+
+ __forceinline operator char*() { return (char*)makeBlob(); }
+ __forceinline operator BYTE*() { return makeBlob(); }
+
+ __forceinline DWORD size() const { return m_size; }
+
+ __forceinline MCONTACT get_contact() const { return m_hContact; }
+ __forceinline const char* get_nick() const { return m_szNick; }
+ __forceinline const char* get_firstName() const { return m_szFirstName; }
+ __forceinline const char* get_lastName() const { return m_szLastName; }
+ __forceinline const char* get_email() const { return m_szEmail; }
+ __forceinline const char* get_reason() const { return m_szReason; }
+
+ __forceinline DWORD get_uin() const { return m_dwUin; }
+ __forceinline void set_uin(DWORD dwValue) { m_dwUin = dwValue; }
+ };
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Event cursors
+
+ class MIR_CORE_EXPORT EventCursor : public MZeroedObject
+ {
+ friend class EventIterator;
+
+ protected:
+ MCONTACT hContact;
+
+ public:
+ EventCursor(MCONTACT _1) :
+ hContact(_1)
+ { }
+
+ virtual ~EventCursor();
+ virtual MEVENT FetchNext() = 0;
+
+ __forceinline MEVENT begin() {
+ return FetchNext();
+ }
+
+ __forceinline MEVENT end() {
+ return 0;
+ }
+ };
+
+ class MIR_CORE_EXPORT ECPTR : public MNonCopyable
+ {
+ EventCursor *m_cursor;
+ MEVENT m_prevFetched, m_currEvent;
+
+ public:
+ ECPTR(EventCursor *_1);
+ ~ECPTR();
+
+ void DeleteEvent();
+ MEVENT FetchNext();
+ };
+
+ class EventIterator
+ {
+ EventCursor *cursor;
+ MEVENT hCurr = 0;
+
+ public:
+ EventIterator(EventCursor *_1) :
+ cursor(_1)
+ {}
+
+ EventIterator operator++() {
+ hCurr = cursor->FetchNext();
+ return *this;
+ }
+
+ bool operator!=(const EventIterator &p) {
+ return hCurr != p.hCurr;
+ }
+
+ operator MEVENT() const {
+ return hCurr;
+ }
+ };
+
+ MIR_CORE_DLL(EventCursor*) Events(MCONTACT, MEVENT iStartEvent = 0);
+ MIR_CORE_DLL(EventCursor*) EventsRev(MCONTACT, MEVENT iStartEvent = 0);
+};
+
+#endif // M_DATABASE_H__
diff --git a/include/m_db_int.h b/include/m_db_int.h
index aadd36998d..3a96f6906e 100644
--- a/include/m_db_int.h
+++ b/include/m_db_int.h
@@ -1,405 +1,405 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-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 M_DB_INT_H__
-#define M_DB_INT_H__ 1
-
-#ifndef M_CORE_H__
- #include <m_core.h>
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// basic database checker interface
-
-#define STATUS_MESSAGE 0
-#define STATUS_WARNING 1
-#define STATUS_ERROR 2
-#define STATUS_FATAL 3
-#define STATUS_SUCCESS 4
-
-struct DATABASELINK;
-
-struct DBCHeckCallback
-{
- DWORD spaceProcessed, spaceUsed;
-
- void (*pfnAddLogMessage)(int type, const wchar_t *ptszFormat, ...);
-};
-
-interface MIDatabaseChecker
-{
- STDMETHOD_(BOOL, Start)(DBCHeckCallback *callback) PURE;
- STDMETHOD_(BOOL, CheckDb)(int phase) PURE;
- STDMETHOD_(VOID, Destroy)() PURE;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// basic database interface
-
-struct DBCachedGlobalValue
-{
- char *name;
- DBVARIANT value;
-};
-
-struct DBCachedContactValue
-{
- char *name;
- DBVARIANT value;
- DBCachedContactValue *next;
-};
-
-struct DBCachedContactBase
-{
- MCONTACT contactID;
- char *szProto;
- DBCachedContactValue *first, *last;
-
- // metacontacts
- int nSubs; // == -1 -> not a metacontact
- MCONTACT *pSubs;
- MCONTACT parentID; // == 0 -> not a subcontact
- int nDefault; // default sub number
-
- __forceinline bool IsMeta() const { return nSubs != -1; }
- __forceinline bool IsSub() const { return parentID != 0; }
-};
-
-#ifndef OWN_CACHED_CONTACT
-struct DBCachedContact : public DBCachedContactBase {};
-#else
-struct DBCachedContact;
-#endif
-
-interface MIDatabaseCache : public MZeroedObject
-{
- STDMETHOD_(DBCachedContact*, AddContactToCache)(MCONTACT contactID) PURE;
- STDMETHOD_(DBCachedContact*, GetCachedContact)(MCONTACT contactID) PURE;
- STDMETHOD_(DBCachedContact*, GetFirstContact)(void) PURE;
- STDMETHOD_(DBCachedContact*, GetNextContact)(MCONTACT contactID) PURE;
- STDMETHOD_(void, FreeCachedContact)(MCONTACT contactID) PURE;
-
- STDMETHOD_(char*, InsertCachedSetting)(const char *szName, size_t) PURE;
- STDMETHOD_(char*, GetCachedSetting)(const char *szModuleName, const char *szSettingName, size_t, size_t) PURE;
- STDMETHOD_(void, SetCachedVariant)(DBVARIANT *s, DBVARIANT *d) PURE;
- STDMETHOD_(DBVARIANT*, GetCachedValuePtr)(MCONTACT contactID, char *szSetting, int bAllocate) PURE;
-};
-
-interface MIR_APP_EXPORT MIDatabase
-{
- STDMETHOD_(BOOL, IsRelational)(void) PURE;
- STDMETHOD_(void, SetCacheSafetyMode)(BOOL) PURE;
-
- STDMETHOD_(LONG, GetContactCount)(void) PURE;
- STDMETHOD_(MCONTACT, FindFirstContact)(const char *szProto = nullptr) PURE;
- STDMETHOD_(MCONTACT, FindNextContact)(MCONTACT contactID, const char *szProto = nullptr) PURE;
-
- STDMETHOD_(LONG, DeleteContact)(MCONTACT contactID) PURE;
- STDMETHOD_(MCONTACT, AddContact)(void) PURE;
- STDMETHOD_(BOOL, IsDbContact)(MCONTACT contactID) PURE;
- STDMETHOD_(LONG, GetContactSize)(void) PURE;
-
- STDMETHOD_(LONG, GetEventCount)(MCONTACT contactID) PURE;
- STDMETHOD_(MEVENT, AddEvent)(MCONTACT contactID, const DBEVENTINFO *dbe) PURE;
- STDMETHOD_(BOOL, DeleteEvent)(MEVENT hDbEvent) PURE;
- STDMETHOD_(BOOL, EditEvent)(MCONTACT contactID, MEVENT hDbEvent, const DBEVENTINFO *dbe) PURE;
- STDMETHOD_(LONG, GetBlobSize)(MEVENT hDbEvent) PURE;
- STDMETHOD_(BOOL, GetEvent)(MEVENT hDbEvent, DBEVENTINFO *dbe) PURE;
- STDMETHOD_(BOOL, MarkEventRead)(MCONTACT contactID, MEVENT hDbEvent) PURE;
- STDMETHOD_(MCONTACT, GetEventContact)(MEVENT hDbEvent) PURE;
- STDMETHOD_(MEVENT, FindFirstEvent)(MCONTACT contactID) PURE;
- STDMETHOD_(MEVENT, FindFirstUnreadEvent)(MCONTACT contactID) PURE;
- STDMETHOD_(MEVENT, FindLastEvent)(MCONTACT contactID) PURE;
- STDMETHOD_(MEVENT, FindNextEvent)(MCONTACT contactID, MEVENT hDbEvent) PURE;
- STDMETHOD_(MEVENT, FindPrevEvent)(MCONTACT contactID, MEVENT hDbEvent) PURE;
-
- STDMETHOD_(BOOL, DeleteModule)(MCONTACT contactID, LPCSTR szModule) PURE;
- STDMETHOD_(BOOL, EnumModuleNames)(DBMODULEENUMPROC pFunc, void *pParam) PURE;
-
- STDMETHOD_(BOOL, GetContactSetting)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) PURE;
- STDMETHOD_(BOOL, GetContactSettingStr)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) PURE;
- STDMETHOD_(BOOL, GetContactSettingStatic)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) PURE;
- STDMETHOD_(BOOL, FreeVariant)(DBVARIANT *dbv) PURE;
- STDMETHOD_(BOOL, WriteContactSetting)(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) PURE;
- STDMETHOD_(BOOL, DeleteContactSetting)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting) PURE;
- STDMETHOD_(BOOL, EnumContactSettings)(MCONTACT contactID, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) PURE;
- STDMETHOD_(BOOL, SetSettingResident)(BOOL bIsResident, const char *pszSettingName) PURE;
- STDMETHOD_(BOOL, EnumResidentSettings)(DBMODULEENUMPROC pFunc, void *pParam) PURE;
- STDMETHOD_(BOOL, IsSettingEncrypted)(LPCSTR szModule, LPCSTR szSetting) PURE;
-
- STDMETHOD_(BOOL, MetaDetouchSub)(DBCachedContact*, int nSub) PURE;
- STDMETHOD_(BOOL, MetaSetDefault)(DBCachedContact*) PURE;
- STDMETHOD_(BOOL, MetaMergeHistory)(DBCachedContact *ccMeta, DBCachedContact *ccSub) PURE;
- STDMETHOD_(BOOL, MetaSplitHistory)(DBCachedContact *ccMeta, DBCachedContact *ccSub) PURE;
- STDMETHOD_(BOOL, MetaRemoveSubHistory)(DBCachedContact *ccSub) PURE;
-
- STDMETHOD_(BOOL, Compact)(void) PURE;
- STDMETHOD_(BOOL, Backup)(LPCWSTR) PURE;
- STDMETHOD_(BOOL, Flush)(void) PURE;
-
- STDMETHOD_(MIDatabaseChecker*, GetChecker)(void) PURE;
- STDMETHOD_(DATABASELINK*, GetDriver)(void) PURE;
-
- STDMETHOD_(MEVENT, GetEventById)(LPCSTR szModule, LPCSTR szId) PURE;
-
- STDMETHOD_(DB::EventCursor*, EventCursor)(MCONTACT hContact, MEVENT hDbEvent) PURE;
- STDMETHOD_(DB::EventCursor*, EventCursorRev)(MCONTACT hContact, MEVENT hDbEvent) PURE;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma warning(push)
-#pragma warning(disable:4275)
-
-struct MICryptoEngine;
-struct CRYPTO_PROVIDER;
-
-class MIR_APP_EXPORT MDatabaseCommon : public MIDatabase, public MNonCopyable
-{
- HANDLE m_hLock = nullptr;
-
-protected:
- bool m_bEncrypted = false, m_bUsesPassword = false;
- int m_codePage;
-
- mir_cs m_csDbAccess;
- LIST<char> m_lResidentSettings;
- MIDatabaseCache* m_cache;
- MICryptoEngine *m_crypto = nullptr;
-
-protected:
- int CheckProto(DBCachedContact *cc, const char *proto);
- void FillContactSettings();
- bool LockName(const wchar_t *pwszProfileName);
- void UnlockName();
-
- STDMETHOD_(BOOL, GetContactSettingWorker)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic);
- STDMETHOD_(BOOL, WriteContactSettingWorker)(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) PURE;
-
-public:
- MDatabaseCommon();
- virtual ~MDatabaseCommon();
-
- __forceinline bool isEncrypted() const { return m_bEncrypted; }
- __forceinline MICryptoEngine* getCrypt() const { return m_crypto; }
- __forceinline MIDatabaseCache* getCache() const { return m_cache; }
- __forceinline bool usesPassword() const { return m_bUsesPassword; }
-
- void SetPassword(const wchar_t *ptszPassword);
-
- STDMETHODIMP_(BOOL) DeleteModule(MCONTACT contactID, LPCSTR szModule) override;
-
- STDMETHODIMP_(MCONTACT) FindFirstContact(const char *szProto = nullptr) override;
- STDMETHODIMP_(MCONTACT) FindNextContact(MCONTACT contactID, const char *szProto = nullptr) override;
-
- STDMETHODIMP_(BOOL) MetaDetouchSub(DBCachedContact *cc, int nSub) override;
- STDMETHODIMP_(BOOL) MetaSetDefault(DBCachedContact *cc) override;
- STDMETHODIMP_(BOOL) MetaRemoveSubHistory(DBCachedContact *ccSub) override;
-
- STDMETHODIMP_(BOOL) IsSettingEncrypted(LPCSTR szModule, LPCSTR szSetting) override;
- STDMETHODIMP_(BOOL) GetContactSetting(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) override;
- STDMETHODIMP_(BOOL) GetContactSettingStr(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) override;
- STDMETHODIMP_(BOOL) GetContactSettingStatic(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) override;
- STDMETHODIMP_(BOOL) FreeVariant(DBVARIANT *dbv);
- STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) override;
-
- STDMETHODIMP_(BOOL) EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam) override;
- STDMETHODIMP_(BOOL) SetSettingResident(BOOL bIsResident, const char *pszSettingName) override;
-
- STDMETHODIMP_(BOOL) Compact(void) override;
- STDMETHODIMP_(BOOL) Backup(LPCWSTR) override;
- STDMETHODIMP_(BOOL) Flush(void) override;
-
- STDMETHODIMP_(MIDatabaseChecker*) GetChecker(void) override;
-
- STDMETHODIMP_(DB::EventCursor*) EventCursor(MCONTACT hContact, MEVENT hDbEvent) override;
- STDMETHODIMP_(DB::EventCursor*) EventCursorRev(MCONTACT hContact, MEVENT hDbEvent) override;
-
- ////////////////////////////////////////////////////////////////////////////////////////
- // encryption support
-
- int InitCrypt();
-
- CRYPTO_PROVIDER* SelectProvider();
- STDMETHOD_(CRYPTO_PROVIDER*, ReadProvider)() PURE;
- STDMETHOD_(BOOL, StoreProvider)(CRYPTO_PROVIDER*) PURE;
-
- STDMETHOD_(BOOL, ReadCryptoKey)(MBinBuffer&) PURE;
- STDMETHOD_(BOOL, StoreCryptoKey)() PURE;
-
- STDMETHOD_(BOOL, EnableEncryption)(BOOL) PURE;
- STDMETHOD_(BOOL, ReadEncryption)() PURE;
-};
-
-#pragma warning(pop)
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Read-only database, that cannot add/modify information in a profile
-
-class MIR_APP_EXPORT MDatabaseReadonly : public MDatabaseCommon
-{
-public:
- MDatabaseReadonly();
-
- STDMETHODIMP_(BOOL) IsRelational(void) override;
-
- STDMETHODIMP_(void) SetCacheSafetyMode(BOOL) override;
-
- STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC, void*) override;
-
- STDMETHODIMP_(CRYPTO_PROVIDER*) ReadProvider() override;
- STDMETHODIMP_(BOOL) StoreProvider(CRYPTO_PROVIDER*) override;
- STDMETHODIMP_(BOOL) ReadCryptoKey(MBinBuffer&) override;
- STDMETHODIMP_(BOOL) StoreCryptoKey() override;
- STDMETHODIMP_(BOOL) EnableEncryption(BOOL) override;
- STDMETHODIMP_(BOOL) ReadEncryption() override;
-
- ////////////////////////////////////////////////////////////////////////////////////////
- STDMETHODIMP_(MCONTACT) AddContact(void) override;
- STDMETHODIMP_(LONG) DeleteContact(MCONTACT) override;
- STDMETHODIMP_(BOOL) IsDbContact(MCONTACT contactID) override;
- STDMETHODIMP_(LONG) GetContactSize(void) override;
-
- ////////////////////////////////////////////////////////////////////////////////////////
- STDMETHODIMP_(MEVENT) AddEvent(MCONTACT, const DBEVENTINFO*) override;
- STDMETHODIMP_(BOOL) DeleteEvent(MEVENT) override;
- STDMETHODIMP_(BOOL) EditEvent(MCONTACT contactID, MEVENT hDbEvent, const DBEVENTINFO *dbe) override;
- STDMETHODIMP_(LONG) GetBlobSize(MEVENT) override;
- STDMETHODIMP_(BOOL) MarkEventRead(MCONTACT, MEVENT) override;
- STDMETHODIMP_(MCONTACT) GetEventContact(MEVENT) override;
- STDMETHODIMP_(MEVENT) FindFirstUnreadEvent(MCONTACT) override;
-
- ////////////////////////////////////////////////////////////////////////////////////////
- STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT, LPCSTR, LPCSTR, DBVARIANT*, int) override;
- STDMETHODIMP_(BOOL) WriteContactSettingWorker(MCONTACT, DBCONTACTWRITESETTING&) override;
- STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT, LPCSTR, LPCSTR) override;
- STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT, DBSETTINGENUMPROC, const char*, void*) override;
-
- ////////////////////////////////////////////////////////////////////////////////////////
- STDMETHODIMP_(BOOL) MetaMergeHistory(DBCachedContact*, DBCachedContact*) override;
- STDMETHODIMP_(BOOL) MetaSplitHistory(DBCachedContact*, DBCachedContact*) override;
- STDMETHODIMP_(BOOL) MetaRemoveSubHistory(DBCachedContact*) override;
-
- ////////////////////////////////////////////////////////////////////////////////////////
- STDMETHODIMP_(MEVENT) GetEventById(LPCSTR szModule, LPCSTR szId) override;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Each database plugin should register itself using this structure
-
-// Codes for DATABASELINK functions
-
-// grokHeader() error codes
-#define EGROKPRF_NOERROR 0
-#define EGROKPRF_CANTREAD 1 // can't open the profile for reading
-#define EGROKPRF_UNKHEADER 2 // header not supported, not a supported profile
-#define EGROKPRF_VERNEWER 3 // header correct, version in profile newer than reader/writer
-#define EGROKPRF_DAMAGED 4 // header/version fine, other internal data missing, damaged.
-#define EGROKPRF_OBSOLETE 5 // obsolete database version detected, requiring conversion
-
-// makeDatabase() error codes
-#define EMKPRF_CREATEFAILED 1 // for some reason CreateFile() didnt like something
-
-#define MDB_CAPS_CREATE 0x0001 // new database can be created
-#define MDB_CAPS_COMPACT 0x0002 // database can be compacted
-#define MDB_CAPS_CHECK 0x0004 // database can be checked
-
-
-struct DATABASELINK
-{
- int capabilities;
- char* szShortName; // uniqie short database name
- wchar_t* szFullName; // in English, auto-translated by the core
-
- /*
- profile: pointer to a string which contains full path + name
- Affect: The database plugin should create the profile, the filepath will not exist at
- the time of this call, profile will be C:\..\<name>.dat
- Returns: 0 on success, non zero on failure - error contains extended error information, see EMKPRF_*
- */
- int (*makeDatabase)(const wchar_t *profile);
-
- /*
- profile: [in] a null terminated string to file path of selected profile
- error: [in/out] pointer to an int to set with error if any
- Affect: Ask the database plugin if it supports the given profile, if it does it will
- return 0, if it doesnt return 1, with the error set in error -- EGROKPRF_* can be valid error
- condition, most common error would be [EGROKPRF_UNKHEADER]
- Note: Just because 1 is returned, doesnt mean the profile is not supported, the profile might be damaged
- etc.
- Returns: 0 on success, non zero on failure
- */
- int (*grokHeader)(const wchar_t *profile);
-
- /*
- Affect: Tell the database to create all services/hooks that a 3.xx legacy database might support into link,
- which is a PLUGINLINK structure
- Returns: 0 on success, nonzero on failure
- */
- MDatabaseCommon* (*Load)(const wchar_t *profile, BOOL bReadOnly);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// global database event handles
-
-EXTERN_C MIR_APP_EXPORT HANDLE
- g_hevContactDeleted, // ME_DB_CONTACT_DELETED
- g_hevContactAdded, // ME_DB_CONTACT_ADDED
- g_hevSettingChanged, // ME_DB_CONTACT_SETTINGCHANGED
- g_hevMarkedRead, // ME_DB_EVENT_MARKED_READ
- g_hevEventAdded, // ME_DB_EVENT_ADDED
- g_hevEventEdited, // ME_DB_EVENT_EDITED
- g_hevEventDeleted, // ME_DB_EVENT_DELETED
- g_hevEventFiltered; // ME_DB_EVENT_FILTER_ADD
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// cache access function
-
-EXTERN_C MIR_CORE_DLL(DBCachedContact*) db_get_contact(MCONTACT);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// database list's functions
-
-EXTERN_C MIR_CORE_DLL(MDatabaseCommon*) db_get_current(void);
-EXTERN_C MIR_CORE_DLL(void) db_setCurrent(MDatabaseCommon *_db);
-
-// registers a database plugin
-EXTERN_C MIR_APP_DLL(void) RegisterDatabasePlugin(DATABASELINK *pDescr);
-
-// looks for a database plugin by its short name
-// returns DATABASELINK* of the required plugin or nullptr on error
-EXTERN_C MIR_APP_DLL(DATABASELINK*) GetDatabasePlugin(const char *pszDriverName);
-
-// looks for a database plugin suitable to open this file
-// returns DATABASELINK* of the required plugin or nullptr on error
-EXTERN_C MIR_APP_DLL(DATABASELINK*) FindDatabasePlugin(const wchar_t *ptszFileName);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// database upgrader
-
-namespace DB
-{
- MIR_APP_DLL(MDatabaseCommon *) Upgrade(const wchar_t *profile);
-}
-
-#endif // M_DB_INT_H__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+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
+aint with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_DB_INT_H__
+#define M_DB_INT_H__ 1
+
+#ifndef M_CORE_H__
+ #include <m_core.h>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// basic database checker interface
+
+#define STATUS_MESSAGE 0
+#define STATUS_WARNING 1
+#define STATUS_ERROR 2
+#define STATUS_FATAL 3
+#define STATUS_SUCCESS 4
+
+struct DATABASELINK;
+
+struct DBCHeckCallback
+{
+ DWORD spaceProcessed, spaceUsed;
+
+ void (*pfnAddLogMessage)(int type, const wchar_t *ptszFormat, ...);
+};
+
+interface MIDatabaseChecker
+{
+ STDMETHOD_(BOOL, Start)(DBCHeckCallback *callback) PURE;
+ STDMETHOD_(BOOL, CheckDb)(int phase) PURE;
+ STDMETHOD_(void, Destroy)() PURE;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// basic database interface
+
+struct DBCachedGlobalValue
+{
+ char *name;
+ DBVARIANT value;
+};
+
+struct DBCachedContactValue
+{
+ char *name;
+ DBVARIANT value;
+ DBCachedContactValue *next;
+};
+
+struct DBCachedContactBase
+{
+ MCONTACT contactID;
+ char *szProto;
+ DBCachedContactValue *first, *last;
+
+ // metacontacts
+ int nSubs; // == -1 -> not a metacontact
+ MCONTACT *pSubs;
+ MCONTACT parentID; // == 0 -> not a subcontact
+ int nDefault; // default sub number
+
+ __forceinline bool IsMeta() const { return nSubs != -1; }
+ __forceinline bool IsSub() const { return parentID != 0; }
+};
+
+#ifndef OWN_CACHED_CONTACT
+struct DBCachedContact : public DBCachedContactBase {};
+#else
+struct DBCachedContact;
+#endif
+
+interface MIDatabaseCache : public MZeroedObject
+{
+ STDMETHOD_(DBCachedContact*, AddContactToCache)(MCONTACT contactID) PURE;
+ STDMETHOD_(DBCachedContact*, GetCachedContact)(MCONTACT contactID) PURE;
+ STDMETHOD_(DBCachedContact*, GetFirstContact)(void) PURE;
+ STDMETHOD_(DBCachedContact*, GetNextContact)(MCONTACT contactID) PURE;
+ STDMETHOD_(void, FreeCachedContact)(MCONTACT contactID) PURE;
+
+ STDMETHOD_(char*, InsertCachedSetting)(const char *szName, size_t) PURE;
+ STDMETHOD_(char*, GetCachedSetting)(const char *szModuleName, const char *szSettingName, size_t, size_t) PURE;
+ STDMETHOD_(void, SetCachedVariant)(DBVARIANT *s, DBVARIANT *d) PURE;
+ STDMETHOD_(DBVARIANT*, GetCachedValuePtr)(MCONTACT contactID, char *szSetting, int bAllocate) PURE;
+};
+
+interface MIR_APP_EXPORT MIDatabase
+{
+ STDMETHOD_(BOOL, IsRelational)(void) PURE;
+ STDMETHOD_(void, SetCacheSafetyMode)(BOOL) PURE;
+
+ STDMETHOD_(int, GetContactCount)(void) PURE;
+ STDMETHOD_(MCONTACT, FindFirstContact)(const char *szProto = nullptr) PURE;
+ STDMETHOD_(MCONTACT, FindNextContact)(MCONTACT contactID, const char *szProto = nullptr) PURE;
+
+ STDMETHOD_(int, DeleteContact)(MCONTACT contactID) PURE;
+ STDMETHOD_(MCONTACT, AddContact)(void) PURE;
+ STDMETHOD_(BOOL, IsDbContact)(MCONTACT contactID) PURE;
+ STDMETHOD_(int, GetContactSize)(void) PURE;
+
+ STDMETHOD_(int, GetEventCount)(MCONTACT contactID) PURE;
+ STDMETHOD_(MEVENT, AddEvent)(MCONTACT contactID, const DBEVENTINFO *dbe) PURE;
+ STDMETHOD_(BOOL, DeleteEvent)(MEVENT hDbEvent) PURE;
+ STDMETHOD_(BOOL, EditEvent)(MCONTACT contactID, MEVENT hDbEvent, const DBEVENTINFO *dbe) PURE;
+ STDMETHOD_(int, GetBlobSize)(MEVENT hDbEvent) PURE;
+ STDMETHOD_(BOOL, GetEvent)(MEVENT hDbEvent, DBEVENTINFO *dbe) PURE;
+ STDMETHOD_(BOOL, MarkEventRead)(MCONTACT contactID, MEVENT hDbEvent) PURE;
+ STDMETHOD_(MCONTACT, GetEventContact)(MEVENT hDbEvent) PURE;
+ STDMETHOD_(MEVENT, FindFirstEvent)(MCONTACT contactID) PURE;
+ STDMETHOD_(MEVENT, FindFirstUnreadEvent)(MCONTACT contactID) PURE;
+ STDMETHOD_(MEVENT, FindLastEvent)(MCONTACT contactID) PURE;
+ STDMETHOD_(MEVENT, FindNextEvent)(MCONTACT contactID, MEVENT hDbEvent) PURE;
+ STDMETHOD_(MEVENT, FindPrevEvent)(MCONTACT contactID, MEVENT hDbEvent) PURE;
+
+ STDMETHOD_(BOOL, DeleteModule)(MCONTACT contactID, LPCSTR szModule) PURE;
+ STDMETHOD_(BOOL, EnumModuleNames)(DBMODULEENUMPROC pFunc, void *pParam) PURE;
+
+ STDMETHOD_(BOOL, GetContactSetting)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) PURE;
+ STDMETHOD_(BOOL, GetContactSettingStr)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) PURE;
+ STDMETHOD_(BOOL, GetContactSettingStatic)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) PURE;
+ STDMETHOD_(BOOL, FreeVariant)(DBVARIANT *dbv) PURE;
+ STDMETHOD_(BOOL, WriteContactSetting)(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) PURE;
+ STDMETHOD_(BOOL, DeleteContactSetting)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting) PURE;
+ STDMETHOD_(BOOL, EnumContactSettings)(MCONTACT contactID, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) PURE;
+ STDMETHOD_(BOOL, SetSettingResident)(BOOL bIsResident, const char *pszSettingName) PURE;
+ STDMETHOD_(BOOL, EnumResidentSettings)(DBMODULEENUMPROC pFunc, void *pParam) PURE;
+ STDMETHOD_(BOOL, IsSettingEncrypted)(LPCSTR szModule, LPCSTR szSetting) PURE;
+
+ STDMETHOD_(BOOL, MetaDetouchSub)(DBCachedContact*, int nSub) PURE;
+ STDMETHOD_(BOOL, MetaSetDefault)(DBCachedContact*) PURE;
+ STDMETHOD_(BOOL, MetaMergeHistory)(DBCachedContact *ccMeta, DBCachedContact *ccSub) PURE;
+ STDMETHOD_(BOOL, MetaSplitHistory)(DBCachedContact *ccMeta, DBCachedContact *ccSub) PURE;
+ STDMETHOD_(BOOL, MetaRemoveSubHistory)(DBCachedContact *ccSub) PURE;
+
+ STDMETHOD_(BOOL, Compact)(void) PURE;
+ STDMETHOD_(BOOL, Backup)(LPCWSTR) PURE;
+ STDMETHOD_(BOOL, Flush)(void) PURE;
+
+ STDMETHOD_(MIDatabaseChecker*, GetChecker)(void) PURE;
+ STDMETHOD_(DATABASELINK*, GetDriver)(void) PURE;
+
+ STDMETHOD_(MEVENT, GetEventById)(LPCSTR szModule, LPCSTR szId) PURE;
+
+ STDMETHOD_(DB::EventCursor*, EventCursor)(MCONTACT hContact, MEVENT hDbEvent) PURE;
+ STDMETHOD_(DB::EventCursor*, EventCursorRev)(MCONTACT hContact, MEVENT hDbEvent) PURE;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma warning(push)
+#pragma warning(disable:4275)
+
+struct MICryptoEngine;
+struct CRYPTO_PROVIDER;
+
+class MIR_APP_EXPORT MDatabaseCommon : public MIDatabase, public MNonCopyable
+{
+ HANDLE m_hLock = nullptr;
+
+protected:
+ bool m_bEncrypted = false, m_bUsesPassword = false;
+ int m_codePage;
+
+ mir_cs m_csDbAccess;
+ LIST<char> m_lResidentSettings;
+ MIDatabaseCache* m_cache;
+ MICryptoEngine *m_crypto = nullptr;
+
+protected:
+ int CheckProto(DBCachedContact *cc, const char *proto);
+ void FillContactSettings();
+ bool LockName(const wchar_t *pwszProfileName);
+ void UnlockName();
+
+ STDMETHOD_(BOOL, GetContactSettingWorker)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic);
+ STDMETHOD_(BOOL, WriteContactSettingWorker)(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) PURE;
+
+public:
+ MDatabaseCommon();
+ virtual ~MDatabaseCommon();
+
+ __forceinline bool isEncrypted() const { return m_bEncrypted; }
+ __forceinline MICryptoEngine* getCrypt() const { return m_crypto; }
+ __forceinline MIDatabaseCache* getCache() const { return m_cache; }
+ __forceinline bool usesPassword() const { return m_bUsesPassword; }
+
+ void SetPassword(const wchar_t *ptszPassword);
+
+ STDMETHODIMP_(BOOL) DeleteModule(MCONTACT contactID, LPCSTR szModule) override;
+
+ STDMETHODIMP_(MCONTACT) FindFirstContact(const char *szProto = nullptr) override;
+ STDMETHODIMP_(MCONTACT) FindNextContact(MCONTACT contactID, const char *szProto = nullptr) override;
+
+ STDMETHODIMP_(BOOL) MetaDetouchSub(DBCachedContact *cc, int nSub) override;
+ STDMETHODIMP_(BOOL) MetaSetDefault(DBCachedContact *cc) override;
+ STDMETHODIMP_(BOOL) MetaRemoveSubHistory(DBCachedContact *ccSub) override;
+
+ STDMETHODIMP_(BOOL) IsSettingEncrypted(LPCSTR szModule, LPCSTR szSetting) override;
+ STDMETHODIMP_(BOOL) GetContactSetting(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) override;
+ STDMETHODIMP_(BOOL) GetContactSettingStr(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) override;
+ STDMETHODIMP_(BOOL) GetContactSettingStatic(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) override;
+ STDMETHODIMP_(BOOL) FreeVariant(DBVARIANT *dbv);
+ STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) override;
+
+ STDMETHODIMP_(BOOL) EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam) override;
+ STDMETHODIMP_(BOOL) SetSettingResident(BOOL bIsResident, const char *pszSettingName) override;
+
+ STDMETHODIMP_(BOOL) Compact(void) override;
+ STDMETHODIMP_(BOOL) Backup(LPCWSTR) override;
+ STDMETHODIMP_(BOOL) Flush(void) override;
+
+ STDMETHODIMP_(MIDatabaseChecker*) GetChecker(void) override;
+
+ STDMETHODIMP_(DB::EventCursor*) EventCursor(MCONTACT hContact, MEVENT hDbEvent) override;
+ STDMETHODIMP_(DB::EventCursor*) EventCursorRev(MCONTACT hContact, MEVENT hDbEvent) override;
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // encryption support
+
+ int InitCrypt();
+
+ CRYPTO_PROVIDER* SelectProvider();
+ STDMETHOD_(CRYPTO_PROVIDER*, ReadProvider)() PURE;
+ STDMETHOD_(BOOL, StoreProvider)(CRYPTO_PROVIDER*) PURE;
+
+ STDMETHOD_(BOOL, ReadCryptoKey)(MBinBuffer&) PURE;
+ STDMETHOD_(BOOL, StoreCryptoKey)() PURE;
+
+ STDMETHOD_(BOOL, EnableEncryption)(BOOL) PURE;
+ STDMETHOD_(BOOL, ReadEncryption)() PURE;
+};
+
+#pragma warning(pop)
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Read-only database, that cannot add/modify information in a profile
+
+class MIR_APP_EXPORT MDatabaseReadonly : public MDatabaseCommon
+{
+public:
+ MDatabaseReadonly();
+
+ STDMETHODIMP_(BOOL) IsRelational(void) override;
+
+ STDMETHODIMP_(void) SetCacheSafetyMode(BOOL) override;
+
+ STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC, void*) override;
+
+ STDMETHODIMP_(CRYPTO_PROVIDER*) ReadProvider() override;
+ STDMETHODIMP_(BOOL) StoreProvider(CRYPTO_PROVIDER*) override;
+ STDMETHODIMP_(BOOL) ReadCryptoKey(MBinBuffer&) override;
+ STDMETHODIMP_(BOOL) StoreCryptoKey() override;
+ STDMETHODIMP_(BOOL) EnableEncryption(BOOL) override;
+ STDMETHODIMP_(BOOL) ReadEncryption() override;
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ STDMETHODIMP_(MCONTACT) AddContact(void) override;
+ STDMETHODIMP_(int) DeleteContact(MCONTACT) override;
+ STDMETHODIMP_(BOOL) IsDbContact(MCONTACT contactID) override;
+ STDMETHODIMP_(int) GetContactSize(void) override;
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ STDMETHODIMP_(MEVENT) AddEvent(MCONTACT, const DBEVENTINFO*) override;
+ STDMETHODIMP_(BOOL) DeleteEvent(MEVENT) override;
+ STDMETHODIMP_(BOOL) EditEvent(MCONTACT contactID, MEVENT hDbEvent, const DBEVENTINFO *dbe) override;
+ STDMETHODIMP_(int) GetBlobSize(MEVENT) override;
+ STDMETHODIMP_(BOOL) MarkEventRead(MCONTACT, MEVENT) override;
+ STDMETHODIMP_(MCONTACT) GetEventContact(MEVENT) override;
+ STDMETHODIMP_(MEVENT) FindFirstUnreadEvent(MCONTACT) override;
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT, LPCSTR, LPCSTR, DBVARIANT*, int) override;
+ STDMETHODIMP_(BOOL) WriteContactSettingWorker(MCONTACT, DBCONTACTWRITESETTING&) override;
+ STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT, LPCSTR, LPCSTR) override;
+ STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT, DBSETTINGENUMPROC, const char*, void*) override;
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ STDMETHODIMP_(BOOL) MetaMergeHistory(DBCachedContact*, DBCachedContact*) override;
+ STDMETHODIMP_(BOOL) MetaSplitHistory(DBCachedContact*, DBCachedContact*) override;
+ STDMETHODIMP_(BOOL) MetaRemoveSubHistory(DBCachedContact*) override;
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ STDMETHODIMP_(MEVENT) GetEventById(LPCSTR szModule, LPCSTR szId) override;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Each database plugin should register itself using this structure
+
+// Codes for DATABASELINK functions
+
+// grokHeader() error codes
+#define EGROKPRF_NOERROR 0
+#define EGROKPRF_CANTREAD 1 // can't open the profile for reading
+#define EGROKPRF_UNKHEADER 2 // header not supported, not a supported profile
+#define EGROKPRF_VERNEWER 3 // header correct, version in profile newer than reader/writer
+#define EGROKPRF_DAMAGED 4 // header/version fine, other internal data missing, damaged.
+#define EGROKPRF_OBSOLETE 5 // obsolete database version detected, requiring conversion
+
+// makeDatabase() error codes
+#define EMKPRF_CREATEFAILED 1 // for some reason CreateFile() didnt like something
+
+#define MDB_CAPS_CREATE 0x0001 // new database can be created
+#define MDB_CAPS_COMPACT 0x0002 // database can be compacted
+#define MDB_CAPS_CHECK 0x0004 // database can be checked
+
+
+struct DATABASELINK
+{
+ int capabilities;
+ char* szShortName; // uniqie short database name
+ wchar_t* szFullName; // in English, auto-translated by the core
+
+ /*
+ profile: pointer to a string which contains full path + name
+ Affect: The database plugin should create the profile, the filepath will not exist at
+ the time of this call, profile will be C:\..\<name>.dat
+ Returns: 0 on success, non zero on failure - error contains extended error information, see EMKPRF_*
+ */
+ int (*makeDatabase)(const wchar_t *profile);
+
+ /*
+ profile: [in] a null terminated string to file path of selected profile
+ error: [in/out] pointer to an int to set with error if any
+ Affect: Ask the database plugin if it supports the given profile, if it does it will
+ return 0, if it doesnt return 1, with the error set in error -- EGROKPRF_* can be valid error
+ condition, most common error would be [EGROKPRF_UNKHEADER]
+ Note: Just because 1 is returned, doesnt mean the profile is not supported, the profile might be damaged
+ etc.
+ Returns: 0 on success, non zero on failure
+ */
+ int (*grokHeader)(const wchar_t *profile);
+
+ /*
+ Affect: Tell the database to create all services/hooks that a 3.xx legacy database might support into link,
+ which is a PLUGINLINK structure
+ Returns: 0 on success, nonzero on failure
+ */
+ MDatabaseCommon* (*Load)(const wchar_t *profile, BOOL bReadOnly);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// global database event handles
+
+EXTERN_C MIR_APP_EXPORT HANDLE
+ g_hevContactDeleted, // ME_DB_CONTACT_DELETED
+ g_hevContactAdded, // ME_DB_CONTACT_ADDED
+ g_hevSettingChanged, // ME_DB_CONTACT_SETTINGCHANGED
+ g_hevMarkedRead, // ME_DB_EVENT_MARKED_READ
+ g_hevEventAdded, // ME_DB_EVENT_ADDED
+ g_hevEventEdited, // ME_DB_EVENT_EDITED
+ g_hevEventDeleted, // ME_DB_EVENT_DELETED
+ g_hevEventFiltered; // ME_DB_EVENT_FILTER_ADD
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// cache access function
+
+EXTERN_C MIR_CORE_DLL(DBCachedContact*) db_get_contact(MCONTACT);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// database list's functions
+
+EXTERN_C MIR_CORE_DLL(MDatabaseCommon*) db_get_current(void);
+EXTERN_C MIR_CORE_DLL(void) db_setCurrent(MDatabaseCommon *_db);
+
+// registers a database plugin
+EXTERN_C MIR_APP_DLL(void) RegisterDatabasePlugin(DATABASELINK *pDescr);
+
+// looks for a database plugin by its short name
+// returns DATABASELINK* of the required plugin or nullptr on error
+EXTERN_C MIR_APP_DLL(DATABASELINK*) GetDatabasePlugin(const char *pszDriverName);
+
+// looks for a database plugin suitable to open this file
+// returns DATABASELINK* of the required plugin or nullptr on error
+EXTERN_C MIR_APP_DLL(DATABASELINK*) FindDatabasePlugin(const wchar_t *ptszFileName);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// database upgrader
+
+namespace DB
+{
+ MIR_APP_DLL(MDatabaseCommon *) Upgrade(const wchar_t *profile);
+}
+
+#endif // M_DB_INT_H__
diff --git a/include/m_gui.h b/include/m_gui.h
index 85fba587a4..5277d7e05d 100644
--- a/include/m_gui.h
+++ b/include/m_gui.h
@@ -1,1580 +1,1589 @@
-/*
-
-Jabber Protocol Plugin for Miranda NG
-
-Copyright (c) 2002-04 Santithorn Bunchua
-Copyright (c) 2005-12 George Hazan
-Copyright (c) 2007-09 Maxim Mluhov
-Copyright (c) 2007-09 Victor Pavlychko
-Copyright (C) 2012-21 Miranda NG team
-
-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.
-
-*/
-
-#pragma once
-
-#ifndef __M_GUI_H
-#define __M_GUI_H
-
-#include <CommCtrl.h>
-
-#include <m_system.h>
-#include <m_protoint.h>
-#include <m_clc.h>
-
-#pragma warning(disable:4355 4251 4481)
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// helpers for the option's visualization
-
-template<int Size>
-struct CMDBTraits
-{
-};
-
-template<>
-struct CMDBTraits<1>
-{
- typedef BYTE DBType;
- enum { DBTypeId = DBVT_BYTE };
- static __forceinline DBType Get(const char *szModule, const char *szSetting, DBType value)
- {
- return db_get_b(0, szModule, szSetting, value);
- }
- static __forceinline void Set(const char *szModule, const char *szSetting, DBType value)
- {
- db_set_b(0, szModule, szSetting, value);
- }
-};
-
-template<>
-struct CMDBTraits<2>
-{
- typedef WORD DBType;
- enum { DBTypeId = DBVT_WORD };
- static __forceinline DBType Get(const char *szModule, const char *szSetting, DBType value)
- {
- return db_get_w(0, szModule, szSetting, value);
- }
- static __forceinline void Set(const char *szModule, const char *szSetting, DBType value)
- {
- db_set_w(0, szModule, szSetting, value);
- }
-};
-
-template<>
-struct CMDBTraits<4>
-{
- typedef DWORD DBType;
- enum { DBTypeId = DBVT_DWORD };
- static __forceinline DBType Get(const char *szModule, const char *szSetting, DBType value)
- {
- return db_get_dw(0, szModule, szSetting, value);
- }
- static __forceinline void Set(const char *szModule, const char *szSetting, DBType value)
- {
- db_set_dw(0, szModule, szSetting, value);
- }
-};
-
-template<>
-struct CMDBTraits<8>
-{
- typedef DWORD DBType;
- enum { DBTypeId = DBVT_DWORD };
- static __forceinline DBType Get(const char *szModule, const char *szSetting, DBType value)
- {
- return db_get_dw(0, szModule, szSetting, value);
- }
- static __forceinline void Set(const char *szModule, const char *szSetting, DBType value)
- {
- db_set_dw(0, szModule, szSetting, value);
- }
-};
-
-class CMOptionBase : public MNonCopyable
-{
-public:
- __forceinline const char* GetDBModuleName() const { return m_szModuleName; }
- __forceinline const char* GetDBSettingName() const { return m_szSetting; }
-
-protected:
- __forceinline CMOptionBase(PROTO_INTERFACE *proto, const char *szSetting) :
- m_szModuleName(proto->m_szModuleName), m_szSetting(szSetting)
- {}
-
- __forceinline CMOptionBase(const char *module, const char *szSetting) :
- m_szModuleName(module), m_szSetting(szSetting)
- {}
-
- const char *m_szModuleName;
- const char *m_szSetting;
-};
-
-template<class T>
-class CMOption : public CMOptionBase
-{
-public:
- typedef T Type;
-
- __forceinline CMOption(PROTO_INTERFACE *proto, const char *szSetting, Type defValue) :
- CMOptionBase(proto, szSetting), m_default(defValue)
- {}
-
- __forceinline CMOption(const char *szModule, const char *szSetting, Type defValue) :
- CMOptionBase(szModule, szSetting), m_default(defValue)
- {}
-
- __forceinline Type Default() const
- {
- return m_default;
- }
-
- __forceinline operator Type()
- {
- return (Type)CMDBTraits<sizeof(Type)>::Get(m_szModuleName, m_szSetting, m_default);
- }
-
- __forceinline Type operator= (Type value)
- {
- CMDBTraits<sizeof(Type)>::Set(m_szModuleName, m_szSetting, (CMDBTraits<sizeof(Type)>::DBType)value);
- return value;
- }
-
-private:
- Type m_default;
-};
-
-template<>
-class CMOption<char*> : public CMOptionBase
-{
-public:
-
- typedef char Type;
-
- __forceinline CMOption(PROTO_INTERFACE *proto, const char *szSetting, const Type *defValue = nullptr) :
- CMOptionBase(proto, szSetting), m_default(defValue)
- {}
-
- __forceinline CMOption(const char *szModule, const char *szSetting, const Type *defValue = nullptr) :
- CMOptionBase(szModule, szSetting), m_default(defValue)
- {}
-
- __forceinline const Type* Default() const
- {
- return m_default;
- }
-
- __forceinline operator Type*()
- {
- m_value = db_get_sa(0, m_szModuleName, m_szSetting);
- if (!m_value) m_value = mir_strdup(m_default);
- return m_value;
- }
-
- __forceinline Type* operator= (Type *value)
- {
- db_set_s(0, m_szModuleName, m_szSetting, value);
- return value;
- }
-
-private:
- const Type *m_default;
- mir_ptr<Type> m_value;
-};
-
-template<>
-class CMOption<wchar_t*> : public CMOptionBase
-{
-public:
-
- typedef wchar_t Type;
-
- __forceinline CMOption(PROTO_INTERFACE *proto, const char *szSetting, const Type *defValue = nullptr) :
- CMOptionBase(proto, szSetting), m_default(defValue)
- {}
-
- __forceinline CMOption(const char *szModule, const char *szSetting, const Type *defValue = nullptr) :
- CMOptionBase(szModule, szSetting), m_default(defValue)
- {}
-
- __forceinline const Type* Default() const
- {
- return m_default;
- }
-
- __forceinline operator Type*()
- {
- m_value = db_get_wsa(0, m_szModuleName, m_szSetting);
- if (!m_value) m_value = mir_wstrdup(m_default);
- return m_value;
- }
-
- __forceinline const Type* operator= (const Type *value)
- {
- db_set_ws(0, m_szModuleName, m_szSetting, value);
- return value;
- }
-
-private:
- const Type *m_default;
- mir_ptr<Type> m_value;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CDbLink
-
-class MIR_CORE_EXPORT CDataLink
-{
-protected:
- BYTE m_type;
-
-public:
- __inline CDataLink(BYTE type) : m_type(type) {}
- virtual ~CDataLink() {}
-
- __inline BYTE GetDataType() const { return m_type; }
-
- virtual DWORD LoadInt() = 0;
- virtual void SaveInt(DWORD value) = 0;
-
- virtual wchar_t* LoadText() = 0;
- virtual void SaveText(wchar_t *value) = 0;
-};
-
-class MIR_CORE_EXPORT CDbLink : public CDataLink
-{
- char *m_szModule;
- char *m_szSetting;
-
- DWORD m_iDefault;
- wchar_t *m_szDefault;
-
- DBVARIANT dbv;
-
-public:
- CDbLink(const char *szModule, const char *szSetting, BYTE type, DWORD iValue);
- CDbLink(const char *szModule, const char *szSetting, BYTE type, wchar_t *szValue);
- ~CDbLink();
-
- DWORD LoadInt() override;
- void SaveInt(DWORD value) override;
-
- wchar_t* LoadText() override;
- void SaveText(wchar_t *value) override;
-};
-
-template<class T>
-class CMOptionLink : public CDataLink
-{
-private:
- CMOption<T> *m_option;
-
-public:
- __forceinline CMOptionLink(CMOption<T> &option) :
- CDataLink(CMDBTraits<sizeof(T)>::DBTypeId), m_option(&option)
- {}
-
- __forceinline DWORD LoadInt() override { return (DWORD)(T)*m_option; }
- __forceinline void SaveInt(DWORD value) override { *m_option = (T)value; }
-
- __forceinline wchar_t* LoadText() override { return nullptr; }
- __forceinline void SaveText(wchar_t*) override {}
-};
-
-template<>
-class CMOptionLink<wchar_t*> : public CDataLink
-{
-private:
- typedef wchar_t *T;
- CMOption<T> *m_option;
-
-public:
- __forceinline CMOptionLink(CMOption<T> &option) :
- CDataLink(DBVT_WCHAR), m_option(&option)
- {}
-
- __forceinline DWORD LoadInt() override { return 0; }
- __forceinline void SaveInt(DWORD) override { }
-
- __forceinline wchar_t* LoadText() override { return *m_option; }
- __forceinline void SaveText(wchar_t *value) override { *m_option = value; }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CDlgBase - base dialog class
-
-class MIR_CORE_EXPORT CDlgBase
-{
- friend class CTimer;
- friend class CCtrlBase;
- friend class CCtrlData;
-
-public:
- CDlgBase(class CMPluginBase &pPlug, int idDialog);
- virtual ~CDlgBase();
-
- // general utilities
- void Close();
- void Resize();
- void Create();
- void Show(int nCmdShow = SW_SHOW);
- int DoModal();
- void EndModal(INT_PTR nResult);
-
- CCtrlBase* FindControl(int idCtrl);
- CCtrlBase* FindControl(HWND hwnd);
-
- void SetCaption(const wchar_t *ptszCaption);
- void SetDraw(bool bEnable);
- void NotifyChange(void); // sends a notification to a parent window
-
- __forceinline HINSTANCE GetInst() const { return m_pPlugin.getInst(); }
- __forceinline HWND GetHwnd() const { return m_hwnd; }
- __forceinline void Hide() { Show(SW_HIDE); }
- __forceinline bool IsInitialized() const { return m_bInitialized; }
- __forceinline void SetMinSize(int x, int y) { m_iMinWidth = x, m_iMinHeight = y; }
- __forceinline void SetParent(HWND hwnd) { m_hwndParent = hwnd; }
-
- __forceinline CCtrlBase* operator[](int iControlId) { return FindControl(iControlId); }
-
- static CDlgBase* Find(HWND hwnd);
-
-protected:
- HWND m_hwnd = nullptr; // must be the first data item
- HWND m_hwndParent = nullptr;
- int m_idDialog;
-
- bool m_isModal = false;
- bool m_bInitialized = false;
- bool m_forceResizable = false;
- bool m_bSucceeded = false; // was IDOK pressed or not
- bool m_bExiting = false; // window received WM_CLOSE and gonna die soon
-
- enum { CLOSE_ON_OK = 0x1, CLOSE_ON_CANCEL = 0x2 };
- BYTE m_autoClose; // automatically close dialog on IDOK/CANCEL commands. default: CLOSE_ON_OK|CLOSE_ON_CANCEL
-
- CMPluginBase &m_pPlugin;
-
- // override this handlers to provide custom functionality
- // general messages
- virtual bool OnInitDialog();
- virtual bool OnApply();
- virtual bool OnClose();
- virtual void OnDestroy();
-
- virtual void OnTimer(CTimer*);
-
- // miranda-related stuff
- virtual int Resizer(UTILRESIZECONTROL *urc);
- virtual void OnReset();
- virtual void OnChange();
-
- // main dialog procedure
- virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam);
-
- CCallback<void> m_OnFinishWizard;
-
- // register controls
- void AddControl(CCtrlBase *ctrl);
- void RemoveControl(CCtrlBase *ctrl);
-
- // timers
- void AddTimer(CTimer *timer);
- void RemoveTimer(UINT_PTR idEvent);
-
- // options support
- void CreateLink(CCtrlData& ctrl, const char *szSetting, BYTE type, DWORD iValue);
- void CreateLink(CCtrlData& ctrl, const char *szSetting, wchar_t *szValue);
-
- template<class T>
- __inline void CreateLink(CCtrlData& ctrl, CMOption<T> &option)
- {
- ctrl.CreateDbLink(new CMOptionLink<T>(option));
- }
-
- // win32 stuff
- void ThemeDialogBackground(BOOL tabbed);
-
-private:
- LIST<CTimer> m_timers;
- LIST<CCtrlBase> m_controls;
-
- void NotifyControls(void (CCtrlBase::*fn)());
- bool VerifyControls(bool (CCtrlBase::*fn)());
-
- CTimer* FindTimer(int idEvent);
- int m_iMinWidth = -1, m_iMinHeight = -1;
-
- static BOOL CALLBACK GlobalFieldEnum(HWND hwnd, LPARAM lParam);
- static INT_PTR CALLBACK GlobalDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
- static int GlobalDlgResizer(HWND hwnd, LPARAM lParam, UTILRESIZECONTROL *urc);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CTimer
-
-class MIR_CORE_EXPORT CTimer
-{
- friend class CDlgBase;
-
-public:
- CTimer(CDlgBase* wnd, UINT_PTR idEvent);
- ~CTimer();
-
- __forceinline UINT_PTR GetEventId() const { return m_idEvent; }
- __forceinline HWND GetHwnd() const { return m_wnd->GetHwnd(); }
-
- virtual BOOL OnTimer();
-
- void Start(int elapse);
- bool Stop(); // returns true if timer was active
-
- void StartSafe(int elapse);
- void StopSafe();
-
- CCallback<CTimer> OnEvent;
-
-protected:
- UINT_PTR m_idEvent;
- CDlgBase* m_wnd;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlBase
-
-struct CContextMenuPos
-{
- const CCtrlBase *pCtrl;
- POINT pt;
- union {
- int iCurr; // int for list boxes
- HTREEITEM hItem;
- };
-};
-
-class MIR_CORE_EXPORT CCtrlBase
-{
- friend class CDlgBase;
-
- __forceinline CCtrlBase(const CCtrlBase&) = delete;
- __forceinline CCtrlBase& operator=(const CCtrlBase&) = delete;
-
-public:
- CCtrlBase(CDlgBase *wnd, int idCtrl);
- virtual ~CCtrlBase();
-
- __forceinline HWND GetHwnd() const { return m_hwnd; }
- __forceinline int GetCtrlId() const { return m_idCtrl; }
- __forceinline CDlgBase *GetParent() const { return m_parentWnd; }
- __forceinline bool IsChanged() const { return m_bChanged; }
- __forceinline void SetSilent(bool bSilent = true) { m_bSilent = bSilent; }
- __forceinline void UseSystemColors() { m_bUseSystemColors = true; }
-
- void Show(bool bShow = true);
- __forceinline void Hide() { Show(false); }
-
- void Enable(bool bIsEnable = true);
- __forceinline void Disable() { Enable(false); }
- bool Enabled(void) const;
-
- void NotifyChange();
- void SetDraw(bool bEnable);
-
- LRESULT SendMsg(UINT Msg, WPARAM wParam, LPARAM lParam) const;
-
- void SetText(const wchar_t *text);
- void SetTextA(const char *text);
- void SetInt(int value);
-
- wchar_t* GetText() const;
- char* GetTextA() const;
- char* GetTextU() const;
-
- wchar_t* GetText(wchar_t *buf, size_t size) const;
- char* GetTextA(char *buf, size_t size) const;
- char* GetTextU(char *buf, size_t size) const;
-
- int GetInt() const;
-
- virtual BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD /*idCode*/) { return FALSE; }
- virtual BOOL OnNotify(int /*idCtrl*/, NMHDR* /*pnmh*/) { return FALSE; }
-
- virtual BOOL OnMeasureItem(MEASUREITEMSTRUCT*) { return FALSE; }
- virtual BOOL OnDrawItem(DRAWITEMSTRUCT*) { return FALSE; }
- virtual BOOL OnDeleteItem(DELETEITEMSTRUCT*) { return FALSE; }
-
- virtual void OnInit();
- virtual void OnDestroy();
-
- virtual bool OnApply();
- virtual void OnReset();
-
-protected:
- HWND m_hwnd = nullptr; // must be the first data item
- int m_idCtrl;
- CDlgBase* m_parentWnd;
- bool m_bChanged = false, m_bSilent = false, m_bUseSystemColors = false, m_bNotifiable = false;
-
-public:
- CCallback<CCtrlBase> OnChange;
- CCallback<CContextMenuPos> OnBuildMenu;
-
-protected:
- virtual void GetCaretPos(CContextMenuPos&) const;
- virtual LRESULT CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam);
-
- void Subclass();
- void Unsubclass();
-
-private:
- static LRESULT CALLBACK GlobalSubclassWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlLabel
-
-class MIR_CORE_EXPORT CCtrlLabel : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
-public:
- CCtrlLabel(CDlgBase *dlg, int ctrlId);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlButton
-
-class MIR_CORE_EXPORT CCtrlButton : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
-public:
- CCtrlButton(CDlgBase *dlg, int ctrlId);
-
- BOOL OnCommand(HWND hwndCtrl, WORD idCtrl, WORD idCode) override;
-
- CCallback<CCtrlButton> OnClick;
-
- void Click();
- bool IsPushed() const;
- void Push(bool bPushed);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlMButton
-
-class MIR_CORE_EXPORT CCtrlMButton : public CCtrlButton
-{
- typedef CCtrlButton CSuper;
-
-public:
- CCtrlMButton(CDlgBase *dlg, int ctrlId, HICON hIcon, const char* tooltip);
- CCtrlMButton(CDlgBase *dlg, int ctrlId, int iCoreIcon, const char* tooltip);
- ~CCtrlMButton();
-
- void MakeFlat();
- void MakePush();
-
- void OnInit() override;
-
-protected:
- HICON m_hIcon;
- const char* m_toolTip;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CSplitter
-
-class MIR_CORE_EXPORT CSplitter : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
-public:
- CSplitter(CDlgBase *dlg, int ctrlId);
-
- __forceinline int GetPos() const { return m_iPosition; }
-
-protected:
- LRESULT CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
- void OnInit() override;
-
- int m_iPosition;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlHyperlink
-
-class MIR_CORE_EXPORT CCtrlHyperlink : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
-public:
- CCtrlHyperlink(CDlgBase *dlg, int ctrlId, const char* url = nullptr);
-
- BOOL OnCommand(HWND hwndCtrl, WORD idCtrl, WORD idCode) override;
-
- CCallback<CCtrlHyperlink> OnClick;
-
- void SetUrl(const char *url);
- const char *GetUrl();
-
-protected:
- const char* m_url;
-
- void Default_OnClick(CCtrlHyperlink*);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CProgress
-
-class MIR_CORE_EXPORT CCtrlProgress : public CCtrlBase
-{
-public:
- CCtrlProgress(CDlgBase *dlg, int ctrlId);
-
- void SetRange(WORD max, WORD min = 0);
- void SetPosition(WORD value);
- void SetStep(WORD value);
- WORD Move(WORD delta = 0);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlClc
-
-#if !defined(MGROUP)
- typedef int MGROUP;
-#endif
-
-class MIR_CORE_EXPORT CCtrlClc : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
-public:
- CCtrlClc(CDlgBase *dlg, int ctrlId);
-
- void AddContact(MCONTACT hContact);
- void AddGroup(HANDLE hGroup);
- HANDLE AddInfoItem(CLCINFOITEM *cii);
- void AutoRebuild();
- void DeleteItem(HANDLE hItem);
- void EditLabel(HANDLE hItem);
- void EndEditLabel(bool save);
- void EnsureVisible(HANDLE hItem, bool partialOk);
- void Expand(HANDLE hItem, DWORD flags);
- HANDLE FindContact(MCONTACT hContact);
- HANDLE FindGroup(MGROUP hGroup);
- COLORREF GetBkColor() const;
- bool GetCheck(HANDLE hItem) const;
- int GetCount() const;
- HWND GetEditControl() const;
- DWORD GetExStyle() const;
- DWORD GetExpand(HANDLE hItem) const;
- int GetExtraColumns() const;
- BYTE GetExtraImage(HANDLE hItem, int iColumn) const;
- HIMAGELIST GetExtraImageList() const;
- HFONT GetFont(int iFontId) const;
- bool GetHideOfflineRoot() const;
- int GetItemType(HANDLE hItem) const;
- HANDLE GetNextItem(HANDLE hItem, DWORD flags) const;
- HANDLE GetSelection() const;
- HANDLE HitTest(int x, int y, DWORD *hitTest) const;
- void SelectItem(HANDLE hItem);
- void SetBkColor(COLORREF clBack);
- void SetCheck(HANDLE hItem, bool check);
- void SetExStyle(DWORD exStyle);
- void SetExtraColumns(int iColumns);
- void SetExtraImage(HANDLE hItem, int iColumn, int iImage);
- void SetExtraImageList(HIMAGELIST hImgList);
- void SetFont(int iFontId, HANDLE hFont, bool bRedraw);
- void SetItemText(HANDLE hItem, char *szText);
- void SetHideEmptyGroups(bool state);
- void SetHideOfflineRoot(bool state);
- void SetOfflineModes(DWORD modes);
- void SetUseGroups(bool state);
-
- struct TEventInfo
- {
- CCtrlClc *ctrl;
- NMCLISTCONTROL *info;
- };
-
- CCallback<TEventInfo> OnExpanded;
- CCallback<TEventInfo> OnListRebuilt;
- CCallback<TEventInfo> OnItemChecked;
- CCallback<TEventInfo> OnDragging;
- CCallback<TEventInfo> OnDropped;
- CCallback<TEventInfo> OnListSizeChange;
- CCallback<TEventInfo> OnOptionsChanged;
- CCallback<TEventInfo> OnDragStop;
- CCallback<TEventInfo> OnNewContact;
- CCallback<TEventInfo> OnContactMoved;
- CCallback<TEventInfo> OnCheckChanged;
- CCallback<TEventInfo> OnClick;
-
-protected:
- BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlData - data access controls base class
-
-class MIR_CORE_EXPORT CCtrlData : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
-public:
- CCtrlData(CDlgBase *dlg, int ctrlId);
- ~CCtrlData();
-
- void CreateDbLink(const char* szModuleName, const char* szSetting, BYTE type, DWORD iValue);
- void CreateDbLink(const char* szModuleName, const char* szSetting, wchar_t* szValue);
- void CreateDbLink(CDataLink *link) { m_dbLink = link; }
-
- void OnInit() override;
-
-protected:
- CDataLink *m_dbLink;
-
- __inline BYTE GetDataType() { return m_dbLink ? m_dbLink->GetDataType() : DBVT_DELETED; }
- __inline DWORD LoadInt() { return m_dbLink ? m_dbLink->LoadInt() : 0; }
- __inline void SaveInt(DWORD value) { if (m_dbLink) m_dbLink->SaveInt(value); }
- __inline const wchar_t *LoadText() { return m_dbLink ? m_dbLink->LoadText() : L""; }
- __inline void SaveText(wchar_t *value) { if (m_dbLink) m_dbLink->SaveText(value); }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlCheck
-
-class MIR_CORE_EXPORT CCtrlCheck : public CCtrlData
-{
- typedef CCtrlData CSuper;
-
-public:
- CCtrlCheck(CDlgBase *dlg, int ctrlId);
- BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD /*idCode*/) override;
-
- bool OnApply() override;
- void OnReset() override;
-
- int GetState() const;
- void SetState(int state);
-
- bool IsChecked();
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlColor - color picker
-
-class MIR_CORE_EXPORT CCtrlColor : public CCtrlData
-{
- typedef CCtrlData CSuper;
-
-public:
- CCtrlColor(CDlgBase *dlg, int ctrlId);
- BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD /*idCode*/) override;
-
- bool OnApply() override;
- void OnReset() override;
-
- DWORD GetColor();
- void SetColor(DWORD dwValue);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlDate - date & time picker
-
-class MIR_CORE_EXPORT CCtrlDate : public CCtrlData
-{
- typedef CCtrlData CSuper;
-
- BOOL OnNotify(int, NMHDR*) override;
-
-public:
- CCtrlDate(CDlgBase *dlg, int ctrlId);
-
- void GetTime(SYSTEMTIME*);
- void SetTime(SYSTEMTIME*);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlEdit
-
-class MIR_CORE_EXPORT CCtrlEdit : public CCtrlData
-{
- typedef CCtrlData CSuper;
-
-public:
- CCtrlEdit(CDlgBase *dlg, int ctrlId);
- BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD idCode) override;
-
- bool OnApply() override;
- void OnReset() override;
-
- void SetMaxLength(unsigned int len);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlRichEdit
-
-class MIR_CORE_EXPORT CCtrlRichEdit : public CCtrlEdit
-{
- typedef CCtrlEdit CSuper;
-
-public:
- CCtrlRichEdit(CDlgBase *dlg, int ctrlId);
-
- // returns text length in bytes if a parameter is omitted or in symbols, if not
- int GetRichTextLength(int iCodePage = CP_ACP) const;
-
- // returns a buffer that should be freed using mir_free() or ptrA/ptrW
- char* GetRichTextRtf(bool bText = false, bool bSelection = false) const; // returns text with formatting
- wchar_t* GetRichText() const; // returns only text in ucs2
-
- // these methods return text length in Unicode chars
- int SetRichText(const wchar_t *text);
- int SetRichTextRtf(const char *text);
-
- // enables or disables content editing
- void SetReadOnly(bool bReadOnly);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlSlider
-
-class MIR_CORE_EXPORT CCtrlSlider : public CCtrlData
-{
- typedef CCtrlData CSuper;
-
- int m_wMin, m_wMax;
-
-protected:
- BOOL OnCommand(HWND hwndCtrl, WORD idCtrl, WORD idCode) override;
-
-public:
- CCtrlSlider(CDlgBase *dlg, int ctrlId, int max = 100, int min = 0);
-
- bool OnApply() override;
- void OnReset() override;
-
- int GetPosition() const;
- void SetPosition(int pos);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlSpin
-
-class MIR_CORE_EXPORT CCtrlSpin : public CCtrlData
-{
- typedef CCtrlData CSuper;
-
- WORD m_wMin, m_wMax, m_wCurr;
-
- BOOL OnNotify(int, NMHDR*) override;
-
-public:
- CCtrlSpin(CDlgBase *dlg, int ctrlId, WORD max = 100, WORD min = 0);
-
- bool OnApply() override;
- void OnReset() override;
-
- WORD GetPosition();
- void SetPosition(WORD pos);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlListBox
-
-class MIR_CORE_EXPORT CCtrlListBox : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
-public:
- CCtrlListBox(CDlgBase *dlg, int ctrlId);
-
- int AddString(const wchar_t *text, LPARAM data=0);
- void DeleteString(int index);
- int FindString(const wchar_t *str, int index = -1, bool exact = false);
- int GetCount() const;
- int GetCurSel() const;
- LPARAM GetItemData(int index) const;
- int GetItemRect(int index, RECT *pResult) const;
- wchar_t* GetItemText(int index) const;
- wchar_t* GetItemText(int index, wchar_t *buf, int size) const;
- bool GetSel(int index) const;
- int GetSelCount() const;
- int* GetSelItems(int *items, int count) const;
- int* GetSelItems() const;
- int InsertString(const wchar_t *text, int pos, LPARAM data=0);
- void ResetContent();
- int SelectString(const wchar_t *str);
- int SetCurSel(int index);
- void SetItemData(int index, LPARAM data);
- void SetItemHeight(int index, int iHeight);
- void SetSel(int index, bool sel = true);
-
- // Events
- CCallback<CCtrlListBox> OnDblClick;
- CCallback<CCtrlListBox> OnSelCancel;
- CCallback<CCtrlListBox> OnSelChange;
-
-protected:
- BOOL OnCommand(HWND hwndCtrl, WORD idCtrl, WORD idCode) override;
- void GetCaretPos(CContextMenuPos&) const override;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlCombo
-
-class MIR_CORE_EXPORT CCtrlCombo : public CCtrlData
-{
- typedef CCtrlData CSuper;
-
-public:
- CCtrlCombo(CDlgBase *dlg, int ctrlId);
-
- BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD idCode) override;
- void OnInit() override;
- bool OnApply() override;
- void OnReset() override;
-
- // returns item data associated with the selected item or -1
- LPARAM GetCurData() const;
-
- // selects line with userdata passed. returns index of this line or -1
- int SelectData(LPARAM data);
-
- // Control interface
- int AddString(const wchar_t *text, LPARAM data = 0);
- int AddStringA(const char *text, LPARAM data = 0);
- void DeleteString(int index);
- int FindString(const wchar_t *str, int index = -1, bool exact = false);
- int FindStringA(const char *str, int index = -1, bool exact = false);
- int GetCount() const;
- int GetCurSel() const;
- bool GetDroppedState() const;
- LPARAM GetItemData(int index) const;
- wchar_t* GetItemText(int index) const;
- wchar_t* GetItemText(int index, wchar_t *buf, int size) const;
- int InsertString(const wchar_t *text, int pos, LPARAM data=0);
- void ResetContent();
- int SelectString(const wchar_t *str);
- int SetCurSel(int index);
- void SetItemData(int index, LPARAM data);
- void ShowDropdown(bool show = true);
-
- // Events
- CCallback<CCtrlCombo> OnCloseup;
- CCallback<CCtrlCombo> OnDropdown;
- CCallback<CCtrlCombo> OnKillFocus;
- CCallback<CCtrlCombo> OnSelChanged;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlListView
-
-class MIR_CORE_EXPORT CCtrlListView : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
-public:
- CCtrlListView(CDlgBase *dlg, int ctrlId);
-
- // direction = -1 or 1. returns new item index
- int MoveItem(int idx, int direction);
-
- void SetCurSel(int idx);
-
- // Classic LV interface
- DWORD ApproximateViewRect(int cx, int cy, int iCount);
- void Arrange(UINT code);
- void CancelEditLabel();
- HIMAGELIST CreateDragImage(int iItem, LPPOINT lpptUpLeft);
- void DeleteAllItems();
- void DeleteColumn(int iCol);
- void DeleteItem(int iItem);
- HWND EditLabel(int iItem);
- int EnableGroupView(BOOL fEnable);
- BOOL EnsureVisible(int i, BOOL fPartialOK);
- int FindItem(int iStart, const LVFINDINFO *plvfi);
- COLORREF GetBkColor() const;
- void GetBkImage(LPLVBKIMAGE plvbki) const;
- UINT GetCallbackMask() const;
- BOOL GetCheckState(UINT iIndex) const;
- void GetColumn(int iCol, LPLVCOLUMN pcol) const;
- void GetColumnOrderArray(int iCount, int *lpiArray) const;
- int GetColumnWidth(int iCol) const;
- int GetCountPerPage() const;
- HWND GetEditControl() const;
- DWORD GetExtendedListViewStyle() const;
- INT GetFocusedGroup() const;
- int GetGroupCount() const;
- void GetGroupInfo(int iGroupId, PLVGROUP pgrp) const;
- void GetGroupInfoByIndex(int iIndex, PLVGROUP pgrp) const;
- void GetGroupMetrics(LVGROUPMETRICS *pGroupMetrics) const;
- UINT GetGroupState(UINT dwGroupId, UINT dwMask) const;
- HWND GetHeader() const;
- HCURSOR GetHotCursor() const;
- INT GetHotItem() const;
- DWORD GetHoverTime() const;
- HIMAGELIST GetImageList(int iImageList) const;
- BOOL GetInsertMark(LVINSERTMARK *plvim) const;
- COLORREF GetInsertMarkColor() const;
- int GetInsertMarkRect(LPRECT prc) const;
- BOOL GetISearchString(LPSTR lpsz) const;
- bool GetItem(LPLVITEM pitem) const;
- int GetItemCount() const;
- void GetItemPosition(int i, POINT *ppt) const;
- void GetItemRect(int i, RECT *prc, int code) const;
- DWORD GetItemSpacing(BOOL fSmall) const;
- UINT GetItemState(int i, UINT mask) const;
- void GetItemText(int iItem, int iSubItem, LPTSTR pszText, int cchTextMax) const;
- int GetNextItem(int iStart, UINT flags) const;
- BOOL GetNumberOfWorkAreas(LPUINT lpuWorkAreas) const;
- BOOL GetOrigin(LPPOINT lpptOrg) const;
- COLORREF GetOutlineColor() const;
- UINT GetSelectedColumn() const;
- UINT GetSelectedCount() const;
- INT GetSelectionMark() const;
- int GetStringWidth(LPCSTR psz) const;
- BOOL GetSubItemRect(int iItem, int iSubItem, int code, LPRECT lpRect) const;
- COLORREF GetTextBkColor() const;
- COLORREF GetTextColor() const;
- void GetTileInfo(PLVTILEINFO plvtinfo) const;
- void GetTileViewInfo(PLVTILEVIEWINFO plvtvinfo) const;
- HWND GetToolTips() const;
- int GetTopIndex() const;
- BOOL GetUnicodeFormat() const;
- DWORD GetView() const;
- BOOL GetViewRect(RECT *prc) const;
- void GetWorkAreas(INT nWorkAreas, LPRECT lprc) const;
- BOOL HasGroup(int dwGroupId);
- int HitTest(LPLVHITTESTINFO pinfo) const;
- int HitTestEx(LPLVHITTESTINFO pinfo);
- int InsertColumn(int iCol, const LPLVCOLUMN pcol);
- int InsertGroup(int index, PLVGROUP pgrp);
- void InsertGroupSorted(PLVINSERTGROUPSORTED structInsert);
- int InsertItem(const LPLVITEM pitem);
- BOOL InsertMarkHitTest(LPPOINT point, LVINSERTMARK *plvim);
- BOOL IsGroupViewEnabled();
- UINT IsItemVisible(UINT index);
- UINT MapIDToIndex(UINT id);
- UINT MapIndexToID(UINT index);
- BOOL RedrawItems(int iFirst, int iLast);
- void RemoveAllGroups();
- int RemoveGroup(int iGroupId);
- BOOL Scroll(int dx, int dy);
- BOOL SetBkColor(COLORREF clrBk);
- BOOL SetBkImage(LPLVBKIMAGE plvbki);
- BOOL SetCallbackMask(UINT mask);
- void SetCheckState(UINT iIndex, BOOL fCheck);
- BOOL SetColumn(int iCol, LPLVCOLUMN pcol);
- BOOL SetColumnOrderArray(int iCount, int *lpiArray);
- BOOL SetColumnWidth(int iCol, int cx);
- void SetExtendedListViewStyle(DWORD dwExStyle);
- void SetExtendedListViewStyleEx(DWORD dwExMask, DWORD dwExStyle);
- int SetGroupInfo(int iGroupId, PLVGROUP pgrp);
- void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics);
- void SetGroupState(UINT dwGroupId, UINT dwMask, UINT dwState);
- HCURSOR SetHotCursor(HCURSOR hCursor);
- INT SetHotItem(INT iIndex);
- void SetHoverTime(DWORD dwHoverTime);
- DWORD SetIconSpacing(int cx, int cy);
- HIMAGELIST SetImageList(HIMAGELIST himl, int iImageList);
- BOOL SetInfoTip(PLVSETINFOTIP plvSetInfoTip);
- BOOL SetInsertMark(LVINSERTMARK *plvim);
- COLORREF SetInsertMarkColor(COLORREF color);
- BOOL SetItem(const LPLVITEM pitem);
- void SetItemCount(int cItems);
- void SetItemCountEx(int cItems, DWORD dwFlags);
- BOOL SetItemPosition(int i, int x, int y);
- void SetItemPosition32(int iItem, int x, int y);
- void SetItemState(int i, UINT state, UINT mask);
- void SetItemText(int i, int iSubItem, const wchar_t *pszText);
- COLORREF SetOutlineColor(COLORREF color);
- void SetSelectedColumn(int iCol);
- INT SetSelectionMark(INT iIndex);
- BOOL SetTextBkColor(COLORREF clrText);
- BOOL SetTextColor(COLORREF clrText);
- BOOL SetTileInfo(PLVTILEINFO plvtinfo);
- BOOL SetTileViewInfo(PLVTILEVIEWINFO plvtvinfo);
- HWND SetToolTips(HWND ToolTip);
- BOOL SetUnicodeFormat(BOOL fUnicode);
- int SetView(DWORD iView);
- void SetWorkAreas(INT nWorkAreas, LPRECT lprc);
- int SortGroups(PFNLVGROUPCOMPARE pfnGroupCompare, LPVOID plv);
- BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort);
- BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort);
- INT SubItemHitTest(LPLVHITTESTINFO pInfo) const;
- INT SubItemHitTestEx(LPLVHITTESTINFO plvhti);
- BOOL Update(int iItem);
-
- // Additional APIs
- HIMAGELIST CreateImageList(int iImageList);
- void AddColumn(int iSubItem, const wchar_t *name, int cx);
- void AddGroup(int iGroupId, const wchar_t *name);
- int AddItem(const wchar_t *text, int iIcon, LPARAM lParam = 0, int iGroupId = -1);
- void SetItem(int iItem, int iSubItem, const wchar_t *text, int iIcon = -1);
- LPARAM GetItemData(int iItem) const;
-
- // Events
- struct TEventInfo {
- CCtrlListView *treeviewctrl;
- union {
- NMHDR *nmhdr;
- NMLISTVIEW *nmlv;
- NMLVDISPINFO *nmlvdi;
- NMLVSCROLL *nmlvscr;
- NMLVGETINFOTIP *nmlvit;
- NMLVFINDITEM *nmlvfi;
- NMITEMACTIVATE *nmlvia;
- NMLVKEYDOWN *nmlvkey;
- NMLVCUSTOMDRAW *nmcd;
- };
- };
-
- CCallback<TEventInfo> OnBeginDrag;
- CCallback<TEventInfo> OnBeginLabelEdit;
- CCallback<TEventInfo> OnBeginRDrag;
- CCallback<TEventInfo> OnBeginScroll;
- CCallback<TEventInfo> OnColumnClick;
- CCallback<TEventInfo> OnCustomDraw;
- CCallback<TEventInfo> OnDeleteAllItems;
- CCallback<TEventInfo> OnDeleteItem;
- CCallback<TEventInfo> OnClick;
- CCallback<TEventInfo> OnDoubleClick;
- CCallback<TEventInfo> OnEndLabelEdit;
- CCallback<TEventInfo> OnEndScroll;
- CCallback<TEventInfo> OnGetDispInfo;
- CCallback<TEventInfo> OnGetInfoTip;
- CCallback<TEventInfo> OnHotTrack;
- CCallback<TEventInfo> OnIncrementalSearch;
- CCallback<TEventInfo> OnInsertItem;
- CCallback<TEventInfo> OnItemActivate;
- CCallback<TEventInfo> OnItemChanged;
- CCallback<TEventInfo> OnItemChanging;
- CCallback<TEventInfo> OnKeyDown;
- CCallback<TEventInfo> OnMarqueeBegin;
- CCallback<TEventInfo> OnSetDispInfo;
-
-protected:
- BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
- void GetCaretPos(CContextMenuPos&) const override;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlTreeView
-
-#undef GetNextSibling
-#undef GetPrevSibling
-
-#define MTREE_CHECKBOX 0x0001
-#define MTREE_DND 0x0002
-#define MTREE_MULTISELECT 0x0004
-
-class MIR_CORE_EXPORT CCtrlTreeView : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
- HTREEITEM MoveItemAbove(HTREEITEM hItem, HTREEITEM hInsertAfter, HTREEITEM hParent);
-
-public:
- CCtrlTreeView(CDlgBase *dlg, int ctrlId);
-
- void SetFlags(uint32_t dwFlags); // MTREE_* combination
-
- // Classic TV interface
- HIMAGELIST CreateDragImage(HTREEITEM hItem);
- void DeleteAllItems();
- void DeleteItem(HTREEITEM hItem);
- HWND EditLabel(HTREEITEM hItem);
- void EndEditLabelNow(BOOL cancel);
- void EnsureVisible(HTREEITEM hItem);
- void Expand(HTREEITEM hItem, DWORD flag);
- COLORREF GetBkColor() const;
- DWORD GetCheckState(HTREEITEM hItem) const;
- HTREEITEM GetChild(HTREEITEM hItem) const;
- int GetCount() const;
- HTREEITEM GetDropHilight() const;
- HWND GetEditControl() const;
- HTREEITEM GetFirstVisible() const;
- HIMAGELIST GetImageList(int iImage) const;
- int GetIndent() const;
- COLORREF GetInsertMarkColor() const;
- bool GetItem(TVITEMEX *tvi) const;
- int GetItemHeight() const;
- void GetItemRect(HTREEITEM hItem, RECT *rcItem, BOOL fItemRect) const;
- DWORD GetItemState(HTREEITEM hItem, DWORD stateMask) const;
- HTREEITEM GetLastVisible() const;
- COLORREF GetLineColor() const;
- HTREEITEM GetNextItem(HTREEITEM hItem, DWORD flag) const;
- HTREEITEM GetNextSibling(HTREEITEM hItem) const;
- HTREEITEM GetNextVisible(HTREEITEM hItem) const;
- HTREEITEM GetParent(HTREEITEM hItem) const;
- HTREEITEM GetPrevSibling(HTREEITEM hItem) const;
- HTREEITEM GetPrevVisible(HTREEITEM hItem) const;
- HTREEITEM GetRoot() const;
- DWORD GetScrollTime() const;
- HTREEITEM GetSelection() const;
- COLORREF GetTextColor() const;
- HWND GetToolTips() const;
- BOOL GetUnicodeFormat() const;
- unsigned GetVisibleCount() const;
- HTREEITEM HitTest(TVHITTESTINFO *hti) const;
- HTREEITEM InsertItem(TVINSERTSTRUCT *tvis);
- void Select(HTREEITEM hItem, DWORD flag);
- void SelectDropTarget(HTREEITEM hItem);
- void SelectItem(HTREEITEM hItem);
- void SelectSetFirstVisible(HTREEITEM hItem);
- COLORREF SetBkColor(COLORREF clBack);
- void SetCheckState(HTREEITEM hItem, DWORD state);
- void SetImageList(HIMAGELIST hIml, int iImage);
- void SetIndent(int iIndent);
- void SetInsertMark(HTREEITEM hItem, BOOL fAfter);
- COLORREF SetInsertMarkColor(COLORREF clMark);
- void SetItem(TVITEMEX *tvi);
- void SetItemHeight(short cyItem);
- void SetItemState(HTREEITEM hItem, DWORD state, DWORD stateMask);
- COLORREF SetLineColor(COLORREF clLine);
- void SetScrollTime(UINT uMaxScrollTime);
- COLORREF SetTextColor(COLORREF clText);
- HWND SetToolTips(HWND hwndToolTips);
- BOOL SetUnicodeFormat(BOOL fUnicode);
- void SortChildren(HTREEITEM hItem, BOOL fRecurse);
- void SortChildrenCB(TVSORTCB *cb, BOOL fRecurse);
-
- // Additional stuff
- void TranslateItem(HTREEITEM hItem);
- void TranslateTree();
- HTREEITEM FindNamedItem(HTREEITEM hItem, const wchar_t *name);
- void GetItem(HTREEITEM hItem, TVITEMEX *tvi) const;
- void GetItem(HTREEITEM hItem, TVITEMEX *tvi, wchar_t *szText, int iTextLength) const;
- void InvertCheck(HTREEITEM hItem);
-
- bool IsSelected(HTREEITEM hItem);
- int GetNumSelected();
- void GetSelected(LIST<_TREEITEM> &selected);
-
- void Select(HTREEITEM hItem);
- void Select(LIST<_TREEITEM> &selected);
- void SelectAll();
- void SelectRange(HTREEITEM hStart, HTREEITEM hEnd);
-
- void Unselect(HTREEITEM hItem);
- void UnselectAll();
-
- void DropHilite(HTREEITEM hItem);
- void DropUnhilite(HTREEITEM hItem);
-
- // Events
- struct TEventInfo {
- CCtrlTreeView *treeviewctrl;
- union {
- NMHDR *nmhdr;
- NMTREEVIEW *nmtv;
- NMTVKEYDOWN *nmtvkey;
- NMTVDISPINFO *nmtvdi;
- NMTVGETINFOTIP *nmtvit;
- NMTVCUSTOMDRAW *nmcd;
- HTREEITEM hItem; // for OnItemChanged
- };
- };
-
- CCallback<TEventInfo> OnBeginDrag;
- CCallback<TEventInfo> OnBeginLabelEdit;
- CCallback<TEventInfo> OnBeginRDrag;
- CCallback<TEventInfo> OnCustomDraw;
- CCallback<TEventInfo> OnDeleteItem;
- CCallback<TEventInfo> OnEndLabelEdit;
- CCallback<TEventInfo> OnGetDispInfo;
- CCallback<TEventInfo> OnGetInfoTip;
- CCallback<TEventInfo> OnItemChanged;
- CCallback<TEventInfo> OnItemExpanded;
- CCallback<TEventInfo> OnItemExpanding;
- CCallback<TEventInfo> OnKeyDown;
- CCallback<TEventInfo> OnRightClick;
- CCallback<TEventInfo> OnSelChanged;
- CCallback<TEventInfo> OnSelChanging;
- CCallback<TEventInfo> OnSetDispInfo;
- CCallback<TEventInfo> OnSingleExpand;
-
-protected:
- void OnInit() override;
- void OnDestroy() override;
- BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
-
- void GetCaretPos(CContextMenuPos&) const override;
- LRESULT CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
-
- union {
- uint32_t m_dwFlags;
- struct {
- bool m_bDndEnabled : 1;
- bool m_bDragging : 1;
- bool m_bCheckBox : 1;
- bool m_bMultiSelect : 1;
- };
- };
- HTREEITEM m_hDragItem; // valid if m_bDragging == true
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlTreeOpts - array of options with sections
-
-class MIR_CORE_EXPORT CCtrlTreeOpts : public CCtrlTreeView
-{
- typedef CCtrlTreeView CSuper;
-
-public:
- CCtrlTreeOpts(CDlgBase *dlg, int ctrlId);
- ~CCtrlTreeOpts();
-
- void AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, CMOption<bool> &option);
-
- BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
- void OnDestroy() override;
- void OnInit() override;
- bool OnApply() override;
-
-protected:
- struct COptionsItem
- {
- const wchar_t *m_pwszSection, *m_pwszName;
-
- CMOption<bool> *m_option;
-
- HTREEITEM m_hItem = nullptr;
-
- COptionsItem(const wchar_t *pwszSection, const wchar_t *pwszName, CMOption<bool> &option) :
- m_pwszSection(pwszSection),
- m_pwszName(pwszName),
- m_option(&option)
- {
- }
- };
-
- OBJLIST<COptionsItem> m_options;
-
- void ProcessItemClick(HTREEITEM hti);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CCtrlPages
-
-#define PSN_INFOCHANGED 1
-#define PSN_PARAMCHANGED 2
-
-// force-send a PSN_INFOCHANGED to all pages
-#define PSM_FORCECHANGED (WM_USER+100)
-
-class MIR_CORE_EXPORT CCtrlPages : public CCtrlBase
-{
- typedef CCtrlBase CSuper;
-
- HIMAGELIST m_hIml;
- CDlgBase *m_pActivePage;
- int m_numRows = 1;
-
- struct TPageInfo;
- void InsertPage(TPageInfo *pPage);
- void ShowPage(CDlgBase *pDlg);
-
- void CheckRowCount();
- TPageInfo* GetCurrPage();
- TPageInfo* GetItemPage(int iPage);
- LIST<TPageInfo> m_pages;
-
-public:
- CCtrlPages(CDlgBase *dlg, int ctrlId);
-
- void AddPage(const wchar_t *ptszName, HICON hIcon, CDlgBase *pDlg);
- void ActivatePage(int iPage);
- int GetCount(void);
- int GetDlgIndex(CDlgBase*);
- void RemovePage(int iPage);
- void SwapPages(int idx1, int idx2);
-
- CDlgBase* GetNthPage(int iPage);
-
- __forceinline CDlgBase* GetActivePage() const
- { return m_pActivePage;
- }
-
-protected:
- BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
-
- void OnInit() override;
- void OnDestroy() override;
-
- bool OnApply() override;
- void OnReset() override;
-
- LRESULT CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CProtoDlgBase
-
-#define WM_PROTO_REFRESH (WM_USER + 100)
-#define WM_PROTO_CHECK_ONLINE (WM_USER + 101)
-#define WM_PROTO_ACTIVATE (WM_USER + 102)
-#define WM_PROTO_LAST (WM_USER + 200)
-
-struct PROTO_INTERFACE;
-
-class MIR_APP_EXPORT CProtoIntDlgBase : public CDlgBase
-{
- typedef CDlgBase CSuper;
-
-public:
- CProtoIntDlgBase(PROTO_INTERFACE *proto, int idDialog);
-
- void CreateLink(CCtrlData &ctrl, const char *szSetting, BYTE type, DWORD iValue);
- void CreateLink(CCtrlData &ctrl, const char *szSetting, wchar_t *szValue);
-
- template<class T>
- __inline void CreateLink(CCtrlData &ctrl, CMOption<T> &option)
- {
- ctrl.CreateDbLink(new CMOptionLink<T>(option));
- }
-
- __inline PROTO_INTERFACE *GetProtoInterface() { return m_proto_interface; }
-
- void SetStatusText(const wchar_t *statusText);
-
-protected:
- PROTO_INTERFACE *m_proto_interface;
- HWND m_hwndStatus = nullptr;
-
- INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
-
- virtual void OnProtoRefresh(WPARAM, LPARAM);
- virtual void OnProtoActivate(WPARAM, LPARAM);
- virtual void OnProtoCheckOnline(WPARAM, LPARAM);
-
-private:
- void UpdateStatusBar();
-};
-
-template<typename TProto>
-class CProtoDlgBase : public CProtoIntDlgBase
-{
- typedef CProtoIntDlgBase CSuper;
-
-public:
- __inline CProtoDlgBase<TProto>(TProto *proto, int idDialog) :
- CProtoIntDlgBase(proto, idDialog),
- m_proto(proto)
- {
- }
-
- __inline TProto *GetProto() { return m_proto; }
-
-protected:
- TProto* m_proto;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Safe open/close dialogs
-#define UI_SAFE_OPEN(dlgClass, dlgPtr) \
- { \
- if (dlgPtr) \
- { \
- SetForegroundWindow((dlgPtr)->GetHwnd()); \
- } else \
- { \
- (dlgPtr) = new dlgClass(this); \
- (dlgPtr)->Show(); \
- } \
- }
-
-#define UI_SAFE_OPEN_EX(dlgClass, dlgPtr, dlgLocal) \
- if (dlgPtr) \
- { \
- ::SetForegroundWindow((dlgPtr)->GetHwnd()); \
- } else \
- { \
- (dlgPtr) = new dlgClass(this); \
- (dlgPtr)->Show(); \
- } \
- dlgClass *dlgLocal = (dlgClass *)(dlgPtr);
-
-#define UI_SAFE_CLOSE(dlg) \
- { \
- if (dlg) { \
- (dlg)->Close(); \
- (dlg) = NULL; \
- } \
- }
-
-#define UI_SAFE_CLOSE_HWND(hwnd) \
- { \
- if (hwnd) { \
- ::SendMessage((hwnd), WM_CLOSE, 0, 0); \
- (hwnd) = NULL; \
- } \
- }
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// NULL-Safe dialog notifications
-#define UI_SAFE_NOTIFY(dlg, msg) \
- { \
- if (dlg) \
- ::SendMessage((dlg)->GetHwnd(), msg, 0, 0); \
- }
-
-#define UI_SAFE_NOTIFY_HWND(hwnd, msg) \
- { \
- if (hwnd) \
- ::SendMessage((hwnd), msg, 0, 0); \
- }
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Define message maps
-#define UI_MESSAGE_MAP(dlgClass, baseDlgClass) \
- typedef baseDlgClass CMessageMapSuperClass; \
- virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) \
- { \
- switch (msg) \
- { \
- case 0: \
- break /* just to handle ";" symbol after macro */
-
-#define UI_MESSAGE(msg, proc) \
- case msg: \
- proc(msg, wParam, lParam); \
- break
-
-#define UI_MESSAGE_EX(msg, func) \
- case msg: \
- return func(msg, wParam, lParam)
-
-#define UI_POSTPROCESS_MESSAGE(msg, proc) \
- case msg: \
- CMessageMapSuperClass::DlgProc(msg, wParam, lParam); \
- return FALSE
-
-#define UI_POSTPROCESS_MESSAGE_EX(msg, func) \
- case msg: \
- CMessageMapSuperClass::DlgProc(msg, wParam, lParam); \
- return func(msg, wParam, lParam)
-
-#define UI_MESSAGE_MAP_END() \
- } \
- return CMessageMapSuperClass::DlgProc(msg, wParam, lParam); \
- }
-
-#endif // __M_GUI_H
+/*
+
+Jabber Protocol Plugin for Miranda NG
+
+Copyright (c) 2002-04 Santithorn Bunchua
+Copyright (c) 2005-12 George Hazan
+Copyright (c) 2007-09 Maxim Mluhov
+Copyright (c) 2007-09 Victor Pavlychko
+Copyright (C) 2012-21 Miranda NG team
+
+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.
+
+*/
+
+#pragma once
+
+#ifndef __M_GUI_H
+#define __M_GUI_H
+
+#ifdef _MSC_VER
+#include <CommCtrl.h>
+#endif // _WINDOWS
+
+#include <m_system.h>
+#include <m_protoint.h>
+#include <m_clc.h>
+
+#pragma warning(disable:4355 4251 4481)
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// helpers for the option's visualization
+
+template<int Size>
+struct CMDBTraits
+{
+};
+
+template<>
+struct CMDBTraits<1>
+{
+ typedef BYTE DBType;
+ enum { DBTypeId = DBVT_BYTE };
+ static __forceinline DBType Get(const char *szModule, const char *szSetting, DBType value)
+ {
+ return db_get_b(0, szModule, szSetting, value);
+ }
+ static __forceinline void Set(const char *szModule, const char *szSetting, DBType value)
+ {
+ db_set_b(0, szModule, szSetting, value);
+ }
+};
+
+template<>
+struct CMDBTraits<2>
+{
+ typedef WORD DBType;
+ enum { DBTypeId = DBVT_WORD };
+ static __forceinline DBType Get(const char *szModule, const char *szSetting, DBType value)
+ {
+ return db_get_w(0, szModule, szSetting, value);
+ }
+ static __forceinline void Set(const char *szModule, const char *szSetting, DBType value)
+ {
+ db_set_w(0, szModule, szSetting, value);
+ }
+};
+
+template<>
+struct CMDBTraits<4>
+{
+ typedef DWORD DBType;
+ enum { DBTypeId = DBVT_DWORD };
+ static __forceinline DBType Get(const char *szModule, const char *szSetting, DBType value)
+ {
+ return db_get_dw(0, szModule, szSetting, value);
+ }
+ static __forceinline void Set(const char *szModule, const char *szSetting, DBType value)
+ {
+ db_set_dw(0, szModule, szSetting, value);
+ }
+};
+
+template<>
+struct CMDBTraits<8>
+{
+ typedef DWORD DBType;
+ enum { DBTypeId = DBVT_DWORD };
+ static __forceinline DBType Get(const char *szModule, const char *szSetting, DBType value)
+ {
+ return db_get_dw(0, szModule, szSetting, value);
+ }
+ static __forceinline void Set(const char *szModule, const char *szSetting, DBType value)
+ {
+ db_set_dw(0, szModule, szSetting, value);
+ }
+};
+
+class CMOptionBase : public MNonCopyable
+{
+public:
+ __forceinline const char* GetDBModuleName() const { return m_szModuleName; }
+ __forceinline const char* GetDBSettingName() const { return m_szSetting; }
+
+protected:
+ __forceinline CMOptionBase(PROTO_INTERFACE *proto, const char *szSetting) :
+ m_szModuleName(proto->m_szModuleName), m_szSetting(szSetting)
+ {}
+
+ __forceinline CMOptionBase(const char *module, const char *szSetting) :
+ m_szModuleName(module), m_szSetting(szSetting)
+ {}
+
+ const char *m_szModuleName;
+ const char *m_szSetting;
+};
+
+template<class T>
+class CMOption : public CMOptionBase
+{
+public:
+ typedef T Type;
+
+ __forceinline CMOption(PROTO_INTERFACE *proto, const char *szSetting, Type defValue) :
+ CMOptionBase(proto, szSetting), m_default(defValue)
+ {}
+
+ __forceinline CMOption(const char *szModule, const char *szSetting, Type defValue) :
+ CMOptionBase(szModule, szSetting), m_default(defValue)
+ {}
+
+ __forceinline Type Default() const
+ {
+ return m_default;
+ }
+
+ __forceinline operator Type()
+ {
+ return (Type)CMDBTraits<sizeof(Type)>::Get(m_szModuleName, m_szSetting, m_default);
+ }
+
+ __forceinline Type operator= (Type value)
+ {
+ #ifdef _MSC_VER
+ CMDBTraits<sizeof(Type)>::Set(m_szModuleName, m_szSetting, (CMDBTraits<sizeof(Type)>::DBType)value);
+ #else
+ CMDBTraits<sizeof(Type)>::Set(m_szModuleName, m_szSetting, value);
+ #endif
+ return value;
+ }
+
+private:
+ Type m_default;
+};
+
+template<>
+class CMOption<char*> : public CMOptionBase
+{
+public:
+
+ typedef char Type;
+
+ __forceinline CMOption(PROTO_INTERFACE *proto, const char *szSetting, const Type *defValue = nullptr) :
+ CMOptionBase(proto, szSetting), m_default(defValue)
+ {}
+
+ __forceinline CMOption(const char *szModule, const char *szSetting, const Type *defValue = nullptr) :
+ CMOptionBase(szModule, szSetting), m_default(defValue)
+ {}
+
+ __forceinline const Type* Default() const
+ {
+ return m_default;
+ }
+
+ __forceinline operator Type*()
+ {
+ m_value = db_get_sa(0, m_szModuleName, m_szSetting);
+ if (!m_value) m_value = mir_strdup(m_default);
+ return m_value;
+ }
+
+ __forceinline Type* operator= (Type *value)
+ {
+ db_set_s(0, m_szModuleName, m_szSetting, value);
+ return value;
+ }
+
+private:
+ const Type *m_default;
+ mir_ptr<Type> m_value;
+};
+
+template<>
+class CMOption<wchar_t*> : public CMOptionBase
+{
+public:
+
+ typedef wchar_t Type;
+
+ __forceinline CMOption(PROTO_INTERFACE *proto, const char *szSetting, const Type *defValue = nullptr) :
+ CMOptionBase(proto, szSetting), m_default(defValue)
+ {}
+
+ __forceinline CMOption(const char *szModule, const char *szSetting, const Type *defValue = nullptr) :
+ CMOptionBase(szModule, szSetting), m_default(defValue)
+ {}
+
+ __forceinline const Type* Default() const
+ {
+ return m_default;
+ }
+
+ __forceinline operator Type*()
+ {
+ m_value = db_get_wsa(0, m_szModuleName, m_szSetting);
+ if (!m_value) m_value = mir_wstrdup(m_default);
+ return m_value;
+ }
+
+ __forceinline const Type* operator= (const Type *value)
+ {
+ db_set_ws(0, m_szModuleName, m_szSetting, value);
+ return value;
+ }
+
+private:
+ const Type *m_default;
+ mir_ptr<Type> m_value;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CDbLink
+
+class MIR_CORE_EXPORT CDataLink
+{
+protected:
+ BYTE m_type;
+
+public:
+ __inline CDataLink(BYTE type) : m_type(type) {}
+ virtual ~CDataLink() {}
+
+ __inline BYTE GetDataType() const { return m_type; }
+
+ virtual DWORD LoadInt() = 0;
+ virtual void SaveInt(DWORD value) = 0;
+
+ virtual wchar_t* LoadText() = 0;
+ virtual void SaveText(wchar_t *value) = 0;
+};
+
+class MIR_CORE_EXPORT CDbLink : public CDataLink
+{
+ char *m_szModule;
+ char *m_szSetting;
+
+ DWORD m_iDefault;
+ wchar_t *m_szDefault;
+
+ DBVARIANT dbv;
+
+public:
+ CDbLink(const char *szModule, const char *szSetting, BYTE type, DWORD iValue);
+ CDbLink(const char *szModule, const char *szSetting, BYTE type, wchar_t *szValue);
+ ~CDbLink();
+
+ DWORD LoadInt() override;
+ void SaveInt(DWORD value) override;
+
+ wchar_t* LoadText() override;
+ void SaveText(wchar_t *value) override;
+};
+
+template<class T>
+class CMOptionLink : public CDataLink
+{
+private:
+ CMOption<T> *m_option;
+
+public:
+ __forceinline CMOptionLink(CMOption<T> &option) :
+ CDataLink(CMDBTraits<sizeof(T)>::DBTypeId), m_option(&option)
+ {}
+
+ __forceinline DWORD LoadInt() override { return (DWORD)(T)*m_option; }
+ __forceinline void SaveInt(DWORD value) override { *m_option = (T)value; }
+
+ __forceinline wchar_t* LoadText() override { return nullptr; }
+ __forceinline void SaveText(wchar_t*) override {}
+};
+
+template<>
+class CMOptionLink<wchar_t*> : public CDataLink
+{
+private:
+ typedef wchar_t *T;
+ CMOption<T> *m_option;
+
+public:
+ __forceinline CMOptionLink(CMOption<T> &option) :
+ CDataLink(DBVT_WCHAR), m_option(&option)
+ {}
+
+ __forceinline DWORD LoadInt() override { return 0; }
+ __forceinline void SaveInt(DWORD) override { }
+
+ __forceinline wchar_t* LoadText() override { return *m_option; }
+ __forceinline void SaveText(wchar_t *value) override { *m_option = value; }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CDlgBase - base dialog class
+
+class MIR_CORE_EXPORT CDlgBase
+{
+ friend class CTimer;
+ friend class CCtrlBase;
+ friend class CCtrlData;
+
+public:
+ CDlgBase(class CMPluginBase &pPlug, int idDialog);
+ virtual ~CDlgBase();
+
+ // general utilities
+ void Close();
+ void Resize();
+ void Create();
+ void Show(int nCmdShow = SW_SHOW);
+ int DoModal();
+ void EndModal(INT_PTR nResult);
+
+ class CCtrlBase* FindControl(int idCtrl);
+ class CCtrlBase* FindControl(HWND hwnd);
+
+ void SetCaption(const wchar_t *ptszCaption);
+ void SetDraw(bool bEnable);
+ void NotifyChange(void); // sends a notification to a parent window
+
+ __forceinline HINSTANCE GetInst() const { return m_pPlugin.getInst(); }
+ __forceinline HWND GetHwnd() const { return m_hwnd; }
+ __forceinline void Hide() { Show(SW_HIDE); }
+ __forceinline bool IsInitialized() const { return m_bInitialized; }
+ __forceinline void SetMinSize(int x, int y) { m_iMinWidth = x, m_iMinHeight = y; }
+ __forceinline void SetParent(HWND hwnd) { m_hwndParent = hwnd; }
+
+ __forceinline CCtrlBase* operator[](int iControlId) { return FindControl(iControlId); }
+
+ static CDlgBase* Find(HWND hwnd);
+
+protected:
+ HWND m_hwnd = nullptr; // must be the first data item
+ HWND m_hwndParent = nullptr;
+ int m_idDialog;
+
+ bool m_isModal = false;
+ bool m_bInitialized = false;
+ bool m_forceResizable = false;
+ bool m_bSucceeded = false; // was IDOK pressed or not
+ bool m_bExiting = false; // window received WM_CLOSE and gonna die soon
+
+ enum { CLOSE_ON_OK = 0x1, CLOSE_ON_CANCEL = 0x2 };
+ BYTE m_autoClose; // automatically close dialog on IDOK/CANCEL commands. default: CLOSE_ON_OK|CLOSE_ON_CANCEL
+
+ CMPluginBase &m_pPlugin;
+
+ // override this handlers to provide custom functionality
+ // general messages
+ virtual bool OnInitDialog();
+ virtual bool OnApply();
+ virtual bool OnClose();
+ virtual void OnDestroy();
+
+ virtual void OnTimer(class CTimer*);
+
+ // miranda-related stuff
+ virtual int Resizer(UTILRESIZECONTROL *urc);
+ virtual void OnReset();
+ virtual void OnChange();
+
+ // main dialog procedure
+ virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam);
+
+ CCallback<void> m_OnFinishWizard;
+
+ // register controls
+ void AddControl(CCtrlBase *ctrl);
+ void RemoveControl(CCtrlBase *ctrl);
+
+ // timers
+ void AddTimer(CTimer *timer);
+ void RemoveTimer(UINT_PTR idEvent);
+
+ // options support
+ void CreateLink(class CCtrlData& ctrl, const char *szSetting, BYTE type, DWORD iValue);
+ void CreateLink(class CCtrlData& ctrl, const char *szSetting, wchar_t *szValue);
+
+ template<class T>
+ __inline void CreateLink(CCtrlData& ctrl, CMOption<T> &option)
+ {
+ ctrl.CreateDbLink(new CMOptionLink<T>(option));
+ }
+
+ // win32 stuff
+ void ThemeDialogBackground(BOOL tabbed);
+
+private:
+ LIST<CTimer> m_timers;
+ LIST<CCtrlBase> m_controls;
+
+ void NotifyControls(void (CCtrlBase::*fn)());
+ bool VerifyControls(bool (CCtrlBase::*fn)());
+
+ CTimer* FindTimer(int idEvent);
+ int m_iMinWidth = -1, m_iMinHeight = -1;
+
+ static BOOL CALLBACK GlobalFieldEnum(HWND hwnd, LPARAM lParam);
+ static INT_PTR CALLBACK GlobalDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static int GlobalDlgResizer(HWND hwnd, LPARAM lParam, UTILRESIZECONTROL *urc);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CTimer
+
+class MIR_CORE_EXPORT CTimer
+{
+ friend class CDlgBase;
+
+public:
+ CTimer(CDlgBase* wnd, UINT_PTR idEvent);
+ ~CTimer();
+
+ __forceinline UINT_PTR GetEventId() const { return m_idEvent; }
+ __forceinline HWND GetHwnd() const { return m_wnd->GetHwnd(); }
+
+ virtual BOOL OnTimer();
+
+ void Start(int elapse);
+ bool Stop(); // returns true if timer was active
+
+ void StartSafe(int elapse);
+ void StopSafe();
+
+ CCallback<CTimer> OnEvent;
+
+protected:
+ UINT_PTR m_idEvent;
+ CDlgBase* m_wnd;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlBase
+
+struct CContextMenuPos
+{
+ const CCtrlBase *pCtrl;
+ POINT pt;
+ union {
+ int iCurr; // int for list boxes
+ HTREEITEM hItem;
+ };
+};
+
+class MIR_CORE_EXPORT CCtrlBase
+{
+ friend class CDlgBase;
+
+ __forceinline CCtrlBase(const CCtrlBase&) = delete;
+ __forceinline CCtrlBase& operator=(const CCtrlBase&) = delete;
+
+public:
+ CCtrlBase(CDlgBase *wnd, int idCtrl);
+ virtual ~CCtrlBase();
+
+ __forceinline HWND GetHwnd() const { return m_hwnd; }
+ __forceinline int GetCtrlId() const { return m_idCtrl; }
+ __forceinline CDlgBase *GetParent() const { return m_parentWnd; }
+ __forceinline bool IsChanged() const { return m_bChanged; }
+ __forceinline void SetSilent(bool bSilent = true) { m_bSilent = bSilent; }
+ __forceinline void UseSystemColors() { m_bUseSystemColors = true; }
+
+ void Show(bool bShow = true);
+ __forceinline void Hide() { Show(false); }
+
+ void Enable(bool bIsEnable = true);
+ __forceinline void Disable() { Enable(false); }
+ bool Enabled(void) const;
+
+ void NotifyChange();
+ void SetDraw(bool bEnable);
+
+ INT_PTR SendMsg(UINT Msg, WPARAM wParam, LPARAM lParam) const;
+
+ void SetText(const wchar_t *text);
+ void SetTextA(const char *text);
+ void SetInt(int value);
+
+ wchar_t* GetText() const;
+ char* GetTextA() const;
+ char* GetTextU() const;
+
+ wchar_t* GetText(wchar_t *buf, size_t size) const;
+ char* GetTextA(char *buf, size_t size) const;
+ char* GetTextU(char *buf, size_t size) const;
+
+ int GetInt() const;
+
+ virtual BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD /*idCode*/) { return FALSE; }
+ virtual BOOL OnNotify(int /*idCtrl*/, struct NMHDR* /*pnmh*/) { return FALSE; }
+
+ virtual BOOL OnMeasureItem(struct MEASUREITEMSTRUCT*) { return FALSE; }
+ virtual BOOL OnDrawItem(struct DRAWITEMSTRUCT*) { return FALSE; }
+ virtual BOOL OnDeleteItem(struct DELETEITEMSTRUCT*) { return FALSE; }
+
+ virtual void OnInit();
+ virtual void OnDestroy();
+
+ virtual bool OnApply();
+ virtual void OnReset();
+
+protected:
+ HWND m_hwnd = nullptr; // must be the first data item
+ int m_idCtrl;
+ CDlgBase* m_parentWnd;
+ bool m_bChanged = false, m_bSilent = false, m_bUseSystemColors = false, m_bNotifiable = false;
+
+public:
+ CCallback<CCtrlBase> OnChange;
+ CCallback<CContextMenuPos> OnBuildMenu;
+
+protected:
+ virtual void GetCaretPos(CContextMenuPos&) const;
+ virtual INT_PTR CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam);
+
+ void Subclass();
+ void Unsubclass();
+
+private:
+ static INT_PTR CALLBACK GlobalSubclassWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlLabel
+
+class MIR_CORE_EXPORT CCtrlLabel : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+public:
+ CCtrlLabel(CDlgBase *dlg, int ctrlId);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlButton
+
+class MIR_CORE_EXPORT CCtrlButton : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+public:
+ CCtrlButton(CDlgBase *dlg, int ctrlId);
+
+ BOOL OnCommand(HWND hwndCtrl, WORD idCtrl, WORD idCode) override;
+
+ CCallback<CCtrlButton> OnClick;
+
+ void Click();
+ bool IsPushed() const;
+ void Push(bool bPushed);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlMButton
+
+class MIR_CORE_EXPORT CCtrlMButton : public CCtrlButton
+{
+ typedef CCtrlButton CSuper;
+
+public:
+ CCtrlMButton(CDlgBase *dlg, int ctrlId, HICON hIcon, const char* tooltip);
+ CCtrlMButton(CDlgBase *dlg, int ctrlId, int iCoreIcon, const char* tooltip);
+ ~CCtrlMButton();
+
+ void MakeFlat();
+ void MakePush();
+
+ void OnInit() override;
+
+protected:
+ HICON m_hIcon;
+ const char* m_toolTip;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CSplitter
+
+class MIR_CORE_EXPORT CSplitter : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+public:
+ CSplitter(CDlgBase *dlg, int ctrlId);
+
+ __forceinline int GetPos() const { return m_iPosition; }
+
+protected:
+ INT_PTR CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
+ void OnInit() override;
+
+ int m_iPosition;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlHyperlink
+
+class MIR_CORE_EXPORT CCtrlHyperlink : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+public:
+ CCtrlHyperlink(CDlgBase *dlg, int ctrlId, const char* url = nullptr);
+
+ BOOL OnCommand(HWND hwndCtrl, WORD idCtrl, WORD idCode) override;
+
+ CCallback<CCtrlHyperlink> OnClick;
+
+ void SetUrl(const char *url);
+ const char *GetUrl();
+
+protected:
+ const char* m_url;
+
+ void Default_OnClick(CCtrlHyperlink*);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CProgress
+
+class MIR_CORE_EXPORT CCtrlProgress : public CCtrlBase
+{
+public:
+ CCtrlProgress(CDlgBase *dlg, int ctrlId);
+
+ void SetRange(WORD max, WORD min = 0);
+ void SetPosition(WORD value);
+ void SetStep(WORD value);
+ WORD Move(WORD delta = 0);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlClc
+
+#if !defined(MGROUP)
+ typedef int MGROUP;
+#endif
+
+class MIR_CORE_EXPORT CCtrlClc : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+public:
+ CCtrlClc(CDlgBase *dlg, int ctrlId);
+
+ void AddContact(MCONTACT hContact);
+ void AddGroup(HANDLE hGroup);
+ HANDLE AddInfoItem(CLCINFOITEM *cii);
+ void AutoRebuild();
+ void DeleteItem(HANDLE hItem);
+ void EditLabel(HANDLE hItem);
+ void EndEditLabel(bool save);
+ void EnsureVisible(HANDLE hItem, bool partialOk);
+ void Expand(HANDLE hItem, DWORD flags);
+ HANDLE FindContact(MCONTACT hContact);
+ HANDLE FindGroup(MGROUP hGroup);
+ COLORREF GetBkColor() const;
+ bool GetCheck(HANDLE hItem) const;
+ int GetCount() const;
+ HWND GetEditControl() const;
+ DWORD GetExStyle() const;
+ DWORD GetExpand(HANDLE hItem) const;
+ int GetExtraColumns() const;
+ BYTE GetExtraImage(HANDLE hItem, int iColumn) const;
+ HIMAGELIST GetExtraImageList() const;
+ HFONT GetFont(int iFontId) const;
+ bool GetHideOfflineRoot() const;
+ int GetItemType(HANDLE hItem) const;
+ HANDLE GetNextItem(HANDLE hItem, DWORD flags) const;
+ HANDLE GetSelection() const;
+ HANDLE HitTest(int x, int y, DWORD *hitTest) const;
+ void SelectItem(HANDLE hItem);
+ void SetBkColor(COLORREF clBack);
+ void SetCheck(HANDLE hItem, bool check);
+ void SetExStyle(DWORD exStyle);
+ void SetExtraColumns(int iColumns);
+ void SetExtraImage(HANDLE hItem, int iColumn, int iImage);
+ void SetExtraImageList(HIMAGELIST hImgList);
+ void SetFont(int iFontId, HANDLE hFont, bool bRedraw);
+ void SetItemText(HANDLE hItem, char *szText);
+ void SetHideEmptyGroups(bool state);
+ void SetHideOfflineRoot(bool state);
+ void SetOfflineModes(DWORD modes);
+ void SetUseGroups(bool state);
+
+ struct TEventInfo
+ {
+ CCtrlClc *ctrl;
+ struct NMCLISTCONTROL *info;
+ };
+
+ CCallback<TEventInfo> OnExpanded;
+ CCallback<TEventInfo> OnListRebuilt;
+ CCallback<TEventInfo> OnItemChecked;
+ CCallback<TEventInfo> OnDragging;
+ CCallback<TEventInfo> OnDropped;
+ CCallback<TEventInfo> OnListSizeChange;
+ CCallback<TEventInfo> OnOptionsChanged;
+ CCallback<TEventInfo> OnDragStop;
+ CCallback<TEventInfo> OnNewContact;
+ CCallback<TEventInfo> OnContactMoved;
+ CCallback<TEventInfo> OnCheckChanged;
+ CCallback<TEventInfo> OnClick;
+
+protected:
+ BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlData - data access controls base class
+
+class MIR_CORE_EXPORT CCtrlData : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+public:
+ CCtrlData(CDlgBase *dlg, int ctrlId);
+ ~CCtrlData();
+
+ void CreateDbLink(const char* szModuleName, const char* szSetting, BYTE type, DWORD iValue);
+ void CreateDbLink(const char* szModuleName, const char* szSetting, wchar_t* szValue);
+ void CreateDbLink(CDataLink *link) { m_dbLink = link; }
+
+ void OnInit() override;
+
+protected:
+ CDataLink *m_dbLink;
+
+ __inline BYTE GetDataType() { return m_dbLink ? m_dbLink->GetDataType() : DBVT_DELETED; }
+ __inline DWORD LoadInt() { return m_dbLink ? m_dbLink->LoadInt() : 0; }
+ __inline void SaveInt(DWORD value) { if (m_dbLink) m_dbLink->SaveInt(value); }
+ __inline const wchar_t *LoadText() { return m_dbLink ? m_dbLink->LoadText() : L""; }
+ __inline void SaveText(wchar_t *value) { if (m_dbLink) m_dbLink->SaveText(value); }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlCheck
+
+class MIR_CORE_EXPORT CCtrlCheck : public CCtrlData
+{
+ typedef CCtrlData CSuper;
+
+public:
+ CCtrlCheck(CDlgBase *dlg, int ctrlId);
+ BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD /*idCode*/) override;
+
+ bool OnApply() override;
+ void OnReset() override;
+
+ int GetState() const;
+ void SetState(int state);
+
+ bool IsChecked();
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlColor - color picker
+
+class MIR_CORE_EXPORT CCtrlColor : public CCtrlData
+{
+ typedef CCtrlData CSuper;
+
+public:
+ CCtrlColor(CDlgBase *dlg, int ctrlId);
+ BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD /*idCode*/) override;
+
+ bool OnApply() override;
+ void OnReset() override;
+
+ DWORD GetColor();
+ void SetColor(DWORD dwValue);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlDate - date & time picker
+
+class MIR_CORE_EXPORT CCtrlDate : public CCtrlData
+{
+ typedef CCtrlData CSuper;
+
+ BOOL OnNotify(int, NMHDR*) override;
+
+public:
+ CCtrlDate(CDlgBase *dlg, int ctrlId);
+
+ void GetTime(struct SYSTEMTIME*);
+ void SetTime(struct SYSTEMTIME*);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlEdit
+
+class MIR_CORE_EXPORT CCtrlEdit : public CCtrlData
+{
+ typedef CCtrlData CSuper;
+
+public:
+ CCtrlEdit(CDlgBase *dlg, int ctrlId);
+ BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD idCode) override;
+
+ bool OnApply() override;
+ void OnReset() override;
+
+ void SetMaxLength(unsigned int len);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlRichEdit
+
+class MIR_CORE_EXPORT CCtrlRichEdit : public CCtrlEdit
+{
+ typedef CCtrlEdit CSuper;
+
+public:
+ CCtrlRichEdit(CDlgBase *dlg, int ctrlId);
+
+ // returns text length in bytes if a parameter is omitted or in symbols, if not
+ int GetRichTextLength(int iCodePage = CP_ACP) const;
+
+ // returns a buffer that should be freed using mir_free() or ptrA/ptrW
+ char* GetRichTextRtf(bool bText = false, bool bSelection = false) const; // returns text with formatting
+ wchar_t* GetRichText() const; // returns only text in ucs2
+
+ // these methods return text length in Unicode chars
+ int SetRichText(const wchar_t *text);
+ int SetRichTextRtf(const char *text);
+
+ // enables or disables content editing
+ void SetReadOnly(bool bReadOnly);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlSlider
+
+class MIR_CORE_EXPORT CCtrlSlider : public CCtrlData
+{
+ typedef CCtrlData CSuper;
+
+ int m_wMin, m_wMax;
+
+protected:
+ BOOL OnCommand(HWND hwndCtrl, WORD idCtrl, WORD idCode) override;
+
+public:
+ CCtrlSlider(CDlgBase *dlg, int ctrlId, int max = 100, int min = 0);
+
+ bool OnApply() override;
+ void OnReset() override;
+
+ int GetPosition() const;
+ void SetPosition(int pos);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlSpin
+
+class MIR_CORE_EXPORT CCtrlSpin : public CCtrlData
+{
+ typedef CCtrlData CSuper;
+
+ WORD m_wMin, m_wMax, m_wCurr;
+
+ BOOL OnNotify(int, NMHDR*) override;
+
+public:
+ CCtrlSpin(CDlgBase *dlg, int ctrlId, WORD max = 100, WORD min = 0);
+
+ bool OnApply() override;
+ void OnReset() override;
+
+ WORD GetPosition();
+ void SetPosition(WORD pos);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlListBox
+
+class MIR_CORE_EXPORT CCtrlListBox : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+public:
+ CCtrlListBox(CDlgBase *dlg, int ctrlId);
+
+ int AddString(const wchar_t *text, LPARAM data=0);
+ void DeleteString(int index);
+ int FindString(const wchar_t *str, int index = -1, bool exact = false);
+ int GetCount() const;
+ int GetCurSel() const;
+ LPARAM GetItemData(int index) const;
+ int GetItemRect(int index, RECT *pResult) const;
+ wchar_t* GetItemText(int index) const;
+ wchar_t* GetItemText(int index, wchar_t *buf, int size) const;
+ bool GetSel(int index) const;
+ int GetSelCount() const;
+ int* GetSelItems(int *items, int count) const;
+ int* GetSelItems() const;
+ int InsertString(const wchar_t *text, int pos, LPARAM data=0);
+ void ResetContent();
+ int SelectString(const wchar_t *str);
+ int SetCurSel(int index);
+ void SetItemData(int index, LPARAM data);
+ void SetItemHeight(int index, int iHeight);
+ void SetSel(int index, bool sel = true);
+
+ // Events
+ CCallback<CCtrlListBox> OnDblClick;
+ CCallback<CCtrlListBox> OnSelCancel;
+ CCallback<CCtrlListBox> OnSelChange;
+
+protected:
+ BOOL OnCommand(HWND hwndCtrl, WORD idCtrl, WORD idCode) override;
+ void GetCaretPos(CContextMenuPos&) const override;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlCombo
+
+class MIR_CORE_EXPORT CCtrlCombo : public CCtrlData
+{
+ typedef CCtrlData CSuper;
+
+public:
+ CCtrlCombo(CDlgBase *dlg, int ctrlId);
+
+ BOOL OnCommand(HWND /*hwndCtrl*/, WORD /*idCtrl*/, WORD idCode) override;
+ void OnInit() override;
+ bool OnApply() override;
+ void OnReset() override;
+
+ // returns item data associated with the selected item or -1
+ LPARAM GetCurData() const;
+
+ // selects line with userdata passed. returns index of this line or -1
+ int SelectData(LPARAM data);
+
+ // Control interface
+ int AddString(const wchar_t *text, LPARAM data = 0);
+ int AddStringA(const char *text, LPARAM data = 0);
+ void DeleteString(int index);
+ int FindString(const wchar_t *str, int index = -1, bool exact = false);
+ int FindStringA(const char *str, int index = -1, bool exact = false);
+ int GetCount() const;
+ int GetCurSel() const;
+ bool GetDroppedState() const;
+ LPARAM GetItemData(int index) const;
+ wchar_t* GetItemText(int index) const;
+ wchar_t* GetItemText(int index, wchar_t *buf, int size) const;
+ int InsertString(const wchar_t *text, int pos, LPARAM data=0);
+ void ResetContent();
+ int SelectString(const wchar_t *str);
+ int SetCurSel(int index);
+ void SetItemData(int index, LPARAM data);
+ void ShowDropdown(bool show = true);
+
+ // Events
+ CCallback<CCtrlCombo> OnCloseup;
+ CCallback<CCtrlCombo> OnDropdown;
+ CCallback<CCtrlCombo> OnKillFocus;
+ CCallback<CCtrlCombo> OnSelChanged;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlListView
+
+class MIR_CORE_EXPORT CCtrlListView : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+public:
+ CCtrlListView(CDlgBase *dlg, int ctrlId);
+
+ // direction = -1 or 1. returns new item index
+ int MoveItem(int idx, int direction);
+
+ void SetCurSel(int idx);
+
+ // Classic LV interface
+ DWORD ApproximateViewRect(int cx, int cy, int iCount);
+ void Arrange(UINT code);
+ void CancelEditLabel();
+ HIMAGELIST CreateDragImage(int iItem, POINT *lpptUpLeft);
+ void DeleteAllItems();
+ void DeleteColumn(int iCol);
+ void DeleteItem(int iItem);
+ HWND EditLabel(int iItem);
+ int EnableGroupView(BOOL fEnable);
+ BOOL EnsureVisible(int i, BOOL fPartialOK);
+ int FindItem(int iStart, const struct LVFINDINFO *plvfi);
+ COLORREF GetBkColor() const;
+ void GetBkImage(struct LVBKIMAGE *plvbki) const;
+ UINT GetCallbackMask() const;
+ BOOL GetCheckState(UINT iIndex) const;
+ void GetColumn(int iCol, struct LVCOLUMN *pcol) const;
+ void GetColumnOrderArray(int iCount, int *lpiArray) const;
+ int GetColumnWidth(int iCol) const;
+ int GetCountPerPage() const;
+ HWND GetEditControl() const;
+ DWORD GetExtendedListViewStyle() const;
+ int GetFocusedGroup() const;
+ int GetGroupCount() const;
+ void GetGroupInfo(int iGroupId, struct LVGROUP *pgrp) const;
+ void GetGroupInfoByIndex(int iIndex, struct LVGROUP *pgrp) const;
+ void GetGroupMetrics(struct LVGROUPMETRICS *pGroupMetrics) const;
+ UINT GetGroupState(UINT dwGroupId, UINT dwMask) const;
+ HWND GetHeader() const;
+ HCURSOR GetHotCursor() const;
+ int GetHotItem() const;
+ DWORD GetHoverTime() const;
+ HIMAGELIST GetImageList(int iImageList) const;
+ BOOL GetInsertMark(struct LVINSERTMARK *plvim) const;
+ COLORREF GetInsertMarkColor() const;
+ int GetInsertMarkRect(RECT *prc) const;
+ BOOL GetISearchString(LPSTR lpsz) const;
+ bool GetItem(struct LVITEM *pitem) const;
+ int GetItemCount() const;
+ void GetItemPosition(int i, POINT *ppt) const;
+ void GetItemRect(int i, RECT *prc, int code) const;
+ DWORD GetItemSpacing(BOOL fSmall) const;
+ UINT GetItemState(int i, UINT mask) const;
+ void GetItemText(int iItem, int iSubItem, LPTSTR pszText, int cchTextMax) const;
+ int GetNextItem(int iStart, UINT flags) const;
+ BOOL GetNumberOfWorkAreas(UINT *lpuWorkAreas) const;
+ BOOL GetOrigin(POINT *lpptOrg) const;
+ COLORREF GetOutlineColor() const;
+ UINT GetSelectedColumn() const;
+ UINT GetSelectedCount() const;
+ int GetSelectionMark() const;
+ int GetStringWidth(LPCSTR psz) const;
+ BOOL GetSubItemRect(int iItem, int iSubItem, int code, RECT *lpRect) const;
+ COLORREF GetTextBkColor() const;
+ COLORREF GetTextColor() const;
+ void GetTileInfo(struct LVTILEINFO *plvtinfo) const;
+ void GetTileViewInfo(struct LVTILEVIEWINFO *plvtvinfo) const;
+ HWND GetToolTips() const;
+ int GetTopIndex() const;
+ BOOL GetUnicodeFormat() const;
+ DWORD GetView() const;
+ BOOL GetViewRect(RECT *prc) const;
+ void GetWorkAreas(int nWorkAreas, RECT *lprc) const;
+ BOOL HasGroup(int dwGroupId);
+ int HitTest(struct LVHITTESTINFO *pinfo) const;
+ int HitTestEx(struct LVHITTESTINFO *pinfo);
+ int InsertColumn(int iCol, const struct LVCOLUMN *pcol);
+ int InsertGroup(int index, struct LVGROUP *pgrp);
+ void InsertGroupSorted(struct LVINSERTGROUPSORTED *structInsert);
+ int InsertItem(const struct LVITEM *pitem);
+ BOOL InsertMarkHitTest(POINT *point, LVINSERTMARK *plvim);
+ BOOL IsGroupViewEnabled();
+ UINT IsItemVisible(UINT index);
+ UINT MapIDToIndex(UINT id);
+ UINT MapIndexToID(UINT index);
+ BOOL RedrawItems(int iFirst, int iLast);
+ void RemoveAllGroups();
+ int RemoveGroup(int iGroupId);
+ BOOL Scroll(int dx, int dy);
+ BOOL SetBkColor(COLORREF clrBk);
+ BOOL SetBkImage(struct LVBKIMAGE *plvbki);
+ BOOL SetCallbackMask(UINT mask);
+ void SetCheckState(UINT iIndex, BOOL fCheck);
+ BOOL SetColumn(int iCol, struct LVCOLUMN *pcol);
+ BOOL SetColumnOrderArray(int iCount, int *lpiArray);
+ BOOL SetColumnWidth(int iCol, int cx);
+ void SetExtendedListViewStyle(DWORD dwExStyle);
+ void SetExtendedListViewStyleEx(DWORD dwExMask, DWORD dwExStyle);
+ int SetGroupInfo(int iGroupId, struct LVGROUP *pgrp);
+ void SetGroupMetrics(struct LVGROUPMETRICS *pGroupMetrics);
+ void SetGroupState(UINT dwGroupId, UINT dwMask, UINT dwState);
+ HCURSOR SetHotCursor(HCURSOR hCursor);
+ int SetHotItem(int iIndex);
+ void SetHoverTime(DWORD dwHoverTime);
+ DWORD SetIconSpacing(int cx, int cy);
+ HIMAGELIST SetImageList(HIMAGELIST himl, int iImageList);
+ BOOL SetInfoTip(struct LVSETINFOTIP *plvSetInfoTip);
+ BOOL SetInsertMark(struct LVINSERTMARK *plvim);
+ COLORREF SetInsertMarkColor(COLORREF color);
+ BOOL SetItem(const struct LVITEM *pitem);
+ void SetItemCount(int cItems);
+ void SetItemCountEx(int cItems, DWORD dwFlags);
+ BOOL SetItemPosition(int i, int x, int y);
+ void SetItemPosition32(int iItem, int x, int y);
+ void SetItemState(int i, UINT state, UINT mask);
+ void SetItemText(int i, int iSubItem, const wchar_t *pszText);
+ COLORREF SetOutlineColor(COLORREF color);
+ void SetSelectedColumn(int iCol);
+ int SetSelectionMark(int iIndex);
+ BOOL SetTextBkColor(COLORREF clrText);
+ BOOL SetTextColor(COLORREF clrText);
+ BOOL SetTileInfo(struct LVTILEINFO *plvtinfo);
+ BOOL SetTileViewInfo(struct LVTILEVIEWINFO *plvtvinfo);
+ HWND SetToolTips(HWND ToolTip);
+ BOOL SetUnicodeFormat(BOOL fUnicode);
+ int SetView(DWORD iView);
+ void SetWorkAreas(int nWorkAreas, RECT *lprc);
+ int SubItemHitTest(struct LVHITTESTINFO *pInfo) const;
+ int SubItemHitTestEx(struct LVHITTESTINFO *plvhti);
+ BOOL Update(int iItem);
+
+ #ifdef _MSC_VER
+ int SortGroups(PFNLVGROUPCOMPARE pfnGroupCompare, LPVOID plv);
+ BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort);
+ BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort);
+ #endif // _MSC_VER
+
+ // Additional APIs
+ HIMAGELIST CreateImageList(int iImageList);
+ void AddColumn(int iSubItem, const wchar_t *name, int cx);
+ void AddGroup(int iGroupId, const wchar_t *name);
+ int AddItem(const wchar_t *text, int iIcon, LPARAM lParam = 0, int iGroupId = -1);
+ void SetItem(int iItem, int iSubItem, const wchar_t *text, int iIcon = -1);
+ LPARAM GetItemData(int iItem) const;
+
+ // Events
+ struct TEventInfo {
+ CCtrlListView *treeviewctrl;
+ union {
+ struct NMHDR *nmhdr;
+ struct NMLISTVIEW *nmlv;
+ struct NMLVDISPINFO *nmlvdi;
+ struct NMLVSCROLL *nmlvscr;
+ struct NMLVGETINFOTIP *nmlvit;
+ struct NMLVFINDITEM *nmlvfi;
+ struct NMITEMACTIVATE *nmlvia;
+ struct NMLVKEYDOWN *nmlvkey;
+ struct NMLVCUSTOMDRAW *nmcd;
+ };
+ };
+
+ CCallback<TEventInfo> OnBeginDrag;
+ CCallback<TEventInfo> OnBeginLabelEdit;
+ CCallback<TEventInfo> OnBeginRDrag;
+ CCallback<TEventInfo> OnBeginScroll;
+ CCallback<TEventInfo> OnColumnClick;
+ CCallback<TEventInfo> OnCustomDraw;
+ CCallback<TEventInfo> OnDeleteAllItems;
+ CCallback<TEventInfo> OnDeleteItem;
+ CCallback<TEventInfo> OnClick;
+ CCallback<TEventInfo> OnDoubleClick;
+ CCallback<TEventInfo> OnEndLabelEdit;
+ CCallback<TEventInfo> OnEndScroll;
+ CCallback<TEventInfo> OnGetDispInfo;
+ CCallback<TEventInfo> OnGetInfoTip;
+ CCallback<TEventInfo> OnHotTrack;
+ CCallback<TEventInfo> OnIncrementalSearch;
+ CCallback<TEventInfo> OnInsertItem;
+ CCallback<TEventInfo> OnItemActivate;
+ CCallback<TEventInfo> OnItemChanged;
+ CCallback<TEventInfo> OnItemChanging;
+ CCallback<TEventInfo> OnKeyDown;
+ CCallback<TEventInfo> OnMarqueeBegin;
+ CCallback<TEventInfo> OnSetDispInfo;
+
+protected:
+ BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
+ void GetCaretPos(CContextMenuPos&) const override;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlTreeView
+
+#undef GetNextSibling
+#undef GetPrevSibling
+
+#define MTREE_CHECKBOX 0x0001
+#define MTREE_DND 0x0002
+#define MTREE_MULTISELECT 0x0004
+
+class MIR_CORE_EXPORT CCtrlTreeView : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+ HTREEITEM MoveItemAbove(HTREEITEM hItem, HTREEITEM hInsertAfter, HTREEITEM hParent);
+
+public:
+ CCtrlTreeView(CDlgBase *dlg, int ctrlId);
+
+ void SetFlags(uint32_t dwFlags); // MTREE_* combination
+
+ // Classic TV interface
+ HIMAGELIST CreateDragImage(HTREEITEM hItem);
+ void DeleteAllItems();
+ void DeleteItem(HTREEITEM hItem);
+ HWND EditLabel(HTREEITEM hItem);
+ void EndEditLabelNow(BOOL cancel);
+ void EnsureVisible(HTREEITEM hItem);
+ void Expand(HTREEITEM hItem, DWORD flag);
+ COLORREF GetBkColor() const;
+ DWORD GetCheckState(HTREEITEM hItem) const;
+ HTREEITEM GetChild(HTREEITEM hItem) const;
+ int GetCount() const;
+ HTREEITEM GetDropHilight() const;
+ HWND GetEditControl() const;
+ HTREEITEM GetFirstVisible() const;
+ HIMAGELIST GetImageList(int iImage) const;
+ int GetIndent() const;
+ COLORREF GetInsertMarkColor() const;
+ bool GetItem(struct TVITEMEX *tvi) const;
+ int GetItemHeight() const;
+ void GetItemRect(HTREEITEM hItem, RECT *rcItem, BOOL fItemRect) const;
+ DWORD GetItemState(HTREEITEM hItem, DWORD stateMask) const;
+ HTREEITEM GetLastVisible() const;
+ COLORREF GetLineColor() const;
+ HTREEITEM GetNextItem(HTREEITEM hItem, DWORD flag) const;
+ HTREEITEM GetNextSibling(HTREEITEM hItem) const;
+ HTREEITEM GetNextVisible(HTREEITEM hItem) const;
+ HTREEITEM GetParent(HTREEITEM hItem) const;
+ HTREEITEM GetPrevSibling(HTREEITEM hItem) const;
+ HTREEITEM GetPrevVisible(HTREEITEM hItem) const;
+ HTREEITEM GetRoot() const;
+ DWORD GetScrollTime() const;
+ HTREEITEM GetSelection() const;
+ COLORREF GetTextColor() const;
+ HWND GetToolTips() const;
+ BOOL GetUnicodeFormat() const;
+ unsigned GetVisibleCount() const;
+ HTREEITEM HitTest(struct TVHITTESTINFO *hti) const;
+ HTREEITEM InsertItem(struct TVINSERTSTRUCT *tvis);
+ void Select(HTREEITEM hItem, DWORD flag);
+ void SelectDropTarget(HTREEITEM hItem);
+ void SelectItem(HTREEITEM hItem);
+ void SelectSetFirstVisible(HTREEITEM hItem);
+ COLORREF SetBkColor(COLORREF clBack);
+ void SetCheckState(HTREEITEM hItem, DWORD state);
+ void SetImageList(HIMAGELIST hIml, int iImage);
+ void SetIndent(int iIndent);
+ void SetInsertMark(HTREEITEM hItem, BOOL fAfter);
+ COLORREF SetInsertMarkColor(COLORREF clMark);
+ void SetItem(TVITEMEX *tvi);
+ void SetItemHeight(short cyItem);
+ void SetItemState(HTREEITEM hItem, DWORD state, DWORD stateMask);
+ COLORREF SetLineColor(COLORREF clLine);
+ void SetScrollTime(UINT uMaxScrollTime);
+ COLORREF SetTextColor(COLORREF clText);
+ HWND SetToolTips(HWND hwndToolTips);
+ BOOL SetUnicodeFormat(BOOL fUnicode);
+ void SortChildren(HTREEITEM hItem, BOOL fRecurse);
+ void SortChildrenCB(struct TVSORTCB *cb, BOOL fRecurse);
+
+ // Additional stuff
+ void TranslateItem(HTREEITEM hItem);
+ void TranslateTree();
+ HTREEITEM FindNamedItem(HTREEITEM hItem, const wchar_t *name);
+ void GetItem(HTREEITEM hItem, TVITEMEX *tvi) const;
+ void GetItem(HTREEITEM hItem, TVITEMEX *tvi, wchar_t *szText, int iTextLength) const;
+ void InvertCheck(HTREEITEM hItem);
+
+ bool IsSelected(HTREEITEM hItem);
+ int GetNumSelected();
+ void GetSelected(LIST<struct _TREEITEM> &selected);
+
+ void Select(HTREEITEM hItem);
+ void Select(LIST<_TREEITEM> &selected);
+ void SelectAll();
+ void SelectRange(HTREEITEM hStart, HTREEITEM hEnd);
+
+ void Unselect(HTREEITEM hItem);
+ void UnselectAll();
+
+ void DropHilite(HTREEITEM hItem);
+ void DropUnhilite(HTREEITEM hItem);
+
+ // Events
+ struct TEventInfo {
+ CCtrlTreeView *treeviewctrl;
+ union {
+ struct NMHDR *nmhdr;
+ struct NMTREEVIEW *nmtv;
+ struct NMTVKEYDOWN *nmtvkey;
+ struct NMTVDISPINFO *nmtvdi;
+ struct NMTVGETINFOTIP *nmtvit;
+ struct NMTVCUSTOMDRAW *nmcd;
+ HTREEITEM hItem; // for OnItemChanged
+ };
+ };
+
+ CCallback<TEventInfo> OnBeginDrag;
+ CCallback<TEventInfo> OnBeginLabelEdit;
+ CCallback<TEventInfo> OnBeginRDrag;
+ CCallback<TEventInfo> OnCustomDraw;
+ CCallback<TEventInfo> OnDeleteItem;
+ CCallback<TEventInfo> OnEndLabelEdit;
+ CCallback<TEventInfo> OnGetDispInfo;
+ CCallback<TEventInfo> OnGetInfoTip;
+ CCallback<TEventInfo> OnItemChanged;
+ CCallback<TEventInfo> OnItemExpanded;
+ CCallback<TEventInfo> OnItemExpanding;
+ CCallback<TEventInfo> OnKeyDown;
+ CCallback<TEventInfo> OnRightClick;
+ CCallback<TEventInfo> OnSelChanged;
+ CCallback<TEventInfo> OnSelChanging;
+ CCallback<TEventInfo> OnSetDispInfo;
+ CCallback<TEventInfo> OnSingleExpand;
+
+protected:
+ void OnInit() override;
+ void OnDestroy() override;
+ BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
+
+ void GetCaretPos(CContextMenuPos&) const override;
+ INT_PTR CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
+
+ union {
+ uint32_t m_dwFlags;
+ struct {
+ bool m_bDndEnabled : 1;
+ bool m_bDragging : 1;
+ bool m_bCheckBox : 1;
+ bool m_bMultiSelect : 1;
+ };
+ };
+ HTREEITEM m_hDragItem; // valid if m_bDragging == true
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlTreeOpts - array of options with sections
+
+class MIR_CORE_EXPORT CCtrlTreeOpts : public CCtrlTreeView
+{
+ typedef CCtrlTreeView CSuper;
+
+public:
+ CCtrlTreeOpts(CDlgBase *dlg, int ctrlId);
+ ~CCtrlTreeOpts();
+
+ void AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, CMOption<bool> &option);
+
+ BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
+ void OnDestroy() override;
+ void OnInit() override;
+ bool OnApply() override;
+
+protected:
+ struct COptionsItem
+ {
+ const wchar_t *m_pwszSection, *m_pwszName;
+
+ CMOption<bool> *m_option;
+
+ HTREEITEM m_hItem = nullptr;
+
+ COptionsItem(const wchar_t *pwszSection, const wchar_t *pwszName, CMOption<bool> &option) :
+ m_pwszSection(pwszSection),
+ m_pwszName(pwszName),
+ m_option(&option)
+ {
+ }
+ };
+
+ OBJLIST<COptionsItem> m_options;
+
+ void ProcessItemClick(HTREEITEM hti);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CCtrlPages
+
+#define PSN_INFOCHANGED 1
+#define PSN_PARAMCHANGED 2
+
+// force-send a PSN_INFOCHANGED to all pages
+#define PSM_FORCECHANGED (WM_USER+100)
+
+class MIR_CORE_EXPORT CCtrlPages : public CCtrlBase
+{
+ typedef CCtrlBase CSuper;
+
+ HIMAGELIST m_hIml;
+ CDlgBase *m_pActivePage;
+ int m_numRows = 1;
+
+ struct TPageInfo;
+ void InsertPage(TPageInfo *pPage);
+ void ShowPage(CDlgBase *pDlg);
+
+ void CheckRowCount();
+ TPageInfo* GetCurrPage();
+ TPageInfo* GetItemPage(int iPage);
+ LIST<TPageInfo> m_pages;
+
+public:
+ CCtrlPages(CDlgBase *dlg, int ctrlId);
+
+ void AddPage(const wchar_t *ptszName, HICON hIcon, CDlgBase *pDlg);
+ void ActivatePage(int iPage);
+ int GetCount(void);
+ int GetDlgIndex(CDlgBase*);
+ void RemovePage(int iPage);
+ void SwapPages(int idx1, int idx2);
+
+ CDlgBase* GetNthPage(int iPage);
+
+ __forceinline CDlgBase* GetActivePage() const
+ { return m_pActivePage;
+ }
+
+protected:
+ BOOL OnNotify(int idCtrl, NMHDR *pnmh) override;
+
+ void OnInit() override;
+ void OnDestroy() override;
+
+ bool OnApply() override;
+ void OnReset() override;
+
+ INT_PTR CustomWndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CProtoDlgBase
+
+#define WM_PROTO_REFRESH (WM_USER + 100)
+#define WM_PROTO_CHECK_ONLINE (WM_USER + 101)
+#define WM_PROTO_ACTIVATE (WM_USER + 102)
+#define WM_PROTO_LAST (WM_USER + 200)
+
+struct PROTO_INTERFACE;
+
+class MIR_APP_EXPORT CProtoIntDlgBase : public CDlgBase
+{
+ typedef CDlgBase CSuper;
+
+public:
+ CProtoIntDlgBase(PROTO_INTERFACE *proto, int idDialog);
+
+ void CreateLink(CCtrlData &ctrl, const char *szSetting, BYTE type, DWORD iValue);
+ void CreateLink(CCtrlData &ctrl, const char *szSetting, wchar_t *szValue);
+
+ template<class T>
+ __inline void CreateLink(CCtrlData &ctrl, CMOption<T> &option)
+ {
+ ctrl.CreateDbLink(new CMOptionLink<T>(option));
+ }
+
+ __inline PROTO_INTERFACE *GetProtoInterface() { return m_proto_interface; }
+
+ void SetStatusText(const wchar_t *statusText);
+
+protected:
+ PROTO_INTERFACE *m_proto_interface;
+ HWND m_hwndStatus = nullptr;
+
+ INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
+
+ virtual void OnProtoRefresh(WPARAM, LPARAM);
+ virtual void OnProtoActivate(WPARAM, LPARAM);
+ virtual void OnProtoCheckOnline(WPARAM, LPARAM);
+
+private:
+ void UpdateStatusBar();
+};
+
+template<typename TProto>
+class CProtoDlgBase : public CProtoIntDlgBase
+{
+ typedef CProtoIntDlgBase CSuper;
+
+public:
+ __inline CProtoDlgBase<TProto>(TProto *proto, int idDialog) :
+ CProtoIntDlgBase(proto, idDialog),
+ m_proto(proto)
+ {
+ }
+
+ __inline TProto *GetProto() { return m_proto; }
+
+protected:
+ TProto* m_proto;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Safe open/close dialogs
+#define UI_SAFE_OPEN(dlgClass, dlgPtr) \
+ { \
+ if (dlgPtr) \
+ { \
+ SetForegroundWindow((dlgPtr)->GetHwnd()); \
+ } else \
+ { \
+ (dlgPtr) = new dlgClass(this); \
+ (dlgPtr)->Show(); \
+ } \
+ }
+
+#define UI_SAFE_OPEN_EX(dlgClass, dlgPtr, dlgLocal) \
+ if (dlgPtr) \
+ { \
+ ::SetForegroundWindow((dlgPtr)->GetHwnd()); \
+ } else \
+ { \
+ (dlgPtr) = new dlgClass(this); \
+ (dlgPtr)->Show(); \
+ } \
+ dlgClass *dlgLocal = (dlgClass *)(dlgPtr);
+
+#define UI_SAFE_CLOSE(dlg) \
+ { \
+ if (dlg) { \
+ (dlg)->Close(); \
+ (dlg) = NULL; \
+ } \
+ }
+
+#define UI_SAFE_CLOSE_HWND(hwnd) \
+ { \
+ if (hwnd) { \
+ ::SendMessage((hwnd), WM_CLOSE, 0, 0); \
+ (hwnd) = NULL; \
+ } \
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// NULL-Safe dialog notifications
+#define UI_SAFE_NOTIFY(dlg, msg) \
+ { \
+ if (dlg) \
+ ::SendMessage((dlg)->GetHwnd(), msg, 0, 0); \
+ }
+
+#define UI_SAFE_NOTIFY_HWND(hwnd, msg) \
+ { \
+ if (hwnd) \
+ ::SendMessage((hwnd), msg, 0, 0); \
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Define message maps
+#define UI_MESSAGE_MAP(dlgClass, baseDlgClass) \
+ typedef baseDlgClass CMessageMapSuperClass; \
+ virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) \
+ { \
+ switch (msg) \
+ { \
+ case 0: \
+ break /* just to handle ";" symbol after macro */
+
+#define UI_MESSAGE(msg, proc) \
+ case msg: \
+ proc(msg, wParam, lParam); \
+ break
+
+#define UI_MESSAGE_EX(msg, func) \
+ case msg: \
+ return func(msg, wParam, lParam)
+
+#define UI_POSTPROCESS_MESSAGE(msg, proc) \
+ case msg: \
+ CMessageMapSuperClass::DlgProc(msg, wParam, lParam); \
+ return FALSE
+
+#define UI_POSTPROCESS_MESSAGE_EX(msg, func) \
+ case msg: \
+ CMessageMapSuperClass::DlgProc(msg, wParam, lParam); \
+ return func(msg, wParam, lParam)
+
+#define UI_MESSAGE_MAP_END() \
+ } \
+ return CMessageMapSuperClass::DlgProc(msg, wParam, lParam); \
+ }
+
+#endif // __M_GUI_H
diff --git a/include/m_netlib.h b/include/m_netlib.h
index b821af977a..8c3e1e1d24 100644
--- a/include/m_netlib.h
+++ b/include/m_netlib.h
@@ -1,865 +1,865 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-Copyright (c) 2000-12 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 M_NETLIB_H__
-#define M_NETLIB_H__ 1
-
-#include "m_utils.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// this module was created in 0.1.2.2
-// All error codes are returned via GetLastError() (or WSAGetLastError():
-// they're the same).
-// This module is thread-safe where it is sensible for it to be so. This
-// basically means that you can call anything from any thread, but don't try
-// to predict what will happen if you try to recv() on the same connection from
-// two different threads at the same time.
-// Note that because the vast majority of the routines in this module return
-// a pointer, I have decided to diverge from the rest of Miranda and go with
-// the convention that functions return false on failure and nonzero on success.
-
-struct NETLIBHTTPREQUEST;
-struct NETLIBOPENCONNECTION;
-
-#define NETLIB_USER_AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.112 Safari/537.36"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Initialises the netlib for a set of connections
-// Returns a HNETLIBUSER to be used for future netlib calls, NULL on failure
-// NOTE: Netlib is loaded after any plugins, so you need to wait until
-// ME_SYSTEM_MODULESLOADED before calling this function
-// Netlib settings are stored under the module szSettingsModule
-// All netlib settings being with "NL".
-// The default settings for registered users that don't have any settings stored
-// in the database are the same as those displayed by the <All connections> page
-// of the netlib options page.
-// Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, ERROR_DUP_NAME
-
-struct NETLIBUSER
-{
- char *szSettingsModule; // used for db settings and log
- MAllStrings szDescriptiveName; // used in options dialog, already translated
- DWORD flags;
- int minIncomingPorts; // only if NUF_INCOMING. Will be used for validation of user input.
-};
-
-#define NUF_INCOMING 0x01 // binds incoming ports
-#define NUF_OUTGOING 0x02 // makes outgoing plain connections
-#define NUF_NOOPTIONS 0x08 // don't create an options page for this. szDescriptiveName is never used.
-#define NUF_HTTPCONNS 0x10 // at least some connections are made for HTTP communication. Enables the HTTP proxy option in options.
-#define NUF_NOHTTPSOPTION 0x20 // disable the HTTPS proxy option in options. Use this if all communication is HTTP.
-#define NUF_UNICODE 0x40 // if set ptszDescriptiveName points to Unicode, otherwise it points to ANSI string
-
-EXTERN_C MIR_APP_DLL(HNETLIBUSER) Netlib_RegisterUser(const NETLIBUSER *pDescr);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Assign a Netlib user handle a set of dynamic HTTP headers to be used with all
-//
-// HTTP connections that enable the HTTP-use-sticky headers flag.
-// The headers persist until cleared with lParam = NULL.
-//
-// All memory should be allocated by the caller using malloc() from MS_SYSTEM_GET_MMI
-// Once it has passed to Netlib, Netlib is the owner of it, the caller should not refer to the memory
-// In any way after this point.
-//
-// NOTE: The szHeaders parameter should be a NULL terminated string following the HTTP header syntax.
-// This string will be injected verbatim, thus the user should be aware of setting strings that are not
-// headers. This service is NOT THREAD SAFE, only a single thread is expected to set the headers and a single
-// thread reading the pointer internally, stopping race conditions and mutual exclusion don't happen.
-//
-// Version 0.3.2a+ (2003/10/27)
-//
-
-EXTERN_C MIR_APP_DLL(int) Netlib_SetStickyHeaders(HNETLIBUSER nlu, const char *szHeaders);
-
-/* Notes on HTTP gateway usage
-When a connection is initiated through an HTTP proxy using
-MS_NETLIB_OPENCONNECTION, netlib will GET nlu.szHttpGatewayHello and read
-the replied headers. Once this succeeds nlu.pfnHttpGatewayInit will be called
-with a valid handle to the connection, the NETLIBOPENCONNECTION structure that
-MS_NETLIB_OPENCONNECTION was called with, and the replied HTTP headers as its
-parameters. This function is responsible for recving and parsing the data then
-calling MS_NETLIB_SETHTTPPROXYINFO with the appropriate information.
-nlu.pfnHttpGatewayInit should return nonzero on success. If it returns zero
-then the entire connection attempt will return signalling failure. If your
-function needs to return an error code it can do so via SetLastError().
-If nlu.pfnHttpGatewayInit returns success without having called
-MS_NETLIB_SETHTTPPROXYINFO then the connection attempt will fail anyway.
-If you need more fine-tuned control over the GET/POST URLs than just appending
-sequence numbers you can call MS_NETLIB_SETHTTPPROXYINFO from within your
-wrap/unwrap functions (see below).
-
-Just prior to MS_NETLIB_OPENCONNECTION returning nlu.pfnHttpGatewayBegin is
-called with the handle to the connection and the NETLIBOPENCONNECTION structure
-as its parameters. This is for gateways that need special non-protocol
-initialisation. If you do send any packets in this function, you probably want
-to remember to use the MSG_NOHTTPGATEWAYWRAP flag. This function pointer can be
-NULL if this functionality isn't needed. This function must return nonzero on
-success. If it fails the connect attempt will return failure without changing
-LastError.
-
-Whenever MS_NETLIB_SEND is called on a connection through an HTTP proxy and
-the MSG_NOHTTPGATEWAYWRAP flags is not set and nlu.pfnHttpGatewayWrapSend is
-not NULL, nlu.pfnHttpGatewayWrapSend will be called *instead* of sending the
-data. It is this function's responsibility to wrap the sending data
-appropriately for transmission and call pfnNetlibSend to send it again.
-The flags parameter to nlu.pfnHttpGatewayWrapSend should be passed straight
-through to the pfnNetlibSend call. It has already been ORed with
-MSG_NOHTTPGATEWAYWRAP. nlu.pfnHttpGatewayWrapSend should return the a
-number of the same type as MS_NETLIB_SEND, ie the number of bytes sent or
-SOCKET_ERROR. The number of wrapping bytes should be subtracted so that the
-return value appears as if the proxy wasn't there.
-pfnNetlibSend() is identical to CallService(MS_NETLIB_SEND, ...) but it's
-quicker to call using this pointer than to do the CallService() lookup again.
-
-Whenever an HTTP reply is received inside MS_NETLIB_RECV the headers and data
-are read into memory. If the headers indicate success then the data is passed
-to nlu.pfnHttpGatewayUnwrapRecv (if it's non-NULL) for processing. This
-function should remove (and do other processing if necessary) all HTTP proxy
-specific headers and return a pointer to the buffer whose size is returned in
-*outBufLen. If the buffer needs to be resized then NetlibRealloc() should be
-used for that purpose, *not* your own CRT's realloc(). NetlibRealloc() behaves
-identically to realloc() so it's possible to free the original buffer and
-create a new one if that's the most sensible way to write your parser.
-If errors are encountered you should SetLastError() and return NULL;
-MS_NETLIB_RECV will return SOCKET_ERROR. If the passed buffer unwraps to
-contain no actual data you should set *outBufLen to 0 but make sure you return
-some non-NULL buffer that can be freed.
-
-When you call MS_NETLIB_SEND or MS_NETLIB_RECV from any of these functions, you
-should use the MSG_DUMPPROXY flag so that the logging is neat.
-*/
-
-#define PROXYTYPE_SOCKS4 1
-#define PROXYTYPE_SOCKS5 2
-#define PROXYTYPE_HTTP 3
-#define PROXYTYPE_HTTPS 4
-#define PROXYTYPE_IE 5
-
-struct NETLIBUSERSETTINGS
-{
- int cbSize; // to be filled in before calling
- int useProxy; // 1 or 0
- int proxyType; // a PROXYTYPE_
- char *szProxyServer; // can be NULL
- int wProxyPort; // host byte order
- int useProxyAuth; // 1 or 0. Always 0 for SOCKS4
- char *szProxyAuthUser; // can be NULL, always used by SOCKS4
- char *szProxyAuthPassword; // can be NULL
- int useProxyAuthNtlm; // 1 or 0, only used by HTTP, HTTPS
- int dnsThroughProxy; // 1 or 0
- int specifyIncomingPorts; // 1 or 0
- char *szIncomingPorts; // can be NULL. Of form "1024-1050, 1060-1070, 2000"
- int specifyOutgoingPorts; // 0.3.3a+
- char *szOutgoingPorts; // 0.3.3a+
- int enableUPnP; // 0.6.1+ only for NUF_INCOMING
- int validateSSL;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Gets the user-configured settings for a netlib user
-//
-// Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
-// The pointers referred to in the returned struct will remain valid until
-// the hUser handle is closed, or until the user changes the settings in the
-// options page, so it's best not to rely on them for too long.
-// Errors: ERROR_INVALID_PARAMETER
-
-EXTERN_C MIR_APP_DLL(int) Netlib_GetUserSettings(HNETLIBUSER nlu, NETLIBUSERSETTINGS *result);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-//Gets the user-configured settings for a netlib user idetified by name
-//
-//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
-//This function behaves like Netlib_GetUserSettings but the user is identified
-//by the name provided by registration. When the name is not found NETLIBUSERSETTINGS is set to NULL.
-//Errors: ERROR_INVALID_PARAMETER
-
-EXTERN_C MIR_APP_DLL(int) Netlib_GetUserSettingsByName(char * UserSettingsName, NETLIBUSERSETTINGS *result);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Changes the user-configurable settings for a netlib user
-//
-// Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
-// This function is only really useful for people that specify NUF_NOOPTIONS
-// and want to create their own options.
-// Even if a setting is not active (eg szProxyAuthPassword when useProxyAuth is
-// zero) that settings is still set for use in the options dialog.
-// Errors: ERROR_INVALID_PARAMETER
-
-EXTERN_C MIR_APP_DLL(int) Netlib_SetUserSettings(HNETLIBUSER nlu, const NETLIBUSERSETTINGS *result);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-//Changes the user-configurable settings for a netlib user idetified by name
-//
-//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
-//This function behaves like Netlib_SetUserSettings but the user is identified
-//by the name provided by registration. Nothing will be changed when the name is not found.
-//Errors: ERROR_INVALID_PARAMETER
-
-EXTERN_C MIR_APP_DLL(int) Netlib_SetUserSettingsByName(char * UserSettingsName, NETLIBUSERSETTINGS *result);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Closes a netlib handle
-//
-// Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
-// This function should be called on all handles returned by netlib functions
-// once you are done with them. If it's called on a socket-type handle, the
-// socket will be closed.
-// Errors: ERROR_INVALID_PARAMETER
-
-EXTERN_C MIR_APP_DLL(int) Netlib_CloseHandle(HANDLE h);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Open a port and wait for connections on it
-//
-// Returns a HANDLE on success, NULL on failure
-// hUser should have been returned by MS_NETLIB_REGISTERUSER
-// This function does the equivalent of socket(), bind(), getsockname(),
-// listen(), accept()
-// Internally this function creates a new thread which waits around in accept()
-// for new connections. When one is received it calls nlb.pfnNewConnection *from
-// this new thread* and then loops back to wait again.
-// Close the returned handle to end the thread and close the open port.
-// Errors: ERROR_INVALID_PARAMETER, any returned by socket() or bind() or
-// listen() or getsockname()
-//
-// Notes:
-//
-// During development of 0.3.1a+ (2003/07/04) passing wPort != 0
-// will result in an attempt to bind on the port given in wPort
-// if this port is taken then you will get an error, so be sure to check
-// for such conditions.
-//
-// passing wPort != 0 is for people who need to open a set port for
-// daemon activities, usually passing wPort == 0 is what you want and
-// will result in a free port given by the TCP/IP socket layer and/or
-// seeded from the user selected port ranges.
-//
-// also note that wPort if != 0, will have be converted to network byte order
-//
-/* pExtra was added during 0.3.4+, prior its just two args, since we use the cdecl convention
-it shouldnt matter */
-
-typedef void (*NETLIBNEWCONNECTIONPROC)(HNETLIBCONN hNewConnection, DWORD dwRemoteIP, void *pExtra);
-
-struct NETLIBBIND
-{
- NETLIBNEWCONNECTIONPROC pfnNewConnection;
-
- // function to call when there's a new connection. Params are: the
- // new connection, IP of remote machine (host byte order)
- DWORD dwInternalIP; // set on return, host byte order
- DWORD dwExternalIP; // set on return, host byte order
- WORD wPort, wExPort; // set on return, host byte order
- void *pExtra; // argument is sent to callback
-};
-
-EXTERN_C MIR_APP_DLL(HNETLIBBIND) Netlib_BindPort(HNETLIBUSER nlu, NETLIBBIND *nlb);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Open a connection
-//
-// Returns a HNETLIBCONN to the new connection on success, NULL on failure
-// hUser must have been returned by MS_NETLIB_REGISTERUSER
-// Internally this function is the equivalent of socket(), gethostbyname(),
-// connect()
-// If NLOCF_HTTP is set and hUser is configured for an HTTP or HTTPS proxy then
-// this function will connect() to the proxy server only, without performing any
-// initialisation conversation.
-// If hUser is configured for an HTTP proxy and does not support HTTP gateways
-// and you try to open a connection without specifying NLOCF_HTTP then this
-// function will first attempt to open an HTTPS connection, if that fails it
-// will try a direct connection, if that fails it will return failure with the
-// error from the connect() during the direct connection attempt.
-// Errors: ERROR_INVALID_PARAMETER, any returned by socket(), gethostbyname(),
-// connect(), MS_NETLIB_SEND, MS_NETLIB_RECV, select()
-// ERROR_TIMEOUT (during proxy communication)
-// ERROR_BAD_FORMAT (very invalid proxy reply)
-// ERROR_ACCESS_DENIED (by proxy)
-// ERROR_CONNECTION_UNAVAIL (socks proxy can't connect to identd)
-// ERROR_INVALID_ACCESS (proxy refused identd auth)
-// ERROR_INVALID_DATA (proxy returned invalid code)
-// ERROR_INVALID_ID_AUTHORITY (proxy requires use of auth method that's not supported)
-// ERROR_GEN_FAILURE (socks5/https general failure)
-// ERROR_CALL_NOT_IMPLEMENTED (socks5 command not supported)
-// ERROR_INVALID_ADDRESS (socks5 address type not supported)
-// HTTP: anything from nlu.pfnHttpGatewayInit, nlu.pfnHttpGatewayBegin,
-// MS_NETLIB_SENDHTTPREQUEST or MS_NETLIB_RECVHTTPHEADERS
-
-#define NLOCF_HTTP 0x0001 // this connection will be used for HTTP communications. If configured for an HTTP/HTTPS proxy the connection is opened as if there was no proxy.
-#define NLOCF_STICKYHEADERS 0x0002 // this connection should send the sticky headers associated with NetLib user apart of any HTTP request
-#define NLOCF_V2 0x0004 // this connection understands the newer structure, newer cbSize isnt enough
-#define NLOCF_UDP 0x0008 // this connection is UDP
-#define NLOCF_SSL 0x0010 // this connection is SSL
-
-struct NETLIBOPENCONNECTION
-{
- const char *szHost; // can contain the string representation of an IP
- WORD wPort; // host byte order
- DWORD flags;
- unsigned int timeout;
- /* optional, called in the context of the thread that issued the attempt, if it returns 0 the connection attempt is
- stopped, the remaining timeout value can also be adjusted */
- int (*waitcallback) (unsigned int *timeout);
-};
-
-EXTERN_C MIR_APP_DLL(HNETLIBCONN) Netlib_OpenConnection(HNETLIBUSER nlu, const NETLIBOPENCONNECTION *nloc);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Sets the required information for an HTTP proxy connection
-//
-// Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
-// This function is designed to be called from within pfnHttpGatewayInit
-// See notes below MS_NETLIB_REGISTERUSER.
-// Errors: ERROR_INVALID_PARAMETER
-
-#define NLHPIF_USEGETSEQUENCE 0x0001 // append sequence numbers to GET requests
-#define NLHPIF_USEPOSTSEQUENCE 0x0002 // append sequence numbers to POST requests
-#define NLHPIF_GETPOSTSAMESEQUENCE 0x0004 // GET and POST use the same sequence
-#define NLHPIF_HTTP11 0x0008 // HTTP 1.1 proxy
-
-struct NETLIBHTTPPROXYINFO
-{
- DWORD flags;
- int firstGetSequence, firstPostSequence;
- int combinePackets;
- char *szHttpPostUrl;
- char *szHttpGetUrl;
-};
-
-EXTERN_C MIR_APP_DLL(int) Netlib_SetHttpProxyInfo(HNETLIBCONN hConnection, const NETLIBHTTPPROXYINFO *nlhpi);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Gets the SOCKET associated with a netlib handle
-//
-// Returns the SOCKET on success, INVALID_SOCKET on failure
-// hNetlibHandle should have been returned by MS_NETLIB_BINDPORT or
-// MS_NETLIB_OPENCONNECTION only.
-// Be careful how you use this socket because you might be connected via an
-// HTTP proxy in which case calling send() or recv() will totally break things.
-// Errors: ERROR_INVALID_PARAMETER
-
-EXTERN_C MIR_APP_DLL(UINT_PTR) Netlib_GetSocket(HNETLIBCONN hConnection);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#define Netlib_GetBase64DecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3)
-#define Netlib_GetBase64EncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1)
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Gets HNETLIBUSER owner of a connection
-
-EXTERN_C MIR_APP_DLL(HNETLIBUSER) Netlib_GetConnNlu(HNETLIBCONN hConn);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Gets the fake User-Agent header field to make some sites happy
-
-EXTERN_C MIR_APP_DLL(char*) Netlib_GetUserAgent();
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Converts numerical representation of IP in SOCKADDR_INET into string representation with IP and port
-// IPv4 will be supplied in formats address:port or address
-// IPv6 will be supplied in formats [address]:port or [address]
-// Returns pointer to the string or NULL if not successful
-
-struct sockaddr_in;
-EXTERN_C MIR_APP_DLL(char*) Netlib_AddressToString(sockaddr_in *addr);
-EXTERN_C MIR_APP_DLL(bool) Netlib_StringToAddress(const char *str, sockaddr_in *addr);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Gets connection Information
-// IPv4 will be supplied in formats address:port or address
-// IPv6 will be supplied in formats [address]:port or [address]
-// Returns 0 if successful
-
-struct NETLIBCONNINFO
-{
- char szIpPort[64];
- unsigned dwIpv4;
- WORD wPort;
-};
-
-EXTERN_C MIR_APP_DLL(int) Netlib_GetConnectionInfo(HNETLIBCONN hConnection, NETLIBCONNINFO *connInfo);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Gets connection Information
-//
-// Returns (INT_PTR)(NETLIBIPLIST*) numeric IP address address array
-// the last element of the array is all 0s, 0 if not successful
-
-struct NETLIBIPLIST
-{
- unsigned cbNum;
- char szIp[1][64];
-};
-
-EXTERN_C MIR_APP_DLL(NETLIBIPLIST*) Netlib_GetMyIp(bool bGlobalOnly);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Send an HTTP request over a connection
-//
-// Returns number of bytes sent on success, SOCKET_ERROR on failure
-// hConnection must have been returned by MS_NETLIB_OPENCONNECTION
-// Note that if you use NLHRF_SMARTAUTHHEADER and NTLM authentication is in use
-// then the full NTLM authentication transaction occurs, comprising sending the
-// domain, receiving the challenge, then sending the response.
-// nlhr.resultCode and nlhr.szResultDescr are ignored by this function.
-// Errors: ERROR_INVALID_PARAMETER, anything returned by MS_NETLIB_SEND
-
-struct NETLIBHTTPHEADER
-{
- char *szName;
- char *szValue;
-};
-
-EXTERN_C MIR_APP_DLL(char*) Netlib_GetHeader(const NETLIBHTTPREQUEST *pRec, const char *pszName);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#define REQUEST_RESPONSE 0 // used by structure returned by MS_NETLIB_RECVHTTPHEADERS
-#define REQUEST_GET 1
-#define REQUEST_POST 2
-#define REQUEST_CONNECT 3
-#define REQUEST_HEAD 4
-#define REQUEST_PUT 5
-#define REQUEST_DELETE 6
-#define REQUEST_PATCH 7
-
-#define NLHRF_MANUALHOST 0x00000001 // do not remove any host and/or protocol portion of szUrl before sending it
-#define NLHRF_HTTP11 0x00000010 // use HTTP 1.1
-#define NLHRF_PERSISTENT 0x00000020 // preserve connection on exit, open connection provided in the nlc field of the reply
- // it should be supplied in nlc field of request for reuse or closed if not needed
-#define NLHRF_SSL 0x00000040 // use SSL connection
-#define NLHRF_NOPROXY 0x00000080 // do not use proxy server
-#define NLHRF_REDIRECT 0x00000100 // handle HTTP redirect requests (response 30x), the resulting url provided in szUrl of the response
-#define NLHRF_NODUMP 0x00010000 // never dump this to the log
-#define NLHRF_NODUMPHEADERS 0x00020000 // don't dump http headers (only useful for POSTs and MS_NETLIB_HTTPTRANSACTION)
-#define NLHRF_DUMPPROXY 0x00040000 // this transaction is a proxy communication. For dump filtering only.
-#define NLHRF_DUMPASTEXT 0x00080000 // dump posted and reply data as text. Headers are always dumped as text.
-#define NLHRF_NODUMPSEND 0x00100000 // do not dump sent message.
-
-struct NETLIBHTTPREQUEST
-{
- int cbSize;
- int requestType; // a REQUEST_
- DWORD flags;
- char *szUrl;
- NETLIBHTTPHEADER *headers; // If this is a POST request and headers
- // doesn't contain a Content-Length it'll be added automatically
- int headersCount;
- char *pData; // data to be sent in POST request.
- int dataLength; // must be 0 for REQUEST_GET/REQUEST_CONNECT
- int resultCode;
- char *szResultDescr;
- HNETLIBCONN nlc;
- int timeout;
-
- __forceinline const char *operator[](const char *pszName) {
- return Netlib_GetHeader(this, pszName);
- }
-};
-
-EXTERN_C MIR_APP_DLL(int) Netlib_SendHttpRequest(HNETLIBCONN hConnection, NETLIBHTTPREQUEST *pRec);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Receives HTTP headers
-//
-// Returns a pointer to a NETLIBHTTPREQUEST structure on success, NULL on failure.
-// Call Netlib_FreeHttpRequest() to free this.
-// hConnection must have been returned by MS_NETLIB_OPENCONNECTION
-// nlhr->pData = NULL and nlhr->dataLength = 0 always. The requested data should
-// be retrieved using MS_NETLIB_RECV once the header has been parsed.
-// If the headers haven't finished within 60 seconds the function returns NULL
-// and ERROR_TIMEOUT.
-// Errors: ERROR_INVALID_PARAMETER, any from MS_NETLIB_RECV or select()
-// ERROR_HANDLE_EOF (connection closed before headers complete)
-// ERROR_TIMEOUT (headers still not complete after 60 seconds)
-// ERROR_BAD_FORMAT (invalid character or line ending in headers, or first line is blank)
-// ERROR_BUFFER_OVERFLOW (each header line must be less than 4096 chars long)
-// ERROR_INVALID_DATA (first header line is malformed ("http/[01].[0-9] [0-9]+ .*", or no colon in subsequent line)
-
-EXTERN_C MIR_APP_DLL(NETLIBHTTPREQUEST*) Netlib_RecvHttpHeaders(HNETLIBCONN hConnection, int flags = 0);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Free the memory used by a NETLIBHTTPREQUEST structure
-//
-// Returns true on success, false on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
-// This should only be called on structures returned by
-// MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION. Calling it on an
-// arbitrary structure will have disastrous results.
-// Errors: ERROR_INVALID_PARAMETER
-
-EXTERN_C MIR_APP_DLL(bool) Netlib_FreeHttpRequest(NETLIBHTTPREQUEST*);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// smart pointer for NETLIBHTTPREQUEST via a call of Netlib_FreeHttpRequest()
-
-#ifdef __cplusplus
-class NLHR_PTR
-{
-protected:
- NETLIBHTTPREQUEST *_p;
-
-public:
- __forceinline explicit NLHR_PTR(NETLIBHTTPREQUEST *p) : _p(p) {}
-
- __forceinline NETLIBHTTPREQUEST* operator=(INT_PTR i_p)
- {
- return operator=((NETLIBHTTPREQUEST*)i_p);
- }
- __forceinline NETLIBHTTPREQUEST* operator=(NETLIBHTTPREQUEST *p)
- {
- if (_p)
- Netlib_FreeHttpRequest(_p);
- _p = p;
- return _p;
- }
- __forceinline operator NETLIBHTTPREQUEST*() const { return _p; }
- __forceinline NETLIBHTTPREQUEST* operator->() const { return _p; }
- __forceinline ~NLHR_PTR()
- {
- Netlib_FreeHttpRequest(_p);
- }
-};
-
-struct MIR_APP_EXPORT MHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
-{
- MHttpRequest();
- ~MHttpRequest();
-
- CMStringA m_szUrl;
- CMStringA m_szParam;
- void *pUserInfo = nullptr;
-
- void AddHeader(const char *szName, const char *szValue);
-};
-
-template <class T>
-class MTHttpRequest : public MHttpRequest
-{
-public:
- __forceinline MTHttpRequest()
- {}
-
- typedef void (T::*MTHttpRequestHandler)(NETLIBHTTPREQUEST*, struct AsyncHttpRequest*);
- MTHttpRequestHandler m_pFunc = nullptr;
-};
-
-MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const INT_PARAM&);
-MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const INT64_PARAM&);
-MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const CHAR_PARAM&);
-MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const WCHAR_PARAM&);
-
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Do an entire HTTP transaction
-//
-// Returns a pointer to another NETLIBHTTPREQUEST structure on success, NULL on failure.
-// Call Netlib_FreeHttpRequest() to free this.
-// hUser must have been returned by MS_NETLIB_REGISTERUSER
-// nlhr.szUrl should be a full HTTP URL. If it does not start with http:// , that
-// will be assumed (but it's best not to use this fact, for reasons of
-// extensibility).
-// This function is the equivalent of MS_NETLIB_OPENCONNECTION,
-// MS_NETLIB_SENDHTTPREQ, MS_NETLIB_RECVHTTPHEADERS, MS_NETLIB_RECV,
-// MS_NETLIB_CLOSEHANDLE
-// nlhr.headers will be augmented with the following headers unless they have
-// already been set by the caller:
-// "Host" (regardless of whether it is requested in nlhr.flags)
-// "User-Agent" (of the form "Miranda/0.1.2.2 (alpha)" or "Miranda/0.1.2.2")
-// "Content-Length" (for POSTs only. Set to nlhr.dataLength)
-// If you do not want to send one of these headers, create a nlhr.headers with
-// szValue = NULL.
-// In the return value headers, headerCount, pData, dataLength, resultCode and
-// szResultDescr are all valid.
-// In the return value pData[dataLength] == 0 always, as an extra safeguard
-// against programming slips.
-// Note that the function can succeed (ie not return NULL) yet result in an HTTP
-// error code. You should check that resultCode == 2xx before proceeding.
-// Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, anything from the above
-// list of functions
-
-EXTERN_C MIR_APP_DLL(NETLIBHTTPREQUEST*) Netlib_HttpTransaction(HNETLIBUSER hNlu, NETLIBHTTPREQUEST *pRequest);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Send data over a connection
-//
-// Returns the number of bytes sent on success, SOCKET_ERROR on failure
-// Errors: ERROR_INVALID_PARAMETER
-// anything from send(), nlu.pfnHttpGatewayWrapSend()
-// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx)
-// anything from socket(), connect(),
-// MS_NETLIB_SENDHTTPREQUEST, MS_NETLIB_RECVHTTPHEADERS
-// flags:
-
-#define MSG_NOHTTPGATEWAYWRAP 0x010000 // don't wrap the outgoing packet using nlu.pfnHttpGatewayWrapSend
-#define MSG_NODUMP 0x020000 // don't dump this packet to the log
-#define MSG_DUMPPROXY 0x040000 // this is proxy communiciation. For dump filtering only.
-#define MSG_DUMPASTEXT 0x080000 // this is textual data, don't dump as hex
-#define MSG_RAW 0x100000 // send as raw data, bypass any HTTP proxy stuff
-#define MSG_DUMPSSL 0x200000 // this is SSL traffic. For dump filtering only.
-#define MSG_NOTITLE 0x400000 // skip date, time & protocol from dump
-
-EXTERN_C MIR_APP_DLL(int) Netlib_Send(HNETLIBCONN hConn, const char *buf, int len, int flags = 0);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Receive data over a connection
-//
-// Returns the number of bytes read on success, SOCKET_ERROR on failure,
-// 0 if the connection has been closed
-// Flags supported: MSG_PEEK, MSG_NODUMP, MSG_DUMPPROXY, MSG_NOHTTPGATEWAYWRAP,
-// MSG_DUMPASTEXT, MSG_RAW
-// On using MSG_NOHTTPGATEWAYWRAP: Because packets through an HTTP proxy are
-// batched and cached and stuff, using this flag is not a guarantee that it
-// will be obeyed, and if it is it may even be propogated to future calls
-// even if you don't specify it then. Because of this, the flag should be
-// considered an all-or-nothing thing: either use it for the entire duration
-// of a connection, or not at all.
-// Errors: ERROR_INVALID_PARAMETER, anything from recv()
-// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx)
-// ERROR_INVALID_DATA (no Content-Length header in reply)
-// ERROR_NOT_ENOUGH_MEMORY (Content-Length very large)
-// ERROR_HANDLE_EOF (connection closed before Content-Length bytes recved)
-// anything from select(), MS_NETLIB_RECVHTTPHEADERS,
-// nlu.pfnHttpGatewayUnwrapRecv, socket(), connect(),
-// MS_NETLIB_SENDHTTPREQUEST
-
-EXTERN_C MIR_APP_DLL(int) Netlib_Recv(HNETLIBCONN hConn, char *buf, int len, int flags = 0);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Determine the status of one or more connections
-// Returns the number of ready connections, SOCKET_ERROR on failure, 0 if the timeout expired.
-// All handles passed to this function must have been returned by either
-// MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT.
-// The last handle in each list must be followed by either NULL or INVALID_HANDLE_VALUE.
-// Errors: ERROR_INVALID_HANDLE, ERROR_INVALID_DATA, anything from select()
-
-struct NETLIBSELECT
-{
- DWORD dwTimeout; // in milliseconds, INFINITE is acceptable
- HNETLIBCONN hReadConns[FD_SETSIZE + 1];
- HNETLIBCONN hWriteConns[FD_SETSIZE + 1];
- HNETLIBCONN hExceptConns[FD_SETSIZE + 1];
-};
-
-EXTERN_C MIR_APP_DLL(int) Netlib_Select(NETLIBSELECT *nls);
-
-struct NETLIBSELECTEX
-{
- DWORD dwTimeout; // in milliseconds, INFINITE is acceptable
- HNETLIBCONN hReadConns[FD_SETSIZE + 1];
- HNETLIBCONN hWriteConns[FD_SETSIZE + 1];
- HNETLIBCONN hExceptConns[FD_SETSIZE + 1];
-
- BOOL hReadStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */
- BOOL hWriteStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */
- BOOL hExceptStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */
-};
-
-EXTERN_C MIR_APP_DLL(int) Netlib_SelectEx(NETLIBSELECTEX *nls);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Shutdown connection
-
-EXTERN_C MIR_APP_DLL(void) Netlib_Shutdown(HNETLIBCONN h);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Create a packet receiver
-//
-// Returns a HANDLE on success, NULL on failure
-// The packet receiver implements the common situation where you have variable
-// length packets coming in over a connection and you want to split them up
-// in order to handle them.
-// The major limitation is that the buffer is created in memory, so you can't
-// have arbitrarily large packets.
-// Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY
-
-EXTERN_C MIR_APP_DLL(HANDLE) Netlib_CreatePacketReceiver(HNETLIBCONN hConnection, int iMaxSize);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Get the next set of packets from a packet receiver
-//
-// Returns the total number of bytes available in the buffer, 0 if the
-// connection was closed, SOCKET_ERROR on error.
-// hPacketRecver must have been returned by MS_NETLIB_CREATEPACKETRECVER
-// If nlpr.bytesUsed is set to zero and the buffer is already full up to
-// maxPacketSize, it is assumed that too large a packet has been received. All
-// data in the buffer is discarded and receiving is begun anew. This will
-// probably cause alignment problems so if you think this is likely to happen
-// then you should deal with it yourself.
-// Closing the packet receiver will not close the associated connection, but
-// will discard any bytes still in the buffer, so if you intend to carry on
-// reading from that connection, make sure you have processed the buffer first.
-// This function is the equivalent of a memmove() to remove the first bytesUsed
-// from the buffer, select() if dwTimeout is not INFINITE, then MS_NETLIB_RECV.
-// Errors: ERROR_INVALID_PARAMETER, ERROR_TIMEOUT,
-// anything from select(), MS_NETLIB_RECV
-
-struct NETLIBPACKETRECVER
-{
- DWORD dwTimeout; // fill before calling. In milliseconds. INFINITE is valid
- int bytesUsed; // fill before calling. This many bytes are removed from the start of the buffer. Set to 0 on return
- int bytesAvailable; // equal to the return value, unless the return value is 0
- int bufferSize; // same as parameter to MS_NETLIB_CREATEPACKETRECVER
- BYTE *buffer; // contains the recved data
-};
-
-EXTERN_C MIR_APP_DLL(int) Netlib_GetMorePackets(HANDLE hReceiver, NETLIBPACKETRECVER *nlprParam);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Sets a gateway polling timeout interval
-//
-// Returns previous timeout value
-// Errors: -1
-
-EXTERN_C MIR_APP_DLL(int) Netlib_SetPollingTimeout(HNETLIBCONN hConnection, int iTimeout);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// netlib log funcitons
-
-EXTERN_C MIR_APP_DLL(int) Netlib_Log(HNETLIBUSER hUser, const char *pszStr);
-EXTERN_C MIR_APP_DLL(int) Netlib_LogW(HNETLIBUSER hUser, const wchar_t *pwszStr);
-
-EXTERN_C MIR_APP_DLL(int) Netlib_Logf(HNETLIBUSER hUser, _Printf_format_string_ const char *fmt, ...);
-EXTERN_C MIR_APP_DLL(int) Netlib_LogfW(HNETLIBUSER hUser, _Printf_format_string_ const wchar_t *fmt, ...);
-
-EXTERN_C MIR_APP_DLL(void) Netlib_Dump(HNETLIBCONN nlc, const void *buf, size_t len, bool bIsSent, int flags);
-
-// Inits a required security provider. Right now only NTLM is supported
-// Returns HANDLE = NULL on error or non-null value on success
-// Known providers: Basic, NTLM, Negotiate, Kerberos, GSSAPI - (Kerberos SASL)
-EXTERN_C MIR_APP_DLL(HANDLE) Netlib_InitSecurityProvider(const wchar_t *szProviderName, const wchar_t *szPrincipal = nullptr);
-
-// Destroys a security provider's handle, provided by Netlib_InitSecurityProvider.
-// Right now only NTLM is supported
-EXTERN_C MIR_APP_DLL(void) Netlib_DestroySecurityProvider(HANDLE hProvider);
-
-// Returns the NTLM response string. The result value should be freed using mir_free
-EXTERN_C MIR_APP_DLL(char*) Netlib_NtlmCreateResponse(HANDLE hProvider, const char *szChallenge, wchar_t *szLogin, wchar_t *szPass, unsigned &complete);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// SSL/TLS support
-
-#if !defined(HSSL_DEFINED)
-DECLARE_HANDLE(HSSL);
-#endif
-
-// Makes connection SSL
-// Returns 0 on failure 1 on success
-EXTERN_C MIR_APP_DLL(int) Netlib_StartSsl(HNETLIBCONN hConnection, const char *host);
-
-// negotiates SSL session, verifies cert, returns NULL if failed
-EXTERN_C MIR_APP_DLL(HSSL) Netlib_SslConnect(SOCKET s, const char* host, int verify);
-
-// return true if there is either unsend or buffered received data (ie. after peek)
-EXTERN_C MIR_APP_DLL(BOOL) Netlib_SslPending(HSSL ssl);
-
-// reads number of bytes, keeps in buffer if peek != 0
-EXTERN_C MIR_APP_DLL(int) Netlib_SslRead(HSSL ssl, char *buf, int num, int peek);
-
-// writes data to the SSL socket
-EXTERN_C MIR_APP_DLL(int) Netlib_SslWrite(HSSL ssl, const char *buf, int num);
-
-// closes SSL session, but keeps socket open
-EXTERN_C MIR_APP_DLL(void) Netlib_SslShutdown(HSSL ssl);
-
-// frees all data associated with the SSL socket
-EXTERN_C MIR_APP_DLL(void) Netlib_SslFree(HSSL ssl);
-
-// gets TLS channel binging data for a socket
-EXTERN_C MIR_APP_DLL(void*) Netlib_GetTlsUnique(HNETLIBCONN nlc, int &cbLen);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// WebSocket support
-
-struct WSHeader
-{
- WSHeader()
- {
- memset(this, 0, sizeof(*this));
- }
-
- bool bIsFinal, bIsMasked;
- int opCode, firstByte;
- size_t payloadSize, headerSize;
-};
-
-// connects to a WebSocket server
-EXTERN_C MIR_APP_DLL(NETLIBHTTPREQUEST*) WebSocket_Connect(HNETLIBUSER, const char *szHost, NETLIBHTTPHEADER *pHeaders = nullptr);
-
-// validates that the provided buffer contains full WebSocket datagram
-EXTERN_C MIR_APP_DLL(bool) WebSocket_InitHeader(WSHeader &hdr, const void *pData, size_t bufSize);
-
-// sends a packet to WebSocket
-EXTERN_C MIR_APP_DLL(void) WebSocket_SendText(HNETLIBCONN nlc, const char *pData);
-EXTERN_C MIR_APP_DLL(void) WebSocket_SendBinary(HNETLIBCONN nlc, const void *pData, size_t strLen);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Netlib hooks (0.8+)
-
-// WARNING: these hooks are being called in the context of the calling thread, without switching
-// to the first thread, like all another events do. The hook procedure should be ready for the
-// multithreaded mode
-//
-// Parameters:
-// wParam: NETLIBNOTIFY* - points to the data being sent/received
-// lParam: NETLIBUSER* - points to the protocol definition
-
-struct NETLIBNOTIFY
-{
- const char *buf;
- int len;
- int flags;
- int result; // amount of bytes really sent/received
-};
-
-#define ME_NETLIB_FASTRECV "Netlib/OnRecv" // being called on every receive
-#define ME_NETLIB_FASTSEND "Netlib/OnSend" // being called on every send
-#define ME_NETLIB_FASTDUMP "Netlib/OnDump" // being called on every dump
-
-struct NETLIBCONNECTIONEVENTINFO
-{
- BOOL connected; // 1-opening socket 0-closing socket
- BOOL listening; // 1-bind 0-connect
- SOCKADDR_IN local; // local IP+port (always used)
- SOCKADDR_IN remote; // remote IP+port (only connect (opening + closing only if no proxy))
- SOCKADDR_IN proxy; // proxy IP+port (only connect when used)
- char *szSettingsModule; // name of the registered Netlib user that requested the action
-};
-
-//This event is sent as a new port is bound or a new connection opened.
-//It is NOT sent for sigle HTTP(S) requests.
-//wParam=(WPARAM)(NETLIBCONNECTIONEVENTINFO*)hInfo
-//lParam=(LPARAM)0 (not used)
-#define ME_NETLIB_EVENT_CONNECTED "Netlib/Event/Connected"
-
-//This event is sent if coneection or listening socket is closed.
-//It is NOT sent for sigle HTTP(S) requests.
-//wParam=(WPARAM)(NETLIBCONNECTIONEVENTINFO*)hInfo
-//lParam=(LPARAM)0 (not used)
-#define ME_NETLIB_EVENT_DISCONNECTED "Netlib/Event/Disconnected"
-
-#endif // M_NETLIB_H__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+Copyright (c) 2000-12 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 M_NETLIB_H__
+#define M_NETLIB_H__ 1
+
+#include "m_utils.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// this module was created in 0.1.2.2
+// All error codes are returned via GetLastError() (or WSAGetLastError():
+// they're the same).
+// This module is thread-safe where it is sensible for it to be so. This
+// basically means that you can call anything from any thread, but don't try
+// to predict what will happen if you try to recv() on the same connection from
+// two different threads at the same time.
+// Note that because the vast majority of the routines in this module return
+// a pointer, I have decided to diverge from the rest of Miranda and go with
+// the convention that functions return false on failure and nonzero on success.
+
+struct NETLIBHTTPREQUEST;
+struct NETLIBOPENCONNECTION;
+
+#define NETLIB_USER_AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.112 Safari/537.36"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Initialises the netlib for a set of connections
+// Returns a HNETLIBUSER to be used for future netlib calls, NULL on failure
+// NOTE: Netlib is loaded after any plugins, so you need to wait until
+// ME_SYSTEM_MODULESLOADED before calling this function
+// Netlib settings are stored under the module szSettingsModule
+// All netlib settings being with "NL".
+// The default settings for registered users that don't have any settings stored
+// in the database are the same as those displayed by the <All connections> page
+// of the netlib options page.
+// Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, ERROR_DUP_NAME
+
+struct NETLIBUSER
+{
+ char *szSettingsModule; // used for db settings and log
+ MAllStrings szDescriptiveName; // used in options dialog, already translated
+ DWORD flags;
+ int minIncomingPorts; // only if NUF_INCOMING. Will be used for validation of user input.
+};
+
+#define NUF_INCOMING 0x01 // binds incoming ports
+#define NUF_OUTGOING 0x02 // makes outgoing plain connections
+#define NUF_NOOPTIONS 0x08 // don't create an options page for this. szDescriptiveName is never used.
+#define NUF_HTTPCONNS 0x10 // at least some connections are made for HTTP communication. Enables the HTTP proxy option in options.
+#define NUF_NOHTTPSOPTION 0x20 // disable the HTTPS proxy option in options. Use this if all communication is HTTP.
+#define NUF_UNICODE 0x40 // if set ptszDescriptiveName points to Unicode, otherwise it points to ANSI string
+
+EXTERN_C MIR_APP_DLL(HNETLIBUSER) Netlib_RegisterUser(const NETLIBUSER *pDescr);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Assign a Netlib user handle a set of dynamic HTTP headers to be used with all
+//
+// HTTP connections that enable the HTTP-use-sticky headers flag.
+// The headers persist until cleared with lParam = NULL.
+//
+// All memory should be allocated by the caller using malloc() from MS_SYSTEM_GET_MMI
+// Once it has passed to Netlib, Netlib is the owner of it, the caller should not refer to the memory
+// In any way after this point.
+//
+// NOTE: The szHeaders parameter should be a NULL terminated string following the HTTP header syntax.
+// This string will be injected verbatim, thus the user should be aware of setting strings that are not
+// headers. This service is NOT THREAD SAFE, only a single thread is expected to set the headers and a single
+// thread reading the pointer internally, stopping race conditions and mutual exclusion don't happen.
+//
+// Version 0.3.2a+ (2003/10/27)
+//
+
+EXTERN_C MIR_APP_DLL(int) Netlib_SetStickyHeaders(HNETLIBUSER nlu, const char *szHeaders);
+
+/* Notes on HTTP gateway usage
+When a connection is initiated through an HTTP proxy using
+MS_NETLIB_OPENCONNECTION, netlib will GET nlu.szHttpGatewayHello and read
+the replied headers. Once this succeeds nlu.pfnHttpGatewayInit will be called
+with a valid handle to the connection, the NETLIBOPENCONNECTION structure that
+MS_NETLIB_OPENCONNECTION was called with, and the replied HTTP headers as its
+parameters. This function is responsible for recving and parsing the data then
+calling MS_NETLIB_SETHTTPPROXYINFO with the appropriate information.
+nlu.pfnHttpGatewayInit should return nonzero on success. If it returns zero
+then the entire connection attempt will return signalling failure. If your
+function needs to return an error code it can do so via SetLastError().
+If nlu.pfnHttpGatewayInit returns success without having called
+MS_NETLIB_SETHTTPPROXYINFO then the connection attempt will fail anyway.
+If you need more fine-tuned control over the GET/POST URLs than just appending
+sequence numbers you can call MS_NETLIB_SETHTTPPROXYINFO from within your
+wrap/unwrap functions (see below).
+
+Just prior to MS_NETLIB_OPENCONNECTION returning nlu.pfnHttpGatewayBegin is
+called with the handle to the connection and the NETLIBOPENCONNECTION structure
+as its parameters. This is for gateways that need special non-protocol
+initialisation. If you do send any packets in this function, you probably want
+to remember to use the MSG_NOHTTPGATEWAYWRAP flag. This function pointer can be
+NULL if this functionality isn't needed. This function must return nonzero on
+success. If it fails the connect attempt will return failure without changing
+LastError.
+
+Whenever MS_NETLIB_SEND is called on a connection through an HTTP proxy and
+the MSG_NOHTTPGATEWAYWRAP flags is not set and nlu.pfnHttpGatewayWrapSend is
+not NULL, nlu.pfnHttpGatewayWrapSend will be called *instead* of sending the
+data. It is this function's responsibility to wrap the sending data
+appropriately for transmission and call pfnNetlibSend to send it again.
+The flags parameter to nlu.pfnHttpGatewayWrapSend should be passed straight
+through to the pfnNetlibSend call. It has already been ORed with
+MSG_NOHTTPGATEWAYWRAP. nlu.pfnHttpGatewayWrapSend should return the a
+number of the same type as MS_NETLIB_SEND, ie the number of bytes sent or
+SOCKET_ERROR. The number of wrapping bytes should be subtracted so that the
+return value appears as if the proxy wasn't there.
+pfnNetlibSend() is identical to CallService(MS_NETLIB_SEND, ...) but it's
+quicker to call using this pointer than to do the CallService() lookup again.
+
+Whenever an HTTP reply is received inside MS_NETLIB_RECV the headers and data
+are read into memory. If the headers indicate success then the data is passed
+to nlu.pfnHttpGatewayUnwrapRecv (if it's non-NULL) for processing. This
+function should remove (and do other processing if necessary) all HTTP proxy
+specific headers and return a pointer to the buffer whose size is returned in
+*outBufLen. If the buffer needs to be resized then NetlibRealloc() should be
+used for that purpose, *not* your own CRT's realloc(). NetlibRealloc() behaves
+identically to realloc() so it's possible to free the original buffer and
+create a new one if that's the most sensible way to write your parser.
+If errors are encountered you should SetLastError() and return NULL;
+MS_NETLIB_RECV will return SOCKET_ERROR. If the passed buffer unwraps to
+contain no actual data you should set *outBufLen to 0 but make sure you return
+some non-NULL buffer that can be freed.
+
+When you call MS_NETLIB_SEND or MS_NETLIB_RECV from any of these functions, you
+should use the MSG_DUMPPROXY flag so that the logging is neat.
+*/
+
+#define PROXYTYPE_SOCKS4 1
+#define PROXYTYPE_SOCKS5 2
+#define PROXYTYPE_HTTP 3
+#define PROXYTYPE_HTTPS 4
+#define PROXYTYPE_IE 5
+
+struct NETLIBUSERSETTINGS
+{
+ int cbSize; // to be filled in before calling
+ int useProxy; // 1 or 0
+ int proxyType; // a PROXYTYPE_
+ char *szProxyServer; // can be NULL
+ int wProxyPort; // host byte order
+ int useProxyAuth; // 1 or 0. Always 0 for SOCKS4
+ char *szProxyAuthUser; // can be NULL, always used by SOCKS4
+ char *szProxyAuthPassword; // can be NULL
+ int useProxyAuthNtlm; // 1 or 0, only used by HTTP, HTTPS
+ int dnsThroughProxy; // 1 or 0
+ int specifyIncomingPorts; // 1 or 0
+ char *szIncomingPorts; // can be NULL. Of form "1024-1050, 1060-1070, 2000"
+ int specifyOutgoingPorts; // 0.3.3a+
+ char *szOutgoingPorts; // 0.3.3a+
+ int enableUPnP; // 0.6.1+ only for NUF_INCOMING
+ int validateSSL;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Gets the user-configured settings for a netlib user
+//
+// Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
+// The pointers referred to in the returned struct will remain valid until
+// the hUser handle is closed, or until the user changes the settings in the
+// options page, so it's best not to rely on them for too long.
+// Errors: ERROR_INVALID_PARAMETER
+
+EXTERN_C MIR_APP_DLL(int) Netlib_GetUserSettings(HNETLIBUSER nlu, NETLIBUSERSETTINGS *result);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//Gets the user-configured settings for a netlib user idetified by name
+//
+//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
+//This function behaves like Netlib_GetUserSettings but the user is identified
+//by the name provided by registration. When the name is not found NETLIBUSERSETTINGS is set to NULL.
+//Errors: ERROR_INVALID_PARAMETER
+
+EXTERN_C MIR_APP_DLL(int) Netlib_GetUserSettingsByName(char * UserSettingsName, NETLIBUSERSETTINGS *result);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Changes the user-configurable settings for a netlib user
+//
+// Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
+// This function is only really useful for people that specify NUF_NOOPTIONS
+// and want to create their own options.
+// Even if a setting is not active (eg szProxyAuthPassword when useProxyAuth is
+// zero) that settings is still set for use in the options dialog.
+// Errors: ERROR_INVALID_PARAMETER
+
+EXTERN_C MIR_APP_DLL(int) Netlib_SetUserSettings(HNETLIBUSER nlu, const NETLIBUSERSETTINGS *result);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//Changes the user-configurable settings for a netlib user idetified by name
+//
+//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
+//This function behaves like Netlib_SetUserSettings but the user is identified
+//by the name provided by registration. Nothing will be changed when the name is not found.
+//Errors: ERROR_INVALID_PARAMETER
+
+EXTERN_C MIR_APP_DLL(int) Netlib_SetUserSettingsByName(char * UserSettingsName, NETLIBUSERSETTINGS *result);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Closes a netlib handle
+//
+// Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
+// This function should be called on all handles returned by netlib functions
+// once you are done with them. If it's called on a socket-type handle, the
+// socket will be closed.
+// Errors: ERROR_INVALID_PARAMETER
+
+EXTERN_C MIR_APP_DLL(int) Netlib_CloseHandle(HANDLE h);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Open a port and wait for connections on it
+//
+// Returns a HANDLE on success, NULL on failure
+// hUser should have been returned by MS_NETLIB_REGISTERUSER
+// This function does the equivalent of socket(), bind(), getsockname(),
+// listen(), accept()
+// Internally this function creates a new thread which waits around in accept()
+// for new connections. When one is received it calls nlb.pfnNewConnection *from
+// this new thread* and then loops back to wait again.
+// Close the returned handle to end the thread and close the open port.
+// Errors: ERROR_INVALID_PARAMETER, any returned by socket() or bind() or
+// listen() or getsockname()
+//
+// Notes:
+//
+// During development of 0.3.1a+ (2003/07/04) passing wPort != 0
+// will result in an attempt to bind on the port given in wPort
+// if this port is taken then you will get an error, so be sure to check
+// for such conditions.
+//
+// passing wPort != 0 is for people who need to open a set port for
+// daemon activities, usually passing wPort == 0 is what you want and
+// will result in a free port given by the TCP/IP socket layer and/or
+// seeded from the user selected port ranges.
+//
+// also note that wPort if != 0, will have be converted to network byte order
+//
+/* pExtra was added during 0.3.4+, prior its just two args, since we use the cdecl convention
+it shouldnt matter */
+
+typedef void (*NETLIBNEWCONNECTIONPROC)(HNETLIBCONN hNewConnection, DWORD dwRemoteIP, void *pExtra);
+
+struct NETLIBBIND
+{
+ NETLIBNEWCONNECTIONPROC pfnNewConnection;
+
+ // function to call when there's a new connection. Params are: the
+ // new connection, IP of remote machine (host byte order)
+ DWORD dwInternalIP; // set on return, host byte order
+ DWORD dwExternalIP; // set on return, host byte order
+ WORD wPort, wExPort; // set on return, host byte order
+ void *pExtra; // argument is sent to callback
+};
+
+EXTERN_C MIR_APP_DLL(HNETLIBBIND) Netlib_BindPort(HNETLIBUSER nlu, NETLIBBIND *nlb);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Open a connection
+//
+// Returns a HNETLIBCONN to the new connection on success, NULL on failure
+// hUser must have been returned by MS_NETLIB_REGISTERUSER
+// Internally this function is the equivalent of socket(), gethostbyname(),
+// connect()
+// If NLOCF_HTTP is set and hUser is configured for an HTTP or HTTPS proxy then
+// this function will connect() to the proxy server only, without performing any
+// initialisation conversation.
+// If hUser is configured for an HTTP proxy and does not support HTTP gateways
+// and you try to open a connection without specifying NLOCF_HTTP then this
+// function will first attempt to open an HTTPS connection, if that fails it
+// will try a direct connection, if that fails it will return failure with the
+// error from the connect() during the direct connection attempt.
+// Errors: ERROR_INVALID_PARAMETER, any returned by socket(), gethostbyname(),
+// connect(), MS_NETLIB_SEND, MS_NETLIB_RECV, select()
+// ERROR_TIMEOUT (during proxy communication)
+// ERROR_BAD_FORMAT (very invalid proxy reply)
+// ERROR_ACCESS_DENIED (by proxy)
+// ERROR_CONNECTION_UNAVAIL (socks proxy can't connect to identd)
+// ERROR_INVALID_ACCESS (proxy refused identd auth)
+// ERROR_INVALID_DATA (proxy returned invalid code)
+// ERROR_INVALID_ID_AUTHORITY (proxy requires use of auth method that's not supported)
+// ERROR_GEN_FAILURE (socks5/https general failure)
+// ERROR_CALL_NOT_IMPLEMENTED (socks5 command not supported)
+// ERROR_INVALID_ADDRESS (socks5 address type not supported)
+// HTTP: anything from nlu.pfnHttpGatewayInit, nlu.pfnHttpGatewayBegin,
+// MS_NETLIB_SENDHTTPREQUEST or MS_NETLIB_RECVHTTPHEADERS
+
+#define NLOCF_HTTP 0x0001 // this connection will be used for HTTP communications. If configured for an HTTP/HTTPS proxy the connection is opened as if there was no proxy.
+#define NLOCF_STICKYHEADERS 0x0002 // this connection should send the sticky headers associated with NetLib user apart of any HTTP request
+#define NLOCF_V2 0x0004 // this connection understands the newer structure, newer cbSize isnt enough
+#define NLOCF_UDP 0x0008 // this connection is UDP
+#define NLOCF_SSL 0x0010 // this connection is SSL
+
+struct NETLIBOPENCONNECTION
+{
+ const char *szHost; // can contain the string representation of an IP
+ WORD wPort; // host byte order
+ DWORD flags;
+ unsigned int timeout;
+ /* optional, called in the context of the thread that issued the attempt, if it returns 0 the connection attempt is
+ stopped, the remaining timeout value can also be adjusted */
+ int (*waitcallback) (unsigned int *timeout);
+};
+
+EXTERN_C MIR_APP_DLL(HNETLIBCONN) Netlib_OpenConnection(HNETLIBUSER nlu, const NETLIBOPENCONNECTION *nloc);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Sets the required information for an HTTP proxy connection
+//
+// Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
+// This function is designed to be called from within pfnHttpGatewayInit
+// See notes below MS_NETLIB_REGISTERUSER.
+// Errors: ERROR_INVALID_PARAMETER
+
+#define NLHPIF_USEGETSEQUENCE 0x0001 // append sequence numbers to GET requests
+#define NLHPIF_USEPOSTSEQUENCE 0x0002 // append sequence numbers to POST requests
+#define NLHPIF_GETPOSTSAMESEQUENCE 0x0004 // GET and POST use the same sequence
+#define NLHPIF_HTTP11 0x0008 // HTTP 1.1 proxy
+
+struct NETLIBHTTPPROXYINFO
+{
+ DWORD flags;
+ int firstGetSequence, firstPostSequence;
+ int combinePackets;
+ char *szHttpPostUrl;
+ char *szHttpGetUrl;
+};
+
+EXTERN_C MIR_APP_DLL(int) Netlib_SetHttpProxyInfo(HNETLIBCONN hConnection, const NETLIBHTTPPROXYINFO *nlhpi);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Gets the SOCKET associated with a netlib handle
+//
+// Returns the SOCKET on success, INVALID_SOCKET on failure
+// hNetlibHandle should have been returned by MS_NETLIB_BINDPORT or
+// MS_NETLIB_OPENCONNECTION only.
+// Be careful how you use this socket because you might be connected via an
+// HTTP proxy in which case calling send() or recv() will totally break things.
+// Errors: ERROR_INVALID_PARAMETER
+
+EXTERN_C MIR_APP_DLL(UINT_PTR) Netlib_GetSocket(HNETLIBCONN hConnection);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#define Netlib_GetBase64DecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3)
+#define Netlib_GetBase64EncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1)
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Gets HNETLIBUSER owner of a connection
+
+EXTERN_C MIR_APP_DLL(HNETLIBUSER) Netlib_GetConnNlu(HNETLIBCONN hConn);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Gets the fake User-Agent header field to make some sites happy
+
+EXTERN_C MIR_APP_DLL(char*) Netlib_GetUserAgent();
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Converts numerical representation of IP in SOCKADDR_INET into string representation with IP and port
+// IPv4 will be supplied in formats address:port or address
+// IPv6 will be supplied in formats [address]:port or [address]
+// Returns pointer to the string or NULL if not successful
+
+struct sockaddr_in;
+EXTERN_C MIR_APP_DLL(char*) Netlib_AddressToString(sockaddr_in *addr);
+EXTERN_C MIR_APP_DLL(bool) Netlib_StringToAddress(const char *str, sockaddr_in *addr);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Gets connection Information
+// IPv4 will be supplied in formats address:port or address
+// IPv6 will be supplied in formats [address]:port or [address]
+// Returns 0 if successful
+
+struct NETLIBCONNINFO
+{
+ char szIpPort[64];
+ unsigned dwIpv4;
+ WORD wPort;
+};
+
+EXTERN_C MIR_APP_DLL(int) Netlib_GetConnectionInfo(HNETLIBCONN hConnection, NETLIBCONNINFO *connInfo);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Gets connection Information
+//
+// Returns (INT_PTR)(NETLIBIPLIST*) numeric IP address address array
+// the last element of the array is all 0s, 0 if not successful
+
+struct NETLIBIPLIST
+{
+ unsigned cbNum;
+ char szIp[1][64];
+};
+
+EXTERN_C MIR_APP_DLL(NETLIBIPLIST*) Netlib_GetMyIp(bool bGlobalOnly);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Send an HTTP request over a connection
+//
+// Returns number of bytes sent on success, SOCKET_ERROR on failure
+// hConnection must have been returned by MS_NETLIB_OPENCONNECTION
+// Note that if you use NLHRF_SMARTAUTHHEADER and NTLM authentication is in use
+// then the full NTLM authentication transaction occurs, comprising sending the
+// domain, receiving the challenge, then sending the response.
+// nlhr.resultCode and nlhr.szResultDescr are ignored by this function.
+// Errors: ERROR_INVALID_PARAMETER, anything returned by MS_NETLIB_SEND
+
+struct NETLIBHTTPHEADER
+{
+ char *szName;
+ char *szValue;
+};
+
+EXTERN_C MIR_APP_DLL(char*) Netlib_GetHeader(const NETLIBHTTPREQUEST *pRec, const char *pszName);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#define REQUEST_RESPONSE 0 // used by structure returned by MS_NETLIB_RECVHTTPHEADERS
+#define REQUEST_GET 1
+#define REQUEST_POST 2
+#define REQUEST_CONNECT 3
+#define REQUEST_HEAD 4
+#define REQUEST_PUT 5
+#define REQUEST_DELETE 6
+#define REQUEST_PATCH 7
+
+#define NLHRF_MANUALHOST 0x00000001 // do not remove any host and/or protocol portion of szUrl before sending it
+#define NLHRF_HTTP11 0x00000010 // use HTTP 1.1
+#define NLHRF_PERSISTENT 0x00000020 // preserve connection on exit, open connection provided in the nlc field of the reply
+ // it should be supplied in nlc field of request for reuse or closed if not needed
+#define NLHRF_SSL 0x00000040 // use SSL connection
+#define NLHRF_NOPROXY 0x00000080 // do not use proxy server
+#define NLHRF_REDIRECT 0x00000100 // handle HTTP redirect requests (response 30x), the resulting url provided in szUrl of the response
+#define NLHRF_NODUMP 0x00010000 // never dump this to the log
+#define NLHRF_NODUMPHEADERS 0x00020000 // don't dump http headers (only useful for POSTs and MS_NETLIB_HTTPTRANSACTION)
+#define NLHRF_DUMPPROXY 0x00040000 // this transaction is a proxy communication. For dump filtering only.
+#define NLHRF_DUMPASTEXT 0x00080000 // dump posted and reply data as text. Headers are always dumped as text.
+#define NLHRF_NODUMPSEND 0x00100000 // do not dump sent message.
+
+struct NETLIBHTTPREQUEST
+{
+ int cbSize;
+ int requestType; // a REQUEST_
+ DWORD flags;
+ char *szUrl;
+ NETLIBHTTPHEADER *headers; // If this is a POST request and headers
+ // doesn't contain a Content-Length it'll be added automatically
+ int headersCount;
+ char *pData; // data to be sent in POST request.
+ int dataLength; // must be 0 for REQUEST_GET/REQUEST_CONNECT
+ int resultCode;
+ char *szResultDescr;
+ HNETLIBCONN nlc;
+ int timeout;
+
+ __forceinline const char *operator[](const char *pszName) {
+ return Netlib_GetHeader(this, pszName);
+ }
+};
+
+EXTERN_C MIR_APP_DLL(int) Netlib_SendHttpRequest(HNETLIBCONN hConnection, NETLIBHTTPREQUEST *pRec);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Receives HTTP headers
+//
+// Returns a pointer to a NETLIBHTTPREQUEST structure on success, NULL on failure.
+// Call Netlib_FreeHttpRequest() to free this.
+// hConnection must have been returned by MS_NETLIB_OPENCONNECTION
+// nlhr->pData = NULL and nlhr->dataLength = 0 always. The requested data should
+// be retrieved using MS_NETLIB_RECV once the header has been parsed.
+// If the headers haven't finished within 60 seconds the function returns NULL
+// and ERROR_TIMEOUT.
+// Errors: ERROR_INVALID_PARAMETER, any from MS_NETLIB_RECV or select()
+// ERROR_HANDLE_EOF (connection closed before headers complete)
+// ERROR_TIMEOUT (headers still not complete after 60 seconds)
+// ERROR_BAD_FORMAT (invalid character or line ending in headers, or first line is blank)
+// ERROR_BUFFER_OVERFLOW (each header line must be less than 4096 chars long)
+// ERROR_INVALID_DATA (first header line is malformed ("http/[01].[0-9] [0-9]+ .*", or no colon in subsequent line)
+
+EXTERN_C MIR_APP_DLL(NETLIBHTTPREQUEST*) Netlib_RecvHttpHeaders(HNETLIBCONN hConnection, int flags = 0);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Free the memory used by a NETLIBHTTPREQUEST structure
+//
+// Returns true on success, false on failure (!! this is different to most of the rest of Miranda, but consistent with netlib)
+// This should only be called on structures returned by
+// MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION. Calling it on an
+// arbitrary structure will have disastrous results.
+// Errors: ERROR_INVALID_PARAMETER
+
+EXTERN_C MIR_APP_DLL(bool) Netlib_FreeHttpRequest(NETLIBHTTPREQUEST*);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// smart pointer for NETLIBHTTPREQUEST via a call of Netlib_FreeHttpRequest()
+
+#ifdef __cplusplus
+class NLHR_PTR
+{
+protected:
+ NETLIBHTTPREQUEST *_p;
+
+public:
+ __forceinline explicit NLHR_PTR(NETLIBHTTPREQUEST *p) : _p(p) {}
+
+ __forceinline NETLIBHTTPREQUEST* operator=(INT_PTR i_p)
+ {
+ return operator=((NETLIBHTTPREQUEST*)i_p);
+ }
+ __forceinline NETLIBHTTPREQUEST* operator=(NETLIBHTTPREQUEST *p)
+ {
+ if (_p)
+ Netlib_FreeHttpRequest(_p);
+ _p = p;
+ return _p;
+ }
+ __forceinline operator NETLIBHTTPREQUEST*() const { return _p; }
+ __forceinline NETLIBHTTPREQUEST* operator->() const { return _p; }
+ __forceinline ~NLHR_PTR()
+ {
+ Netlib_FreeHttpRequest(_p);
+ }
+};
+
+struct MIR_APP_EXPORT MHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
+{
+ MHttpRequest();
+ ~MHttpRequest();
+
+ CMStringA m_szUrl;
+ CMStringA m_szParam;
+ void *pUserInfo = nullptr;
+
+ void AddHeader(const char *szName, const char *szValue);
+};
+
+template <class T>
+class MTHttpRequest : public MHttpRequest
+{
+public:
+ __forceinline MTHttpRequest()
+ {}
+
+ typedef void (T::*MTHttpRequestHandler)(NETLIBHTTPREQUEST*, struct AsyncHttpRequest*);
+ MTHttpRequestHandler m_pFunc = nullptr;
+};
+
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const INT_PARAM&);
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const INT64_PARAM&);
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const CHAR_PARAM&);
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const WCHAR_PARAM&);
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Do an entire HTTP transaction
+//
+// Returns a pointer to another NETLIBHTTPREQUEST structure on success, NULL on failure.
+// Call Netlib_FreeHttpRequest() to free this.
+// hUser must have been returned by MS_NETLIB_REGISTERUSER
+// nlhr.szUrl should be a full HTTP URL. If it does not start with http:// , that
+// will be assumed (but it's best not to use this fact, for reasons of
+// extensibility).
+// This function is the equivalent of MS_NETLIB_OPENCONNECTION,
+// MS_NETLIB_SENDHTTPREQ, MS_NETLIB_RECVHTTPHEADERS, MS_NETLIB_RECV,
+// MS_NETLIB_CLOSEHANDLE
+// nlhr.headers will be augmented with the following headers unless they have
+// already been set by the caller:
+// "Host" (regardless of whether it is requested in nlhr.flags)
+// "User-Agent" (of the form "Miranda/0.1.2.2 (alpha)" or "Miranda/0.1.2.2")
+// "Content-Length" (for POSTs only. Set to nlhr.dataLength)
+// If you do not want to send one of these headers, create a nlhr.headers with
+// szValue = NULL.
+// In the return value headers, headerCount, pData, dataLength, resultCode and
+// szResultDescr are all valid.
+// In the return value pData[dataLength] == 0 always, as an extra safeguard
+// against programming slips.
+// Note that the function can succeed (ie not return NULL) yet result in an HTTP
+// error code. You should check that resultCode == 2xx before proceeding.
+// Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, anything from the above
+// list of functions
+
+EXTERN_C MIR_APP_DLL(NETLIBHTTPREQUEST*) Netlib_HttpTransaction(HNETLIBUSER hNlu, NETLIBHTTPREQUEST *pRequest);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Send data over a connection
+//
+// Returns the number of bytes sent on success, SOCKET_ERROR on failure
+// Errors: ERROR_INVALID_PARAMETER
+// anything from send(), nlu.pfnHttpGatewayWrapSend()
+// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx)
+// anything from socket(), connect(),
+// MS_NETLIB_SENDHTTPREQUEST, MS_NETLIB_RECVHTTPHEADERS
+// flags:
+
+#define MSG_NOHTTPGATEWAYWRAP 0x010000 // don't wrap the outgoing packet using nlu.pfnHttpGatewayWrapSend
+#define MSG_NODUMP 0x020000 // don't dump this packet to the log
+#define MSG_DUMPPROXY 0x040000 // this is proxy communiciation. For dump filtering only.
+#define MSG_DUMPASTEXT 0x080000 // this is textual data, don't dump as hex
+#define MSG_RAW 0x100000 // send as raw data, bypass any HTTP proxy stuff
+#define MSG_DUMPSSL 0x200000 // this is SSL traffic. For dump filtering only.
+#define MSG_NOTITLE 0x400000 // skip date, time & protocol from dump
+
+EXTERN_C MIR_APP_DLL(int) Netlib_Send(HNETLIBCONN hConn, const char *buf, int len, int flags = 0);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Receive data over a connection
+//
+// Returns the number of bytes read on success, SOCKET_ERROR on failure,
+// 0 if the connection has been closed
+// Flags supported: MSG_PEEK, MSG_NODUMP, MSG_DUMPPROXY, MSG_NOHTTPGATEWAYWRAP,
+// MSG_DUMPASTEXT, MSG_RAW
+// On using MSG_NOHTTPGATEWAYWRAP: Because packets through an HTTP proxy are
+// batched and cached and stuff, using this flag is not a guarantee that it
+// will be obeyed, and if it is it may even be propogated to future calls
+// even if you don't specify it then. Because of this, the flag should be
+// considered an all-or-nothing thing: either use it for the entire duration
+// of a connection, or not at all.
+// Errors: ERROR_INVALID_PARAMETER, anything from recv()
+// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx)
+// ERROR_INVALID_DATA (no Content-Length header in reply)
+// ERROR_NOT_ENOUGH_MEMORY (Content-Length very large)
+// ERROR_HANDLE_EOF (connection closed before Content-Length bytes recved)
+// anything from select(), MS_NETLIB_RECVHTTPHEADERS,
+// nlu.pfnHttpGatewayUnwrapRecv, socket(), connect(),
+// MS_NETLIB_SENDHTTPREQUEST
+
+EXTERN_C MIR_APP_DLL(int) Netlib_Recv(HNETLIBCONN hConn, char *buf, int len, int flags = 0);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Determine the status of one or more connections
+// Returns the number of ready connections, SOCKET_ERROR on failure, 0 if the timeout expired.
+// All handles passed to this function must have been returned by either
+// MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT.
+// The last handle in each list must be followed by either NULL or INVALID_HANDLE_VALUE.
+// Errors: ERROR_INVALID_HANDLE, ERROR_INVALID_DATA, anything from select()
+
+struct NETLIBSELECT
+{
+ DWORD dwTimeout; // in milliseconds, INFINITE is acceptable
+ HNETLIBCONN hReadConns[FD_SETSIZE + 1];
+ HNETLIBCONN hWriteConns[FD_SETSIZE + 1];
+ HNETLIBCONN hExceptConns[FD_SETSIZE + 1];
+};
+
+EXTERN_C MIR_APP_DLL(int) Netlib_Select(NETLIBSELECT *nls);
+
+struct NETLIBSELECTEX
+{
+ DWORD dwTimeout; // in milliseconds, INFINITE is acceptable
+ HNETLIBCONN hReadConns[FD_SETSIZE + 1];
+ HNETLIBCONN hWriteConns[FD_SETSIZE + 1];
+ HNETLIBCONN hExceptConns[FD_SETSIZE + 1];
+
+ BOOL hReadStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */
+ BOOL hWriteStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */
+ BOOL hExceptStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */
+};
+
+EXTERN_C MIR_APP_DLL(int) Netlib_SelectEx(NETLIBSELECTEX *nls);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Shutdown connection
+
+EXTERN_C MIR_APP_DLL(void) Netlib_Shutdown(HNETLIBCONN h);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Create a packet receiver
+//
+// Returns a HANDLE on success, NULL on failure
+// The packet receiver implements the common situation where you have variable
+// length packets coming in over a connection and you want to split them up
+// in order to handle them.
+// The major limitation is that the buffer is created in memory, so you can't
+// have arbitrarily large packets.
+// Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY
+
+EXTERN_C MIR_APP_DLL(HANDLE) Netlib_CreatePacketReceiver(HNETLIBCONN hConnection, int iMaxSize);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Get the next set of packets from a packet receiver
+//
+// Returns the total number of bytes available in the buffer, 0 if the
+// connection was closed, SOCKET_ERROR on error.
+// hPacketRecver must have been returned by MS_NETLIB_CREATEPACKETRECVER
+// If nlpr.bytesUsed is set to zero and the buffer is already full up to
+// maxPacketSize, it is assumed that too large a packet has been received. All
+// data in the buffer is discarded and receiving is begun anew. This will
+// probably cause alignment problems so if you think this is likely to happen
+// then you should deal with it yourself.
+// Closing the packet receiver will not close the associated connection, but
+// will discard any bytes still in the buffer, so if you intend to carry on
+// reading from that connection, make sure you have processed the buffer first.
+// This function is the equivalent of a memmove() to remove the first bytesUsed
+// from the buffer, select() if dwTimeout is not INFINITE, then MS_NETLIB_RECV.
+// Errors: ERROR_INVALID_PARAMETER, ERROR_TIMEOUT,
+// anything from select(), MS_NETLIB_RECV
+
+struct NETLIBPACKETRECVER
+{
+ DWORD dwTimeout; // fill before calling. In milliseconds. INFINITE is valid
+ int bytesUsed; // fill before calling. This many bytes are removed from the start of the buffer. Set to 0 on return
+ int bytesAvailable; // equal to the return value, unless the return value is 0
+ int bufferSize; // same as parameter to MS_NETLIB_CREATEPACKETRECVER
+ BYTE *buffer; // contains the recved data
+};
+
+EXTERN_C MIR_APP_DLL(int) Netlib_GetMorePackets(HANDLE hReceiver, NETLIBPACKETRECVER *nlprParam);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Sets a gateway polling timeout interval
+//
+// Returns previous timeout value
+// Errors: -1
+
+EXTERN_C MIR_APP_DLL(int) Netlib_SetPollingTimeout(HNETLIBCONN hConnection, int iTimeout);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// netlib log funcitons
+
+EXTERN_C MIR_APP_DLL(int) Netlib_Log(HNETLIBUSER hUser, const char *pszStr);
+EXTERN_C MIR_APP_DLL(int) Netlib_LogW(HNETLIBUSER hUser, const wchar_t *pwszStr);
+
+EXTERN_C MIR_APP_DLL(int) Netlib_Logf(HNETLIBUSER hUser, _Printf_format_string_ const char *fmt, ...);
+EXTERN_C MIR_APP_DLL(int) Netlib_LogfW(HNETLIBUSER hUser, _Printf_format_string_ const wchar_t *fmt, ...);
+
+EXTERN_C MIR_APP_DLL(void) Netlib_Dump(HNETLIBCONN nlc, const void *buf, size_t len, bool bIsSent, int flags);
+
+// Inits a required security provider. Right now only NTLM is supported
+// Returns HANDLE = NULL on error or non-null value on success
+// Known providers: Basic, NTLM, Negotiate, Kerberos, GSSAPI - (Kerberos SASL)
+EXTERN_C MIR_APP_DLL(HANDLE) Netlib_InitSecurityProvider(const wchar_t *szProviderName, const wchar_t *szPrincipal = nullptr);
+
+// Destroys a security provider's handle, provided by Netlib_InitSecurityProvider.
+// Right now only NTLM is supported
+EXTERN_C MIR_APP_DLL(void) Netlib_DestroySecurityProvider(HANDLE hProvider);
+
+// Returns the NTLM response string. The result value should be freed using mir_free
+EXTERN_C MIR_APP_DLL(char*) Netlib_NtlmCreateResponse(HANDLE hProvider, const char *szChallenge, wchar_t *szLogin, wchar_t *szPass, unsigned &complete);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// SSL/TLS support
+
+#if !defined(HSSL_DEFINED)
+DECLARE_HANDLE(HSSL);
+#endif
+
+// Makes connection SSL
+// Returns 0 on failure 1 on success
+EXTERN_C MIR_APP_DLL(int) Netlib_StartSsl(HNETLIBCONN hConnection, const char *host);
+
+// negotiates SSL session, verifies cert, returns NULL if failed
+EXTERN_C MIR_APP_DLL(HSSL) Netlib_SslConnect(SOCKET s, const char* host, int verify);
+
+// return true if there is either unsend or buffered received data (ie. after peek)
+EXTERN_C MIR_APP_DLL(BOOL) Netlib_SslPending(HSSL ssl);
+
+// reads number of bytes, keeps in buffer if peek != 0
+EXTERN_C MIR_APP_DLL(int) Netlib_SslRead(HSSL ssl, char *buf, int num, int peek);
+
+// writes data to the SSL socket
+EXTERN_C MIR_APP_DLL(int) Netlib_SslWrite(HSSL ssl, const char *buf, int num);
+
+// closes SSL session, but keeps socket open
+EXTERN_C MIR_APP_DLL(void) Netlib_SslShutdown(HSSL ssl);
+
+// frees all data associated with the SSL socket
+EXTERN_C MIR_APP_DLL(void) Netlib_SslFree(HSSL ssl);
+
+// gets TLS channel binging data for a socket
+EXTERN_C MIR_APP_DLL(void*) Netlib_GetTlsUnique(HNETLIBCONN nlc, int &cbLen);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// WebSocket support
+
+struct WSHeader
+{
+ WSHeader()
+ {
+ memset(this, 0, sizeof(*this));
+ }
+
+ bool bIsFinal, bIsMasked;
+ int opCode, firstByte;
+ size_t payloadSize, headerSize;
+};
+
+// connects to a WebSocket server
+EXTERN_C MIR_APP_DLL(NETLIBHTTPREQUEST*) WebSocket_Connect(HNETLIBUSER, const char *szHost, NETLIBHTTPHEADER *pHeaders = nullptr);
+
+// validates that the provided buffer contains full WebSocket datagram
+EXTERN_C MIR_APP_DLL(bool) WebSocket_InitHeader(WSHeader &hdr, const void *pData, size_t bufSize);
+
+// sends a packet to WebSocket
+EXTERN_C MIR_APP_DLL(void) WebSocket_SendText(HNETLIBCONN nlc, const char *pData);
+EXTERN_C MIR_APP_DLL(void) WebSocket_SendBinary(HNETLIBCONN nlc, const void *pData, size_t strLen);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Netlib hooks (0.8+)
+
+// WARNING: these hooks are being called in the context of the calling thread, without switching
+// to the first thread, like all another events do. The hook procedure should be ready for the
+// multithreaded mode
+//
+// Parameters:
+// wParam: NETLIBNOTIFY* - points to the data being sent/received
+// lParam: NETLIBUSER* - points to the protocol definition
+
+struct NETLIBNOTIFY
+{
+ const char *buf;
+ int len;
+ int flags;
+ int result; // amount of bytes really sent/received
+};
+
+#define ME_NETLIB_FASTRECV "Netlib/OnRecv" // being called on every receive
+#define ME_NETLIB_FASTSEND "Netlib/OnSend" // being called on every send
+#define ME_NETLIB_FASTDUMP "Netlib/OnDump" // being called on every dump
+
+struct NETLIBCONNECTIONEVENTINFO
+{
+ BOOL connected; // 1-opening socket 0-closing socket
+ BOOL listening; // 1-bind 0-connect
+ SOCKADDR_IN local; // local IP+port (always used)
+ SOCKADDR_IN remote; // remote IP+port (only connect (opening + closing only if no proxy))
+ SOCKADDR_IN proxy; // proxy IP+port (only connect when used)
+ char *szSettingsModule; // name of the registered Netlib user that requested the action
+};
+
+//This event is sent as a new port is bound or a new connection opened.
+//It is NOT sent for sigle HTTP(S) requests.
+//wParam=(WPARAM)(NETLIBCONNECTIONEVENTINFO*)hInfo
+//lParam=(LPARAM)0 (not used)
+#define ME_NETLIB_EVENT_CONNECTED "Netlib/Event/Connected"
+
+//This event is sent if coneection or listening socket is closed.
+//It is NOT sent for sigle HTTP(S) requests.
+//wParam=(WPARAM)(NETLIBCONNECTIONEVENTINFO*)hInfo
+//lParam=(LPARAM)0 (not used)
+#define ME_NETLIB_EVENT_DISCONNECTED "Netlib/Event/Disconnected"
+
+#endif // M_NETLIB_H__
diff --git a/include/m_protoint.h b/include/m_protoint.h
index 0f9444c448..90955ad34e 100644
--- a/include/m_protoint.h
+++ b/include/m_protoint.h
@@ -1,310 +1,310 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-Copyright (c) 2000-08 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 M_PROTOINT_H__
-#define M_PROTOINT_H__ 1
-
-#include <m_system.h>
-#include <m_protosvc.h>
-#include <m_database.h>
-#include <m_genmenu.h>
-#include <m_utils.h>
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// protocol helpers
-
-struct PROTO_INTERFACE;
-
-// Call it in the very beginning of your proto's constructor
-EXTERN_C MIR_APP_DLL(void) ProtoConstructor(PROTO_INTERFACE *pThis, const char *pszModuleName, const wchar_t *ptszUserName);
-
-// Call it in the very end of your proto's destructor
-EXTERN_C MIR_APP_DLL(void) ProtoDestructor(PROTO_INTERFACE *pThis);
-
-#if defined( __cplusplus )
-typedef void (__cdecl PROTO_INTERFACE::*ProtoThreadFunc)(void*);
-EXTERN_C MIR_APP_DLL(void) ProtoForkThread(PROTO_INTERFACE *pThis, ProtoThreadFunc, void *param);
-EXTERN_C MIR_APP_DLL(HANDLE) ProtoForkThreadEx(PROTO_INTERFACE *pThis, ProtoThreadFunc, void *param, UINT* threadID);
-EXTERN_C MIR_APP_DLL(void) ProtoWindowAdd(PROTO_INTERFACE *pThis, HWND hwnd);
-EXTERN_C MIR_APP_DLL(void) ProtoWindowRemove(PROTO_INTERFACE *pThis, HWND hwnd);
-
-typedef int (__cdecl PROTO_INTERFACE::*ProtoEventFunc)(WPARAM, LPARAM);
-EXTERN_C MIR_APP_DLL(void) ProtoHookEvent(PROTO_INTERFACE *pThis, const char* szName, ProtoEventFunc pFunc);
-EXTERN_C MIR_APP_DLL(HANDLE) ProtoCreateHookableEvent(PROTO_INTERFACE *pThis, const char* szService);
-
-typedef INT_PTR (__cdecl PROTO_INTERFACE::*ProtoServiceFunc)(WPARAM, LPARAM);
-EXTERN_C MIR_APP_DLL(void) ProtoCreateService(PROTO_INTERFACE *pThis, const char* szService, ProtoServiceFunc);
-
-typedef INT_PTR (__cdecl PROTO_INTERFACE::*ProtoServiceFuncParam)(WPARAM, LPARAM, LPARAM);
-EXTERN_C MIR_APP_DLL(void) ProtoCreateServiceParam(PROTO_INTERFACE *pThis, const char* szService, ProtoServiceFuncParam, LPARAM);
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// interface declaration
-
-enum ProtoMenuItemType
-{
- PROTO_MENU_REQ_AUTH,
- PROTO_MENU_GRANT_AUTH,
- PROTO_MENU_REVOKE_AUTH,
- PROTO_MENU_LOAD_HISTORY
-};
-
-struct MIR_APP_EXPORT PROTO_INTERFACE : public MZeroedObject
-{
-
-protected:
- MWindowList m_hWindowList = 0; // list of all windows which belong to this protocol's instance
-
-public:
- int m_iStatus; // current protocol status
- int m_iDesiredStatus; // status to be set after logging in
- int m_iXStatus; // extanded status
- int m_iVersion; // version 2 or higher designate support of Unicode services
- wchar_t* m_tszUserName; // human readable protocol's name
- char* m_szModuleName; // internal protocol name, also its database module name
- HANDLE m_hProtoIcon = 0; // icon to be displayed in the account manager
- HNETLIBUSER m_hNetlibUser = 0; // network agent
- HGENMENU m_hmiMainMenu = 0; // if protocol menus are displayed in the main menu, this is the root
-
- PROTO_INTERFACE(const char *pszModuleName, const wchar_t *ptszUserName);
- ~PROTO_INTERFACE();
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Helpers
-
- __forceinline INT_PTR ProtoBroadcastAck(MCONTACT hContact, int type, int hResult, HANDLE hProcess, LPARAM lParam = 0) {
- return ::ProtoBroadcastAck(m_szModuleName, hContact, type, hResult, hProcess, lParam); }
- __forceinline void ProtoBroadcastAsync(MCONTACT hContact, int type, int hResult, HANDLE hProcess, LPARAM lParam = 0) {
- return ::ProtoBroadcastAsync(m_szModuleName, hContact, type, hResult, hProcess, lParam); }
-
- __forceinline INT_PTR delSetting(const char *name) { return db_unset(NULL, m_szModuleName, name); }
- __forceinline INT_PTR delSetting(MCONTACT hContact, const char *name) { return db_unset(hContact, m_szModuleName, name); }
-
- __forceinline bool getBool(const char *name, bool defaultValue = false) {
- return db_get_b(NULL, m_szModuleName, name, defaultValue) != 0; }
- __forceinline bool getBool(MCONTACT hContact, const char *name, bool defaultValue = false) {
- return db_get_b(hContact, m_szModuleName, name, defaultValue) != 0; }
-
- __forceinline bool isChatRoom(MCONTACT hContact) { return getBool(hContact, "ChatRoom", false); }
-
- __forceinline int getByte(const char *name, BYTE defaultValue = 0) {
- return db_get_b(NULL, m_szModuleName, name, defaultValue); }
- __forceinline int getByte(MCONTACT hContact, const char *name, BYTE defaultValue = 0) {
- return db_get_b(hContact, m_szModuleName, name, defaultValue); }
-
- __forceinline int getWord(const char *name, WORD defaultValue = 0) {
- return db_get_w(NULL, m_szModuleName, name, defaultValue); }
- __forceinline int getWord(MCONTACT hContact, const char *name, WORD defaultValue = 0) {
- return db_get_w(hContact, m_szModuleName, name, defaultValue); }
-
- __forceinline DWORD getDword(const char *name, DWORD defaultValue = 0) {
- return db_get_dw(NULL, m_szModuleName, name, defaultValue); }
- __forceinline DWORD getDword(MCONTACT hContact, const char *name, DWORD defaultValue = 0) {
- return db_get_dw(hContact, m_szModuleName, name, defaultValue); }
-
- __forceinline INT_PTR getString(const char *name, DBVARIANT *result) {
- return db_get_s(NULL, m_szModuleName, name, result, DBVT_ASCIIZ); }
- __forceinline INT_PTR getString(MCONTACT hContact, const char *name, DBVARIANT *result) {
- return db_get_s(hContact, m_szModuleName, name, result, DBVT_ASCIIZ); }
-
- __forceinline INT_PTR getUString(const char *name, DBVARIANT *result) {
- return db_get_s(NULL, m_szModuleName, name, result, DBVT_UTF8); }
- __forceinline INT_PTR getUString(MCONTACT hContact, const char *name, DBVARIANT *result) {
- return db_get_s(hContact, m_szModuleName, name, result, DBVT_UTF8); }
-
- __forceinline INT_PTR getWString(const char *name, DBVARIANT *result) {
- return db_get_s(NULL, m_szModuleName, name, result, DBVT_WCHAR); }
- __forceinline INT_PTR getWString(MCONTACT hContact, const char *name, DBVARIANT *result) {
- return db_get_s(hContact, m_szModuleName, name, result, DBVT_WCHAR); }
-
- __forceinline char* getStringA(const char *name, const char *szValue = nullptr) {
- return db_get_sa(NULL, m_szModuleName, name, szValue); }
- __forceinline char* getStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr) {
- return db_get_sa(hContact, m_szModuleName, name, szValue); }
-
- __forceinline char* getUStringA(const char *name, const char *szValue = nullptr) {
- return db_get_utfa(NULL, m_szModuleName, name, szValue); }
- __forceinline char* getUStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr) {
- return db_get_utfa(hContact, m_szModuleName, name, szValue); }
-
- __forceinline wchar_t* getWStringA(const char *name, const wchar_t *szValue = nullptr) {
- return db_get_wsa(NULL, m_szModuleName, name, szValue); }
- __forceinline wchar_t* getWStringA(MCONTACT hContact, const char *name, const wchar_t *szValue = nullptr) {
- return db_get_wsa(hContact, m_szModuleName, name, szValue); }
-
- __forceinline CMStringA getMStringA(const char *name, const char *szValue = nullptr) {
- return db_get_sm(NULL, m_szModuleName, name, szValue); }
- __forceinline CMStringA getMStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr) {
- return db_get_sm(hContact, m_szModuleName, name, szValue); }
-
- __forceinline CMStringW getMStringW(const char *name, const wchar_t *szValue = nullptr) {
- return db_get_wsm(NULL, m_szModuleName, name, szValue); }
- __forceinline CMStringW getMStringW(MCONTACT hContact, const char *name, const wchar_t *szValue = nullptr) {
- return db_get_wsm(hContact, m_szModuleName, name, szValue); }
-
- __forceinline void setByte(const char *name, BYTE value) { db_set_b(NULL, m_szModuleName, name, value); }
- __forceinline void setByte(MCONTACT hContact, const char *name, BYTE value) { db_set_b(hContact, m_szModuleName, name, value); }
-
- __forceinline void setWord(const char *name, WORD value) { db_set_w(NULL, m_szModuleName, name, value); }
- __forceinline void setWord(MCONTACT hContact, const char *name, WORD value) { db_set_w(hContact, m_szModuleName, name, value); }
-
- __forceinline void setDword(const char *name, DWORD value) { db_set_dw(NULL, m_szModuleName, name, value); }
- __forceinline void setDword(MCONTACT hContact, const char *name, DWORD value) { db_set_dw(hContact, m_szModuleName, name, value); }
-
- __forceinline void setString(const char *name, const char* value) { db_set_s(NULL, m_szModuleName, name, value); }
- __forceinline void setString(MCONTACT hContact, const char *name, const char* value) { db_set_s(hContact, m_szModuleName, name, value); }
-
- __forceinline void setUString(const char *name, const char* value) { db_set_utf(NULL, m_szModuleName, name, value); }
- __forceinline void setUString(MCONTACT hContact, const char *name, const char* value) { db_set_utf(hContact, m_szModuleName, name, value); }
-
- __forceinline void setWString(const char *name, const wchar_t* value) { db_set_ws(NULL, m_szModuleName, name, value); }
- __forceinline void setWString(MCONTACT hContact, const char *name, const wchar_t* value) { db_set_ws(hContact, m_szModuleName, name, value); }
-
- __forceinline Contacts AccContacts() const { return Contacts(m_szModuleName); }
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Service functions
-
- void debugLogA(const char *szFormat, ...);
- void debugLogW(const wchar_t *wszFormat, ...);
-
- void setAllContactStatuses(int iStatus, bool bSkipChats = true);
-
- void ReportSelfAvatarChanged();
-
- void WindowSubscribe(HWND hwnd);
- void WindowUnsubscribe(HWND hwnd);
-
- HGENMENU GetMenuItem(ProtoMenuItemType);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // Virtual functions
-
- virtual MCONTACT AddToList(int flags, PROTOSEARCHRESULT *psr);
- virtual MCONTACT AddToListByEvent(int flags, int iContact, MEVENT hDbEvent);
-
- virtual int Authorize(MEVENT hDbEvent);
- virtual int AuthDeny(MEVENT hDbEvent, const wchar_t *szReason);
- virtual int AuthRecv(MCONTACT hContact, PROTORECVEVENT *);
- virtual int AuthRequest(MCONTACT hContact, const wchar_t *szMessage);
-
- virtual HANDLE FileAllow(MCONTACT hContact, HANDLE hTransfer, const wchar_t *szPath);
- virtual int FileCancel(MCONTACT hContact, HANDLE hTransfer);
- virtual int FileDeny(MCONTACT hContact, HANDLE hTransfer, const wchar_t *szReason);
- virtual int FileResume(HANDLE hTransfer, int action, const wchar_t *szFilename);
-
- virtual INT_PTR GetCaps(int type, MCONTACT hContact = NULL);
- virtual int GetInfo(MCONTACT hContact, int infoType);
-
- virtual HANDLE SearchBasic(const wchar_t *id);
- virtual HANDLE SearchByEmail(const wchar_t *email);
- virtual HANDLE SearchByName(const wchar_t *nick, const wchar_t *firstName, const wchar_t *lastName);
- virtual HWND SearchAdvanced(HWND owner);
- virtual HWND CreateExtendedSearchUI(HWND owner);
-
- virtual int RecvContacts(MCONTACT hContact, PROTORECVEVENT *);
- virtual int RecvFile(MCONTACT hContact, PROTORECVFILE *);
- virtual MEVENT RecvMsg(MCONTACT hContact, PROTORECVEVENT *);
-
- virtual int SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList);
- virtual HANDLE SendFile(MCONTACT hContact, const wchar_t *szDescription, wchar_t **ppszFiles);
- virtual int SendMsg(MCONTACT hContact, int flags, const char *msg);
-
- virtual int SetApparentMode(MCONTACT hContact, int mode);
- virtual int SetStatus(int iNewStatus);
-
- virtual HANDLE GetAwayMsg(MCONTACT hContact);
- virtual int RecvAwayMsg(MCONTACT hContact, int mode, PROTORECVEVENT *evt);
- virtual int SetAwayMsg(int iStatus, const wchar_t *msg);
-
- virtual int UserIsTyping(MCONTACT hContact, int type);
-
- //////////////////////////////////////////////////////////////////////////////////////
- // events
-
- // builds the account's protocol menu
- virtual void OnBuildProtoMenu(void);
-
- // called when an account's contact is added
- virtual void OnContactAdded(MCONTACT);
-
- // called when an account's contact is deleted
- virtual void OnContactDeleted(MCONTACT);
-
- // called when an event is altered in database
- virtual void OnEventEdited(MCONTACT, MEVENT);
-
- // called when an account gets physically removed from the database
- virtual void OnErase();
-
- // the analog of ME_SYSTEM_MODULESLOADED for an account
- virtual void OnModulesLoaded(void);
-
- // same for ME_SYSTEM_SHUTDOWN
- virtual void OnShutdown(void);
-
- // same for ME_SYSTEM_OKTOEXIT
- virtual bool IsReadyToExit(void);
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Basic class for all protocols written in C++
-
-template<class T> struct PROTO : public PROTO_INTERFACE
-{
- typedef PROTO_INTERFACE CSuper;
-
- __forceinline PROTO(const char *szProto, const wchar_t *tszUserName) :
- PROTO_INTERFACE(szProto, tszUserName)
- {}
-
- __forceinline HANDLE CreateProtoEvent(const char *name) {
- return ::ProtoCreateHookableEvent(this, name); }
-
- typedef int(__cdecl T::*MyEventFunc)(WPARAM, LPARAM);
- __forceinline void HookProtoEvent(const char *name, MyEventFunc pFunc) {
- ::ProtoHookEvent(this, name, (ProtoEventFunc)pFunc); }
-
- typedef void(__cdecl T::*MyThreadFunc)(void*);
- __forceinline void ForkThread(MyThreadFunc pFunc, void *param = nullptr) {
- ::ProtoForkThread(this, (ProtoThreadFunc)pFunc, param); }
- HANDLE __forceinline ForkThreadEx(MyThreadFunc pFunc, void *param, UINT *pThreadId) {
- return ::ProtoForkThreadEx(this, (ProtoThreadFunc)pFunc, param, pThreadId); }
-
- typedef INT_PTR(__cdecl T::*MyServiceFunc)(WPARAM, LPARAM);
- __forceinline void CreateProtoService(const char *name, MyServiceFunc pFunc) {
- ::ProtoCreateService(this, name, (ProtoServiceFunc)pFunc); }
-
- typedef INT_PTR(__cdecl T::*MyServiceFuncParam)(WPARAM, LPARAM, LPARAM);
- __forceinline void CreateProtoServiceParam(const char *name, MyServiceFuncParam pFunc, LPARAM param) {
- ::ProtoCreateServiceParam(this, name, (ProtoServiceFuncParam)pFunc, param); }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_APP_DLL(PROTO_INTERFACE *) Proto_GetInstance(const char *szModule);
-MIR_APP_DLL(PROTO_INTERFACE *) Proto_GetInstance(MCONTACT hContact);
-
-#endif // M_PROTOINT_H__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+Copyright (c) 2000-08 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 M_PROTOINT_H__
+#define M_PROTOINT_H__ 1
+
+#include <m_system.h>
+#include <m_protosvc.h>
+#include <m_database.h>
+#include <m_genmenu.h>
+#include <m_utils.h>
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// protocol helpers
+
+struct PROTO_INTERFACE;
+
+// Call it in the very beginning of your proto's constructor
+EXTERN_C MIR_APP_DLL(void) ProtoConstructor(PROTO_INTERFACE *pThis, const char *pszModuleName, const wchar_t *ptszUserName);
+
+// Call it in the very end of your proto's destructor
+EXTERN_C MIR_APP_DLL(void) ProtoDestructor(PROTO_INTERFACE *pThis);
+
+#if defined( __cplusplus )
+typedef void (MIR_CDECL PROTO_INTERFACE::*ProtoThreadFunc)(void*);
+EXTERN_C MIR_APP_DLL(void) ProtoForkThread(PROTO_INTERFACE *pThis, ProtoThreadFunc, void *param);
+EXTERN_C MIR_APP_DLL(HANDLE) ProtoForkThreadEx(PROTO_INTERFACE *pThis, ProtoThreadFunc, void *param, UINT* threadID);
+EXTERN_C MIR_APP_DLL(void) ProtoWindowAdd(PROTO_INTERFACE *pThis, HWND hwnd);
+EXTERN_C MIR_APP_DLL(void) ProtoWindowRemove(PROTO_INTERFACE *pThis, HWND hwnd);
+
+typedef int (MIR_CDECL PROTO_INTERFACE::*ProtoEventFunc)(WPARAM, LPARAM);
+EXTERN_C MIR_APP_DLL(void) ProtoHookEvent(PROTO_INTERFACE *pThis, const char* szName, ProtoEventFunc pFunc);
+EXTERN_C MIR_APP_DLL(HANDLE) ProtoCreateHookableEvent(PROTO_INTERFACE *pThis, const char* szService);
+
+typedef INT_PTR (MIR_CDECL PROTO_INTERFACE::*ProtoServiceFunc)(WPARAM, LPARAM);
+EXTERN_C MIR_APP_DLL(void) ProtoCreateService(PROTO_INTERFACE *pThis, const char* szService, ProtoServiceFunc);
+
+typedef INT_PTR (MIR_CDECL PROTO_INTERFACE::*ProtoServiceFuncParam)(WPARAM, LPARAM, LPARAM);
+EXTERN_C MIR_APP_DLL(void) ProtoCreateServiceParam(PROTO_INTERFACE *pThis, const char* szService, ProtoServiceFuncParam, LPARAM);
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// interface declaration
+
+enum ProtoMenuItemType
+{
+ PROTO_MENU_REQ_AUTH,
+ PROTO_MENU_GRANT_AUTH,
+ PROTO_MENU_REVOKE_AUTH,
+ PROTO_MENU_LOAD_HISTORY
+};
+
+struct MIR_APP_EXPORT PROTO_INTERFACE : public MZeroedObject
+{
+
+protected:
+ MWindowList m_hWindowList = 0; // list of all windows which belong to this protocol's instance
+
+public:
+ int m_iStatus; // current protocol status
+ int m_iDesiredStatus; // status to be set after logging in
+ int m_iXStatus; // extanded status
+ int m_iVersion; // version 2 or higher designate support of Unicode services
+ wchar_t* m_tszUserName; // human readable protocol's name
+ char* m_szModuleName; // internal protocol name, also its database module name
+ HANDLE m_hProtoIcon = 0; // icon to be displayed in the account manager
+ HNETLIBUSER m_hNetlibUser = 0; // network agent
+ HGENMENU m_hmiMainMenu = 0; // if protocol menus are displayed in the main menu, this is the root
+
+ PROTO_INTERFACE(const char *pszModuleName, const wchar_t *ptszUserName);
+ ~PROTO_INTERFACE();
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Helpers
+
+ __forceinline INT_PTR ProtoBroadcastAck(MCONTACT hContact, int type, int hResult, HANDLE hProcess, LPARAM lParam = 0) {
+ return ::ProtoBroadcastAck(m_szModuleName, hContact, type, hResult, hProcess, lParam); }
+ __forceinline void ProtoBroadcastAsync(MCONTACT hContact, int type, int hResult, HANDLE hProcess, LPARAM lParam = 0) {
+ return ::ProtoBroadcastAsync(m_szModuleName, hContact, type, hResult, hProcess, lParam); }
+
+ __forceinline INT_PTR delSetting(const char *name) { return db_unset(NULL, m_szModuleName, name); }
+ __forceinline INT_PTR delSetting(MCONTACT hContact, const char *name) { return db_unset(hContact, m_szModuleName, name); }
+
+ __forceinline bool getBool(const char *name, bool defaultValue = false) {
+ return db_get_b(NULL, m_szModuleName, name, defaultValue) != 0; }
+ __forceinline bool getBool(MCONTACT hContact, const char *name, bool defaultValue = false) {
+ return db_get_b(hContact, m_szModuleName, name, defaultValue) != 0; }
+
+ __forceinline bool isChatRoom(MCONTACT hContact) { return getBool(hContact, "ChatRoom", false); }
+
+ __forceinline int getByte(const char *name, BYTE defaultValue = 0) {
+ return db_get_b(NULL, m_szModuleName, name, defaultValue); }
+ __forceinline int getByte(MCONTACT hContact, const char *name, BYTE defaultValue = 0) {
+ return db_get_b(hContact, m_szModuleName, name, defaultValue); }
+
+ __forceinline int getWord(const char *name, WORD defaultValue = 0) {
+ return db_get_w(NULL, m_szModuleName, name, defaultValue); }
+ __forceinline int getWord(MCONTACT hContact, const char *name, WORD defaultValue = 0) {
+ return db_get_w(hContact, m_szModuleName, name, defaultValue); }
+
+ __forceinline DWORD getDword(const char *name, DWORD defaultValue = 0) {
+ return db_get_dw(NULL, m_szModuleName, name, defaultValue); }
+ __forceinline DWORD getDword(MCONTACT hContact, const char *name, DWORD defaultValue = 0) {
+ return db_get_dw(hContact, m_szModuleName, name, defaultValue); }
+
+ __forceinline INT_PTR getString(const char *name, DBVARIANT *result) {
+ return db_get_s(NULL, m_szModuleName, name, result, DBVT_ASCIIZ); }
+ __forceinline INT_PTR getString(MCONTACT hContact, const char *name, DBVARIANT *result) {
+ return db_get_s(hContact, m_szModuleName, name, result, DBVT_ASCIIZ); }
+
+ __forceinline INT_PTR getUString(const char *name, DBVARIANT *result) {
+ return db_get_s(NULL, m_szModuleName, name, result, DBVT_UTF8); }
+ __forceinline INT_PTR getUString(MCONTACT hContact, const char *name, DBVARIANT *result) {
+ return db_get_s(hContact, m_szModuleName, name, result, DBVT_UTF8); }
+
+ __forceinline INT_PTR getWString(const char *name, DBVARIANT *result) {
+ return db_get_s(NULL, m_szModuleName, name, result, DBVT_WCHAR); }
+ __forceinline INT_PTR getWString(MCONTACT hContact, const char *name, DBVARIANT *result) {
+ return db_get_s(hContact, m_szModuleName, name, result, DBVT_WCHAR); }
+
+ __forceinline char* getStringA(const char *name, const char *szValue = nullptr) {
+ return db_get_sa(NULL, m_szModuleName, name, szValue); }
+ __forceinline char* getStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr) {
+ return db_get_sa(hContact, m_szModuleName, name, szValue); }
+
+ __forceinline char* getUStringA(const char *name, const char *szValue = nullptr) {
+ return db_get_utfa(NULL, m_szModuleName, name, szValue); }
+ __forceinline char* getUStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr) {
+ return db_get_utfa(hContact, m_szModuleName, name, szValue); }
+
+ __forceinline wchar_t* getWStringA(const char *name, const wchar_t *szValue = nullptr) {
+ return db_get_wsa(NULL, m_szModuleName, name, szValue); }
+ __forceinline wchar_t* getWStringA(MCONTACT hContact, const char *name, const wchar_t *szValue = nullptr) {
+ return db_get_wsa(hContact, m_szModuleName, name, szValue); }
+
+ __forceinline CMStringA getMStringA(const char *name, const char *szValue = nullptr) {
+ return db_get_sm(NULL, m_szModuleName, name, szValue); }
+ __forceinline CMStringA getMStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr) {
+ return db_get_sm(hContact, m_szModuleName, name, szValue); }
+
+ __forceinline CMStringW getMStringW(const char *name, const wchar_t *szValue = nullptr) {
+ return db_get_wsm(NULL, m_szModuleName, name, szValue); }
+ __forceinline CMStringW getMStringW(MCONTACT hContact, const char *name, const wchar_t *szValue = nullptr) {
+ return db_get_wsm(hContact, m_szModuleName, name, szValue); }
+
+ __forceinline void setByte(const char *name, BYTE value) { db_set_b(NULL, m_szModuleName, name, value); }
+ __forceinline void setByte(MCONTACT hContact, const char *name, BYTE value) { db_set_b(hContact, m_szModuleName, name, value); }
+
+ __forceinline void setWord(const char *name, WORD value) { db_set_w(NULL, m_szModuleName, name, value); }
+ __forceinline void setWord(MCONTACT hContact, const char *name, WORD value) { db_set_w(hContact, m_szModuleName, name, value); }
+
+ __forceinline void setDword(const char *name, DWORD value) { db_set_dw(NULL, m_szModuleName, name, value); }
+ __forceinline void setDword(MCONTACT hContact, const char *name, DWORD value) { db_set_dw(hContact, m_szModuleName, name, value); }
+
+ __forceinline void setString(const char *name, const char* value) { db_set_s(NULL, m_szModuleName, name, value); }
+ __forceinline void setString(MCONTACT hContact, const char *name, const char* value) { db_set_s(hContact, m_szModuleName, name, value); }
+
+ __forceinline void setUString(const char *name, const char* value) { db_set_utf(NULL, m_szModuleName, name, value); }
+ __forceinline void setUString(MCONTACT hContact, const char *name, const char* value) { db_set_utf(hContact, m_szModuleName, name, value); }
+
+ __forceinline void setWString(const char *name, const wchar_t* value) { db_set_ws(NULL, m_szModuleName, name, value); }
+ __forceinline void setWString(MCONTACT hContact, const char *name, const wchar_t* value) { db_set_ws(hContact, m_szModuleName, name, value); }
+
+ __forceinline Contacts AccContacts() const { return Contacts(m_szModuleName); }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Service functions
+
+ void debugLogA(const char *szFormat, ...);
+ void debugLogW(const wchar_t *wszFormat, ...);
+
+ void setAllContactStatuses(int iStatus, bool bSkipChats = true);
+
+ void ReportSelfAvatarChanged();
+
+ void WindowSubscribe(HWND hwnd);
+ void WindowUnsubscribe(HWND hwnd);
+
+ HGENMENU GetMenuItem(ProtoMenuItemType);
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Virtual functions
+
+ virtual MCONTACT AddToList(int flags, PROTOSEARCHRESULT *psr);
+ virtual MCONTACT AddToListByEvent(int flags, int iContact, MEVENT hDbEvent);
+
+ virtual int Authorize(MEVENT hDbEvent);
+ virtual int AuthDeny(MEVENT hDbEvent, const wchar_t *szReason);
+ virtual int AuthRecv(MCONTACT hContact, PROTORECVEVENT *);
+ virtual int AuthRequest(MCONTACT hContact, const wchar_t *szMessage);
+
+ virtual HANDLE FileAllow(MCONTACT hContact, HANDLE hTransfer, const wchar_t *szPath);
+ virtual int FileCancel(MCONTACT hContact, HANDLE hTransfer);
+ virtual int FileDeny(MCONTACT hContact, HANDLE hTransfer, const wchar_t *szReason);
+ virtual int FileResume(HANDLE hTransfer, int action, const wchar_t *szFilename);
+
+ virtual INT_PTR GetCaps(int type, MCONTACT hContact = NULL);
+ virtual int GetInfo(MCONTACT hContact, int infoType);
+
+ virtual HANDLE SearchBasic(const wchar_t *id);
+ virtual HANDLE SearchByEmail(const wchar_t *email);
+ virtual HANDLE SearchByName(const wchar_t *nick, const wchar_t *firstName, const wchar_t *lastName);
+ virtual HWND SearchAdvanced(HWND owner);
+ virtual HWND CreateExtendedSearchUI(HWND owner);
+
+ virtual int RecvContacts(MCONTACT hContact, PROTORECVEVENT *);
+ virtual int RecvFile(MCONTACT hContact, PROTORECVFILE *);
+ virtual MEVENT RecvMsg(MCONTACT hContact, PROTORECVEVENT *);
+
+ virtual int SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList);
+ virtual HANDLE SendFile(MCONTACT hContact, const wchar_t *szDescription, wchar_t **ppszFiles);
+ virtual int SendMsg(MCONTACT hContact, int flags, const char *msg);
+
+ virtual int SetApparentMode(MCONTACT hContact, int mode);
+ virtual int SetStatus(int iNewStatus);
+
+ virtual HANDLE GetAwayMsg(MCONTACT hContact);
+ virtual int RecvAwayMsg(MCONTACT hContact, int mode, PROTORECVEVENT *evt);
+ virtual int SetAwayMsg(int iStatus, const wchar_t *msg);
+
+ virtual int UserIsTyping(MCONTACT hContact, int type);
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // events
+
+ // builds the account's protocol menu
+ virtual void OnBuildProtoMenu(void);
+
+ // called when an account's contact is added
+ virtual void OnContactAdded(MCONTACT);
+
+ // called when an account's contact is deleted
+ virtual void OnContactDeleted(MCONTACT);
+
+ // called when an event is altered in database
+ virtual void OnEventEdited(MCONTACT, MEVENT);
+
+ // called when an account gets physically removed from the database
+ virtual void OnErase();
+
+ // the analog of ME_SYSTEM_MODULESLOADED for an account
+ virtual void OnModulesLoaded(void);
+
+ // same for ME_SYSTEM_SHUTDOWN
+ virtual void OnShutdown(void);
+
+ // same for ME_SYSTEM_OKTOEXIT
+ virtual bool IsReadyToExit(void);
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Basic class for all protocols written in C++
+
+template<class T> struct PROTO : public PROTO_INTERFACE
+{
+ typedef PROTO_INTERFACE CSuper;
+
+ __forceinline PROTO(const char *szProto, const wchar_t *tszUserName) :
+ PROTO_INTERFACE(szProto, tszUserName)
+ {}
+
+ __forceinline HANDLE CreateProtoEvent(const char *name) {
+ return ::ProtoCreateHookableEvent(this, name); }
+
+ typedef int(MIR_CDECL T::*MyEventFunc)(WPARAM, LPARAM);
+ __forceinline void HookProtoEvent(const char *name, MyEventFunc pFunc) {
+ ::ProtoHookEvent(this, name, (ProtoEventFunc)pFunc); }
+
+ typedef void(MIR_CDECL T::*MyThreadFunc)(void*);
+ __forceinline void ForkThread(MyThreadFunc pFunc, void *param = nullptr) {
+ ::ProtoForkThread(this, (ProtoThreadFunc)pFunc, param); }
+ HANDLE __forceinline ForkThreadEx(MyThreadFunc pFunc, void *param, UINT *pThreadId) {
+ return ::ProtoForkThreadEx(this, (ProtoThreadFunc)pFunc, param, pThreadId); }
+
+ typedef INT_PTR(MIR_CDECL T::*MyServiceFunc)(WPARAM, LPARAM);
+ __forceinline void CreateProtoService(const char *name, MyServiceFunc pFunc) {
+ ::ProtoCreateService(this, name, (ProtoServiceFunc)pFunc); }
+
+ typedef INT_PTR(MIR_CDECL T::*MyServiceFuncParam)(WPARAM, LPARAM, LPARAM);
+ __forceinline void CreateProtoServiceParam(const char *name, MyServiceFuncParam pFunc, LPARAM param) {
+ ::ProtoCreateServiceParam(this, name, (ProtoServiceFuncParam)pFunc, param); }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_APP_DLL(PROTO_INTERFACE *) Proto_GetInstance(const char *szModule);
+MIR_APP_DLL(PROTO_INTERFACE *) Proto_GetInstance(MCONTACT hContact);
+
+#endif // M_PROTOINT_H__
diff --git a/include/m_string.h b/include/m_string.h
index 21404268cd..9d6244b19b 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -1,958 +1,1040 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-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.
-*/
-
-#pragma once
-
-#ifndef M_STRING_H__
-#define M_STRING_H__
-
-#include <stdio.h>
-#include <string.h>
-#include <mbstring.h>
-#include <wchar.h>
-
-#include <m_core.h>
-
-#ifdef __MINGW32__
-#include <limits.h>
-
-__inline size_t strnlen(const char *string, size_t maxlen)
-{
- const char *end = (const char *)memchr ((const void *)string, '\0', maxlen);
- return end ? (size_t) (end - string) : maxlen;
-}
-__inline size_t wcsnlen(const wchar_t *string, size_t maxlen)
-{
- const wchar_t *end = wmemchr (string, L'\0', maxlen);
- return end ? (size_t) (end - string) : maxlen;
-}
-
-/* FIXME: This may be wrong assumption about Langpack_GetDefaultCodePage */
-#define Langpack_GetDefaultCodePage() CP_THREAD_ACP
-/* FIXME: This is unsafe */
-#define memcpy_s(dest,size,src,count) memcpy(dest,src,count)
-/* FIXME: This is quite silly implementation of _mbsstr */
-#define _mbsstr(str,search) strstr((const char *)str,(const char *)search)
-#define __max(x,y) (((x)<(y))?(y):(x))
-#endif /* __MINGW32__ */
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct CMStringData;
-
-MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize);
-MIR_CORE_DLL(void) mirstr_free(CMStringData *pData);
-MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize);
-MIR_CORE_DLL(CMStringData*) mirstr_getNil();
-
-MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis);
-MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis);
-MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-enum CMStringDataFormat { FORMAT };
-
-struct CMStringData
-{
- int nDataLength; // Length of currently used data in XCHARs (not including terminating null)
- int nAllocLength; // Length of allocated data in XCHARs (not including terminating null)
- long nRefs; // Reference count: negative == locked
-
- __forceinline void* data() { return (this + 1); }
- __forceinline void AddRef() { InterlockedIncrement(&nRefs); }
- __forceinline bool IsLocked() const { return nRefs < 0; }
- __forceinline bool IsShared() const { return nRefs > 1; }
-
- __forceinline void Lock() { mirstr_lock(this); }
- __forceinline void Release() { mirstr_release(this); }
- __forceinline void Unlock() { mirstr_unlock(this); }
-};
-
-template< typename BaseType = char >
-class ChTraitsBase
-{
-public:
- typedef char XCHAR;
- typedef LPSTR PXSTR;
- typedef LPCSTR PCXSTR;
- typedef wchar_t YCHAR;
- typedef LPWSTR PYSTR;
- typedef LPCWSTR PCYSTR;
-};
-
-template<>
-class ChTraitsBase< wchar_t >
-{
-public:
- typedef wchar_t XCHAR;
- typedef LPWSTR PXSTR;
- typedef LPCWSTR PCXSTR;
- typedef char YCHAR;
- typedef LPSTR PYSTR;
- typedef LPCSTR PCYSTR;
-};
-
-template< typename BaseType >
-class CMSimpleStringT
-{
-public:
- typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR;
- typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR;
- typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR;
- typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR;
- typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR;
- typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR;
-
-public:
- explicit CMSimpleStringT();
-
- CMSimpleStringT(const CMSimpleStringT& strSrc);
- CMSimpleStringT(PCXSTR pszSrc);
- CMSimpleStringT(const XCHAR* pchSrc, int nLength);
- ~CMSimpleStringT();
-
- __forceinline operator CMSimpleStringT<BaseType>&()
- { return *(CMSimpleStringT<BaseType>*)this;
- }
-
- CMSimpleStringT& operator=(const CMSimpleStringT& strSrc);
-
- __forceinline CMSimpleStringT& operator=(PCXSTR pszSrc)
- { SetString(pszSrc);
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(const CMSimpleStringT& strSrc)
- { Append(strSrc);
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(PCXSTR pszSrc)
- { Append(pszSrc);
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(char ch)
- { AppendChar(XCHAR(ch));
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(unsigned char ch)
- { AppendChar(XCHAR(ch));
- return *this;
- }
-
- __forceinline CMSimpleStringT& operator+=(wchar_t ch)
- { AppendChar(XCHAR(ch));
- return *this;
- }
-
- __forceinline XCHAR operator[](int iChar) const
- { return m_pszData[iChar];
- }
-
- __forceinline operator PCXSTR() const
- { return m_pszData;
- }
-
- __forceinline PCXSTR c_str() const
- { return m_pszData;
- }
-
- __forceinline int GetAllocLength() const
- { return GetData()->nAllocLength;
- }
-
- __forceinline XCHAR GetAt(int iChar) const
- { return m_pszData[iChar];
- }
-
- __forceinline PXSTR GetBuffer(int nMinBufferLength)
- { return PrepareWrite(nMinBufferLength);
- }
-
- __forceinline int GetLength() const
- { return GetData()->nDataLength;
- }
-
- __forceinline PCXSTR GetString() const
- { return m_pszData;
- }
-
- __forceinline PCXSTR GetTail() const
- { return m_pszData + GetData()->nDataLength;
- }
-
- __forceinline bool IsEmpty() const
- { return GetLength() == 0;
- }
-
- __forceinline void Preallocate(int nLength)
- { PrepareWrite(nLength);
- }
-
- __forceinline void ReleaseBufferSetLength(int nNewLength)
- { SetLength(nNewLength);
- }
-
- void Append(PCXSTR pszSrc);
- void Append(PCXSTR pszSrc, int nLength);
- void AppendChar(XCHAR ch);
- void Append(const CMSimpleStringT& strSrc);
-
- void Empty();
- void FreeExtra();
-
- PXSTR GetBuffer();
- PXSTR GetBufferSetLength(int nLength);
-
- PXSTR LockBuffer();
- void UnlockBuffer();
-
- void ReleaseBuffer(int nNewLength = -1);
-
- void Truncate(int nNewLength);
- void SetAt(int iChar, XCHAR ch);
- void SetString(PCXSTR pszSrc);
- void SetString(PCXSTR pszSrc, int nLength);
-
-public:
- friend CMSimpleStringT operator+(const CMSimpleStringT& str1, const CMSimpleStringT& str2);
- friend CMSimpleStringT operator+(const CMSimpleStringT& str1, PCXSTR psz2);
- friend CMSimpleStringT operator+(PCXSTR psz1, const CMSimpleStringT& str2);
-
- static void __stdcall CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars);
- static void __stdcall CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars);
- static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars);
- static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars);
- static int __stdcall StringLength(const char* psz);
- static int __stdcall StringLength(const wchar_t* psz);
- static int __stdcall StringLengthN(const char* psz, size_t sizeInXChar);
- static int __stdcall StringLengthN(const wchar_t* psz, size_t sizeInXChar);
- static void __stdcall Concatenate(CMSimpleStringT& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2);
-
- // Implementation
-private:
- __forceinline CMStringData* GetData() const
- { return (reinterpret_cast<CMStringData *>(m_pszData)-1);
- }
-
- void Attach(CMStringData* pData);
- void Fork(int nLength);
- PXSTR PrepareWrite(int nLength);
- void PrepareWrite2(int nLength);
- void Reallocate(int nLength);
- void SetLength(int nLength);
- static CMStringData* __stdcall CloneData(CMStringData* pData);
-
-private:
- PXSTR m_pszData;
-};
-
-
-template< typename _CharType = char >
-class ChTraitsCRT : public ChTraitsBase < _CharType >
-{
-public:
- static char* __stdcall CharNext(const char* p)
- {
- return reinterpret_cast<char*>(_mbsinc(reinterpret_cast<const unsigned char*>(p)));
- }
-
- static int __stdcall IsDigit(char ch)
- {
- return _ismbcdigit(ch);
- }
-
- static int __stdcall IsSpace(char ch)
- {
- return _ismbcspace(ch);
- }
-
- static int __stdcall StringCompare(LPCSTR pszA, LPCSTR pszB)
- {
- return _mbscmp(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
- }
-
- static int __stdcall StringCompareIgnore(LPCSTR pszA, LPCSTR pszB)
- {
- return _mbsicmp(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
- }
-
- static int __stdcall StringCollate(LPCSTR pszA, LPCSTR pszB)
- {
- return _mbscoll(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
- }
-
- static int __stdcall StringCollateIgnore(LPCSTR pszA, LPCSTR pszB)
- {
- return _mbsicoll(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
- }
-
- static LPCSTR __stdcall StringFindString(LPCSTR pszBlock, LPCSTR pszMatch)
- {
- return reinterpret_cast<LPCSTR>(_mbsstr(reinterpret_cast<const unsigned char*>(pszBlock),
- reinterpret_cast<const unsigned char*>(pszMatch)));
- }
-
- static LPSTR __stdcall StringFindString(LPSTR pszBlock, LPCSTR pszMatch)
- {
- return const_cast<LPSTR>(StringFindString(const_cast<LPCSTR>(pszBlock), pszMatch));
- }
-
- static LPCSTR __stdcall StringFindChar(LPCSTR pszBlock, char chMatch)
- {
- return reinterpret_cast<LPCSTR>(_mbschr(reinterpret_cast<const unsigned char*>(pszBlock), (unsigned char)chMatch));
- }
-
- static LPCSTR __stdcall StringFindCharRev(LPCSTR psz, char ch)
- {
- return reinterpret_cast<LPCSTR>(_mbsrchr(reinterpret_cast<const unsigned char*>(psz), (unsigned char)ch));
- }
-
- static LPCSTR __stdcall StringScanSet(LPCSTR pszBlock, LPCSTR pszMatch)
- {
- return reinterpret_cast<LPCSTR>(_mbspbrk(reinterpret_cast<const unsigned char*>(pszBlock),
- reinterpret_cast<const unsigned char*>(pszMatch)));
- }
-
- static int __stdcall StringSpanIncluding(LPCSTR pszBlock, LPCSTR pszSet)
- {
- return (int)_mbsspn(reinterpret_cast<const unsigned char*>(pszBlock), reinterpret_cast<const unsigned char*>(pszSet));
- }
-
- static int __stdcall StringSpanExcluding(LPCSTR pszBlock, LPCSTR pszSet)
- {
- return (int)_mbscspn(reinterpret_cast<const unsigned char*>(pszBlock), reinterpret_cast<const unsigned char*>(pszSet));
- }
-
- static LPSTR __stdcall StringUppercase(LPSTR psz)
- {
- CharUpperBuffA(psz, (DWORD)strlen(psz));
- return psz;
- }
-
- static LPSTR __stdcall StringLowercase(LPSTR psz)
- {
- CharLowerBuffA(psz, (DWORD)strlen(psz));
- return psz;
- }
-
- static LPSTR __stdcall StringUppercase(LPSTR psz, size_t size)
- {
- CharUpperBuffA(psz, (DWORD)size);
- return psz;
- }
-
- static LPSTR __stdcall StringLowercase(LPSTR psz, size_t size)
- {
- CharLowerBuffA(psz, (DWORD)size);
- return psz;
- }
-
- static LPSTR __stdcall StringReverse(LPSTR psz)
- {
- return reinterpret_cast<LPSTR>(_mbsrev(reinterpret_cast<unsigned char*>(psz)));
- }
-
- static int __stdcall GetFormattedLength(_Printf_format_string_ LPCSTR pszFormat, va_list args)
- {
- return _vscprintf(pszFormat, args);
- }
-
- static int __stdcall Format(LPSTR pszBuffer, size_t nlength, _Printf_format_string_ LPCSTR pszFormat, va_list args)
- {
- return vsprintf_s(pszBuffer, nlength, pszFormat, args);
- }
-
- static int __stdcall GetBaseTypeLength(LPCSTR pszSrc)
- {
- // Returns required buffer length in XCHARs
- return int(strlen(pszSrc));
- }
-
- static int __stdcall GetBaseTypeLength(LPCSTR pszSrc, int nLength)
- {
- (void)pszSrc;
- // Returns required buffer length in XCHARs
- return nLength;
- }
-
- static int __stdcall GetBaseTypeLength(LPCWSTR pszSource)
- {
- // Returns required buffer length in XCHARs
- return ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
- }
-
- static int __stdcall GetBaseTypeLength(LPCWSTR pszSource, int nLength)
- {
- // Returns required buffer length in XCHARs
- return ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSource, nLength, NULL, 0, NULL, NULL);
- }
-
- static void __stdcall ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1)
- {
- if (nSrcLength == -1) { nSrcLength = 1 + GetBaseTypeLength(pszSrc); }
- // nLen is in XCHARs
- memcpy_s(pszDest, nDestLength*sizeof(char), pszSrc, nSrcLength*sizeof(char));
- }
-
- static void __stdcall ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1)
- {
- // nLen is in XCHARs
- ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL);
- }
-
- static void ConvertToOem(_CharType* pstrString)
- {
- BOOL fSuccess = ::CharToOemA(pstrString, pstrString);
- }
-
- static void ConvertToAnsi(_CharType* pstrString)
- {
- BOOL fSuccess = ::OemToCharA(pstrString, pstrString);
- }
-
- static void ConvertToOem(_CharType* pstrString, size_t size)
- {
- DWORD dwSize = static_cast<DWORD>(size);
- ::CharToOemBuffA(pstrString, pstrString, dwSize);
- }
-
- static void ConvertToAnsi(_CharType* pstrString, size_t size)
- {
- DWORD dwSize = static_cast<DWORD>(size);
- ::OemToCharBuffA(pstrString, pstrString, dwSize);
- }
-
- static void __stdcall FloodCharacters(char ch, int nLength, char* pch)
- {
- // nLength is in XCHARs
- memset(pch, ch, nLength);
- }
-
- static int __stdcall SafeStringLen(LPCSTR psz)
- {
- // returns length in bytes
- return (psz != NULL) ? int(strlen(psz)) : 0;
- }
-
- static int __stdcall SafeStringLen(LPCWSTR psz)
- {
- // returns length in wchar_ts
- return (psz != NULL) ? int(wcslen(psz)) : 0;
- }
-
- static int __stdcall GetCharLen(const wchar_t* pch)
- {
- // returns char length
- return 1;
- }
-
- static int __stdcall GetCharLen(const char* pch)
- {
- // returns char length
- return int(_mbclen(reinterpret_cast<const unsigned char*>(pch)));
- }
-
- static DWORD __stdcall GetEnvironmentVariable(LPCSTR pszVar, LPSTR pszBuffer, DWORD dwSize)
- {
- return ::GetEnvironmentVariableA(pszVar, pszBuffer, dwSize);
- }
-
- static char* MirCopy(const char *pstrString, size_t size)
- {
- return mir_strndup(pstrString, size);
- }
-};
-
-// specialization for wchar_t
-template<>
-class ChTraitsCRT< wchar_t > : public ChTraitsBase< wchar_t >
-{
- static DWORD __stdcall _GetEnvironmentVariableW(LPCWSTR pszName, LPWSTR pszBuffer, DWORD nSize)
- {
- return ::GetEnvironmentVariableW(pszName, pszBuffer, nSize);
- }
-
-public:
- static LPWSTR __stdcall CharNext(LPCWSTR psz)
- {
- return const_cast< LPWSTR >(psz+1);
- }
-
- static int __stdcall IsDigit(wchar_t ch)
- {
- return iswdigit(static_cast<unsigned short>(ch));
- }
-
- static int __stdcall IsSpace(wchar_t ch)
- {
- return iswspace(static_cast<unsigned short>(ch));
- }
-
- static int __stdcall StringCompare(LPCWSTR pszA, LPCWSTR pszB)
- {
- return wcscmp(pszA, pszB);
- }
-
- static int __stdcall StringCompareIgnore(LPCWSTR pszA, LPCWSTR pszB)
- {
- return _wcsicmp(pszA, pszB);
- }
-
- static int __stdcall StringCollate(LPCWSTR pszA, LPCWSTR pszB)
- {
- return wcscoll(pszA, pszB);
- }
-
- static int __stdcall StringCollateIgnore(LPCWSTR pszA, LPCWSTR pszB)
- {
- return _wcsicoll(pszA, pszB);
- }
-
- static LPCWSTR __stdcall StringFindString(LPCWSTR pszBlock, LPCWSTR pszMatch)
- {
- return wcsstr(pszBlock, pszMatch);
- }
-
- static LPWSTR __stdcall StringFindString(LPWSTR pszBlock, LPCWSTR pszMatch)
- {
- return const_cast< LPWSTR >(StringFindString(const_cast< LPCWSTR >(pszBlock), pszMatch));
- }
-
- static LPCWSTR __stdcall StringFindChar(LPCWSTR pszBlock, wchar_t chMatch)
- {
- return wcschr(pszBlock, chMatch);
- }
-
- static LPCWSTR __stdcall StringFindCharRev(LPCWSTR psz, wchar_t ch)
- {
- return wcsrchr(psz, ch);
- }
-
- static LPCWSTR __stdcall StringScanSet(LPCWSTR pszBlock, LPCWSTR pszMatch)
- {
- return wcspbrk(pszBlock, pszMatch);
- }
-
- static int __stdcall StringSpanIncluding(LPCWSTR pszBlock, LPCWSTR pszSet)
- {
- return (int)wcsspn(pszBlock, pszSet);
- }
-
- static int __stdcall StringSpanExcluding(LPCWSTR pszBlock, LPCWSTR pszSet)
- {
- return (int)wcscspn(pszBlock, pszSet);
- }
-
- static LPWSTR __stdcall StringUppercase(LPWSTR psz)
- {
- CharUpperBuffW(psz, (DWORD)wcslen(psz));
- return psz;
- }
-
- static LPWSTR __stdcall StringLowercase(LPWSTR psz)
- {
- CharLowerBuffW(psz, (DWORD)wcslen(psz));
- return psz;
- }
-
- static LPWSTR __stdcall StringUppercase(LPWSTR psz, size_t len)
- {
- CharUpperBuffW(psz, (DWORD)len);
- return psz;
- }
-
- static LPWSTR __stdcall StringLowercase(LPWSTR psz, size_t len)
- {
- CharLowerBuffW(psz, (DWORD)len);
- return psz;
- }
-
- static LPWSTR __stdcall StringReverse(LPWSTR psz)
- {
- return _wcsrev(psz);
- }
-
- static int __stdcall GetFormattedLength(_Printf_format_string_ LPCWSTR pszFormat, va_list args)
- {
- return _vscwprintf(pszFormat, args);
- }
-
- static int __stdcall Format(LPWSTR pszBuffer, _Printf_format_string_ LPCWSTR pszFormat, va_list args)
- {
- #pragma warning(push)
- #pragma warning(disable : 4996)
- return vswprintf(pszBuffer, pszFormat, args);
- #pragma warning(pop)
- }
-
- static int __stdcall Format(LPWSTR pszBuffer, size_t nLength, _Printf_format_string_ LPCWSTR pszFormat, va_list args)
- {
- #pragma warning(push)
- #pragma warning(disable : 4996)
- return _vsnwprintf(pszBuffer, nLength, pszFormat, args);
- #pragma warning(pop)
- }
-
- static int __stdcall GetBaseTypeLength(LPCSTR pszSrc)
- {
- // Returns required buffer size in wchar_ts
- return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, -1, nullptr, 0)-1;
- }
-
- static int __stdcall GetBaseTypeLength(LPCSTR pszSrc, int nLength)
- {
- // Returns required buffer size in wchar_ts
- return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nLength, nullptr, 0);
- }
-
- static int __stdcall GetBaseTypeLength(LPCWSTR pszSrc)
- {
- // Returns required buffer size in wchar_ts
- return (int)wcslen(pszSrc);
- }
-
- static int __stdcall GetBaseTypeLength(LPCWSTR pszSrc, int nLength)
- {
- (void)pszSrc;
- // Returns required buffer size in wchar_ts
- return nLength;
- }
-
- static void __stdcall ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1)
- {
- // nLen is in wchar_ts
- ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nSrcLength, pszDest, nDestLength);
- }
-
- static void __stdcall ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1)
- {
- if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
- // nLen is in wchar_ts
- #if _MSC_VER >= 1400
- wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength);
- #else
- wmemcpy(pszDest, pszSrc, nDestLength);
- #endif
- }
-
- static void __stdcall FloodCharacters(wchar_t ch, int nLength, LPWSTR psz)
- {
- // nLength is in XCHARs
- for (int i = 0; i < nLength; i++)
- {
- psz[i] = ch;
- }
- }
-
- static int __stdcall SafeStringLen(LPCSTR psz)
- {
- // returns length in bytes
- return (psz != nullptr) ? (int)strlen(psz) : 0;
- }
-
- static int __stdcall SafeStringLen(LPCWSTR psz)
- {
- // returns length in wchar_ts
- return (psz != nullptr) ? (int)wcslen(psz) : 0;
- }
-
- static int __stdcall GetCharLen(const wchar_t* pch)
- {
- (void)pch;
- // returns char length
- return 1;
- }
-
- static int __stdcall GetCharLen(const char* pch)
- {
- // returns char length
- return (int)(_mbclen(reinterpret_cast< const unsigned char* >(pch)));
- }
-
- static DWORD __stdcall GetEnvironmentVariable(LPCWSTR pszVar, LPWSTR pszBuffer, DWORD dwSize)
- {
- return _GetEnvironmentVariableW(pszVar, pszBuffer, dwSize);
- }
-
- static void __stdcall ConvertToOem(LPWSTR /*psz*/)
- {
- }
-
- static void __stdcall ConvertToAnsi(LPWSTR /*psz*/)
- {
- }
-
- static void __stdcall ConvertToOem(LPWSTR /*psz*/, size_t)
- {
- }
-
- static void __stdcall ConvertToAnsi(LPWSTR /*psz*/, size_t)
- {
- }
-
- static LPWSTR MirCopy(LPCWSTR pstrString, size_t size)
- {
- return mir_wstrndup(pstrString, size);
- }
-};
-
-template< typename BaseType, class StringTraits >
-class MIR_CORE_EXPORT CMStringT : public CMSimpleStringT< BaseType >
-{
-public:
- typedef CMSimpleStringT< BaseType> CThisSimpleString;
- typedef typename CThisSimpleString::XCHAR XCHAR;
- typedef typename CThisSimpleString::PXSTR PXSTR;
- typedef typename CThisSimpleString::PCXSTR PCXSTR;
- typedef typename CThisSimpleString::YCHAR YCHAR;
- typedef typename CThisSimpleString::PYSTR PYSTR;
- typedef typename CThisSimpleString::PCYSTR PCYSTR;
-
-public:
- CMStringT();
-
- // Copy constructor
- CMStringT(const CMStringT& strSrc);
-
- CMStringT(const XCHAR* pszSrc);
- CMStringT(CMStringDataFormat, _Printf_format_string_ const XCHAR* pszFormat, ...);
-
- CMStringT(const YCHAR* pszSrc);
- CMStringT(const unsigned char* pszSrc);
-
- CMStringT(char ch, int nLength = 1);
- CMStringT(wchar_t ch, int nLength = 1);
-
- CMStringT(const XCHAR* pch, int nLength);
- CMStringT(const YCHAR* pch, int nLength);
-
- // Destructor
- ~CMStringT();
-
- // Assignment operators
- CMStringT& operator=(const CMStringT& strSrc);
- CMStringT& operator=(PCXSTR pszSrc);
- CMStringT& operator=(PCYSTR pszSrc);
- CMStringT& operator=(const unsigned char* pszSrc);
- CMStringT& operator=(char ch);
- CMStringT& operator=(wchar_t ch);
-
- CMStringT& operator+=(const CMStringT& str);
- CMStringT& operator+=(const CThisSimpleString& str);
- CMStringT& operator+=(PCXSTR pszSrc);
- CMStringT& operator+=(PCYSTR pszSrc);
- CMStringT& operator+=(char ch);
- CMStringT& operator+=(unsigned char ch);
- CMStringT& operator+=(wchar_t ch);
-
- // Comparison
-
- int Compare(PCXSTR psz) const;
- int CompareNoCase(PCXSTR psz) const;
- int Collate(PCXSTR psz) const;
- int CollateNoCase(PCXSTR psz) const;
-
- // Advanced manipulation
-
- // Delete 'nCount' characters, starting at index 'iIndex'
- int Delete(int iIndex, int nCount = 1);
-
- // Insert character 'ch' before index 'iIndex'
- int Insert(int iIndex, XCHAR ch);
-
- // Insert string 'psz' before index 'iIndex'
- int Insert(int iIndex, PCXSTR psz);
-
- // Replace all occurrences of character 'chOld' with character 'chNew'
- int Replace(XCHAR chOld, XCHAR chNew);
-
- // Replace all occurrences of string 'pszOld' with string 'pszNew'
- int Replace(PCXSTR pszOld, PCXSTR pszNew);
-
- // Remove all occurrences of character 'chRemove'
- int Remove(XCHAR chRemove);
-
- CMStringT Tokenize(PCXSTR pszTokens, int& iStart) const;
-
- // find routines
-
- // Find the first occurrence of character 'ch', starting at index 'iStart'
- int Find(XCHAR ch, int iStart = 0) const;
-
- // look for a specific sub-string
-
- // Find the first occurrence of string 'pszSub', starting at index 'iStart'
- int Find(PCXSTR pszSub, int iStart = 0) const;
-
- // Find the first occurrence of any of the characters in string 'pszCharSet'
- int FindOneOf(PCXSTR pszCharSet) const;
-
- // Find the last occurrence of character 'ch'
- int ReverseFind(XCHAR ch) const;
-
- // manipulation
-
- // Convert the string to uppercase
- CMStringT& MakeUpper();
-
- // Convert the string to lowercase
- CMStringT& MakeLower();
-
- // Reverse the string
- CMStringT& MakeReverse();
-
- // trimming
-
- // Remove all trailing whitespace
- CMStringT& TrimRight();
-
- // Remove all leading whitespace
- CMStringT& TrimLeft();
-
- // Remove all leading and trailing whitespace
- CMStringT& Trim();
-
- // Remove all leading and trailing occurrences of character 'chTarget'
- CMStringT& Trim(XCHAR chTarget);
-
- // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
- CMStringT& Trim(PCXSTR pszTargets);
-
- // trimming anything (either side)
-
- // Remove all trailing occurrences of character 'chTarget'
- CMStringT& TrimRight(XCHAR chTarget);
-
- // Remove all trailing occurrences of any of the characters in string 'pszTargets'
- CMStringT& TrimRight(PCXSTR pszTargets);
-
- // Remove all leading occurrences of character 'chTarget'
- CMStringT& TrimLeft(XCHAR chTarget);
-
- // Remove all leading occurrences of any of the characters in string 'pszTargets'
- CMStringT& TrimLeft(PCXSTR pszTargets);
-
- // Convert the string to the OEM character set
- void AnsiToOem();
-
- // Convert the string to the ANSI character set
- void OemToAnsi();
-
- // Very simple sub-string extraction
-
- // Return the substring starting at index 'iFirst'
- CMStringT Mid(int iFirst) const;
-
- // Return the substring starting at index 'iFirst', with length 'nCount'
- CMStringT Mid(int iFirst, int nCount) const;
-
- // Return the substring consisting of the rightmost 'nCount' characters
- CMStringT Right(int nCount) const;
-
- // Return the substring consisting of the leftmost 'nCount' characters
- CMStringT Left(int nCount) const;
-
- // Return the substring consisting of the leftmost characters in the set 'pszCharSet'
- CMStringT SpanIncluding(PCXSTR pszCharSet) const;
-
- // Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
- CMStringT SpanExcluding(PCXSTR pszCharSet) const;
-
- // Format data using format string 'pszFormat'
- PCXSTR Format(PCXSTR _Printf_format_string_ pszFormat, ...);
- PCXSTR FormatV(PCXSTR _Printf_format_string_ pszFormat, va_list args);
-
- // Append formatted data using format string 'pszFormat'
- PCXSTR AppendFormat(PCXSTR _Printf_format_string_ pszFormat, ...);
- void AppendFormatV(PCXSTR _Printf_format_string_ pszFormat, va_list args);
-
- // return a copy of string to be freed by mir_free()
- PXSTR Detach() const;
-
- // Set the string to the value of environment variable 'pszVar'
- BOOL GetEnvironmentVariable(PCXSTR pszVar);
-
- friend bool __forceinline operator==(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) == 0; }
- friend bool __forceinline operator==(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) == 0; }
- friend bool __forceinline operator==(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) == 0; }
- friend bool __forceinline operator==(const CMStringT& str1, PCYSTR psz2) { return str1 == CMStringT(psz2); }
- friend bool __forceinline operator==(PCYSTR psz1, const CMStringT& str2) { return CMStringT(psz1) == str2; }
-
- friend bool __forceinline operator!=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) != 0; }
- friend bool __forceinline operator!=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) != 0; }
- friend bool __forceinline operator!=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) != 0; }
- friend bool __forceinline operator!=(const CMStringT& str1, PCYSTR psz2) { return str1 != CMStringT(psz2); }
- friend bool __forceinline operator!=(PCYSTR psz1, const CMStringT& str2) { return CMStringT(psz1) != str2; }
-
- friend bool __forceinline operator<(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) < 0; }
- friend bool __forceinline operator<(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) < 0; }
- friend bool __forceinline operator<(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) > 0; }
-
- friend bool __forceinline operator>(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) > 0; }
- friend bool __forceinline operator>(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) > 0; }
- friend bool __forceinline operator>(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) < 0; }
-
- friend bool __forceinline operator<=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) <= 0; }
- friend bool __forceinline operator<=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) <= 0; }
- friend bool __forceinline operator<=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) >= 0; }
-
- friend bool __forceinline operator>=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) >= 0; }
- friend bool __forceinline operator>=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) >= 0; }
- friend bool __forceinline operator>=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) <= 0; }
-
- friend bool __forceinline operator==(XCHAR ch1, const CMStringT& str2) { return (str2.GetLength() == 1) && (str2[0] == ch1); }
- friend bool __forceinline operator==(const CMStringT& str1, XCHAR ch2) { return (str1.GetLength() == 1) && (str1[0] == ch2); }
-
- friend bool __forceinline operator!=(XCHAR ch1, const CMStringT& str2) { return (str2.GetLength() != 1) || (str2[0] != ch1); }
- friend bool __forceinline operator!=(const CMStringT& str1, XCHAR ch2) { return (str1.GetLength() != 1) || (str1[0] != ch2); }
-};
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, const CMStringT<BaseType, StringTraits>& str2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, typename CMStringT<BaseType, StringTraits>::PCXSTR psz2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(typename CMStringT<BaseType, StringTraits>::PCXSTR psz1, const CMStringT<BaseType, StringTraits>& str2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, wchar_t ch2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, char ch2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator + (wchar_t ch1, const CMStringT<BaseType, StringTraits>& str2);
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(char ch1, const CMStringT<BaseType, StringTraits>& str2);
-
-typedef CMStringT< wchar_t, ChTraitsCRT< wchar_t > > CMStringW;
-typedef CMStringT< char, ChTraitsCRT< char > > CMStringA;
-
-#endif // M_STRING_H__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+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.
+*/
+
+#pragma once
+
+#ifndef M_STRING_H__
+#define M_STRING_H__
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _WINDOWS
+#include <mbstring.h>
+#endif // _WINDOWS
+#include <wchar.h>
+
+#include <m_core.h>
+
+#ifdef __MINGW32__
+#include <limits.h>
+
+__inline size_t strnlen(const char *string, size_t maxlen)
+{
+ const char *end = (const char *)memchr ((const void *)string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+__inline size_t wcsnlen(const wchar_t *string, size_t maxlen)
+{
+ const wchar_t *end = wmemchr (string, L'\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+
+/* FIXME: This may be wrong assumption about Langpack_GetDefaultCodePage */
+#define Langpack_GetDefaultCodePage() CP_THREAD_ACP
+/* FIXME: This is unsafe */
+#define memcpy_s(dest,size,src,count) memcpy(dest,src,count)
+/* FIXME: This is quite silly implementation of _mbsstr */
+#define _mbsstr(str,search) strstr((const char *)str,(const char *)search)
+#define __max(x,y) (((x)<(y))?(y):(x))
+#endif /* __MINGW32__ */
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct CMStringData;
+
+MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize);
+MIR_CORE_DLL(void) mirstr_free(CMStringData *pData);
+MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize);
+MIR_CORE_DLL(CMStringData*) mirstr_getNil();
+
+MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis);
+MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis);
+MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+enum CMStringDataFormat { FORMAT };
+
+struct CMStringData
+{
+ int nDataLength; // Length of currently used data in XCHARs (not including terminating null)
+ int nAllocLength; // Length of allocated data in XCHARs (not including terminating null)
+ long nRefs; // Reference count: negative == locked
+
+ __forceinline void* data() { return (this + 1); }
+ __forceinline void AddRef() { InterlockedIncrement(&nRefs); }
+ __forceinline bool IsLocked() const { return nRefs < 0; }
+ __forceinline bool IsShared() const { return nRefs > 1; }
+
+ __forceinline void Lock() { mirstr_lock(this); }
+ __forceinline void Release() { mirstr_release(this); }
+ __forceinline void Unlock() { mirstr_unlock(this); }
+};
+
+template< typename BaseType = char >
+class ChTraitsBase
+{
+public:
+ typedef char XCHAR;
+ typedef LPSTR PXSTR;
+ typedef LPCSTR PCXSTR;
+ typedef wchar_t YCHAR;
+ typedef LPWSTR PYSTR;
+ typedef LPCWSTR PCYSTR;
+};
+
+template<>
+class ChTraitsBase< wchar_t >
+{
+public:
+ typedef wchar_t XCHAR;
+ typedef LPWSTR PXSTR;
+ typedef LPCWSTR PCXSTR;
+ typedef char YCHAR;
+ typedef LPSTR PYSTR;
+ typedef LPCSTR PCYSTR;
+};
+
+template< typename BaseType >
+class CMSimpleStringT
+{
+public:
+ typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR;
+ typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR;
+ typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR;
+ typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR;
+ typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR;
+ typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR;
+
+public:
+ explicit CMSimpleStringT();
+
+ CMSimpleStringT(const CMSimpleStringT& strSrc);
+ CMSimpleStringT(PCXSTR pszSrc);
+ CMSimpleStringT(const XCHAR* pchSrc, int nLength);
+ ~CMSimpleStringT();
+
+ __forceinline operator CMSimpleStringT<BaseType>&()
+ { return *(CMSimpleStringT<BaseType>*)this;
+ }
+
+ CMSimpleStringT& operator=(const CMSimpleStringT& strSrc);
+
+ __forceinline CMSimpleStringT& operator=(PCXSTR pszSrc)
+ { SetString(pszSrc);
+ return *this;
+ }
+
+ __forceinline CMSimpleStringT& operator+=(const CMSimpleStringT& strSrc)
+ { Append(strSrc);
+ return *this;
+ }
+
+ __forceinline CMSimpleStringT& operator+=(PCXSTR pszSrc)
+ { Append(pszSrc);
+ return *this;
+ }
+
+ __forceinline CMSimpleStringT& operator+=(char ch)
+ { AppendChar(XCHAR(ch));
+ return *this;
+ }
+
+ __forceinline CMSimpleStringT& operator+=(unsigned char ch)
+ { AppendChar(XCHAR(ch));
+ return *this;
+ }
+
+ __forceinline CMSimpleStringT& operator+=(wchar_t ch)
+ { AppendChar(XCHAR(ch));
+ return *this;
+ }
+
+ __forceinline XCHAR operator[](int iChar) const
+ { return m_pszData[iChar];
+ }
+
+ __forceinline operator PCXSTR() const
+ { return m_pszData;
+ }
+
+ __forceinline PCXSTR c_str() const
+ { return m_pszData;
+ }
+
+ __forceinline int GetAllocLength() const
+ { return GetData()->nAllocLength;
+ }
+
+ __forceinline XCHAR GetAt(int iChar) const
+ { return m_pszData[iChar];
+ }
+
+ __forceinline PXSTR GetBuffer(int nMinBufferLength)
+ { return PrepareWrite(nMinBufferLength);
+ }
+
+ __forceinline int GetLength() const
+ { return GetData()->nDataLength;
+ }
+
+ __forceinline PCXSTR GetString() const
+ { return m_pszData;
+ }
+
+ __forceinline PCXSTR GetTail() const
+ { return m_pszData + GetData()->nDataLength;
+ }
+
+ __forceinline bool IsEmpty() const
+ { return GetLength() == 0;
+ }
+
+ __forceinline void Preallocate(int nLength)
+ { PrepareWrite(nLength);
+ }
+
+ __forceinline void ReleaseBufferSetLength(int nNewLength)
+ { SetLength(nNewLength);
+ }
+
+ void Append(PCXSTR pszSrc);
+ void Append(PCXSTR pszSrc, int nLength);
+ void AppendChar(XCHAR ch);
+ void Append(const CMSimpleStringT& strSrc);
+
+ void Empty();
+ void FreeExtra();
+
+ PXSTR GetBuffer();
+ PXSTR GetBufferSetLength(int nLength);
+
+ PXSTR LockBuffer();
+ void UnlockBuffer();
+
+ void ReleaseBuffer(int nNewLength = -1);
+
+ void Truncate(int nNewLength);
+ void SetAt(int iChar, XCHAR ch);
+ void SetString(PCXSTR pszSrc);
+ void SetString(PCXSTR pszSrc, int nLength);
+
+public:
+ friend CMSimpleStringT operator+(const CMSimpleStringT& str1, const CMSimpleStringT& str2);
+ friend CMSimpleStringT operator+(const CMSimpleStringT& str1, PCXSTR psz2);
+ friend CMSimpleStringT operator+(PCXSTR psz1, const CMSimpleStringT& str2);
+
+ static void MIR_SYSCALL CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars);
+ static void MIR_SYSCALL CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars);
+ static void MIR_SYSCALL CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars);
+ static void MIR_SYSCALL CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars);
+ static int MIR_SYSCALL StringLength(const char* psz);
+ static int MIR_SYSCALL StringLength(const wchar_t* psz);
+ static int MIR_SYSCALL StringLengthN(const char* psz, size_t sizeInXChar);
+ static int MIR_SYSCALL StringLengthN(const wchar_t* psz, size_t sizeInXChar);
+ static void MIR_SYSCALL Concatenate(CMSimpleStringT& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2);
+
+ // Implementation
+private:
+ __forceinline CMStringData* GetData() const
+ { return (reinterpret_cast<CMStringData *>(m_pszData)-1);
+ }
+
+ void Attach(CMStringData* pData);
+ void Fork(int nLength);
+ PXSTR PrepareWrite(int nLength);
+ void PrepareWrite2(int nLength);
+ void Reallocate(int nLength);
+ void SetLength(int nLength);
+ static CMStringData* MIR_SYSCALL CloneData(CMStringData* pData);
+
+private:
+ PXSTR m_pszData;
+};
+
+
+template< typename _CharType = char >
+class ChTraitsCRT : public ChTraitsBase < _CharType >
+{
+public:
+ static char* MIR_SYSCALL CharNext(const char* p)
+ {
+ return reinterpret_cast<char*>(_mbsinc(reinterpret_cast<const unsigned char*>(p)));
+ }
+
+ static int MIR_SYSCALL IsDigit(char ch)
+ {
+ return _ismbcdigit(ch);
+ }
+
+ static int MIR_SYSCALL IsSpace(char ch)
+ {
+ return _ismbcspace(ch);
+ }
+
+ static int MIR_SYSCALL StringCompare(LPCSTR pszA, LPCSTR pszB)
+ {
+ return _mbscmp(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
+ }
+
+ static int MIR_SYSCALL StringCompareIgnore(LPCSTR pszA, LPCSTR pszB)
+ {
+ return _mbsicmp(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
+ }
+
+ static int MIR_SYSCALL StringCollate(LPCSTR pszA, LPCSTR pszB)
+ {
+ return _mbscoll(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
+ }
+
+ static int MIR_SYSCALL StringCollateIgnore(LPCSTR pszA, LPCSTR pszB)
+ {
+ return _mbsicoll(reinterpret_cast<const unsigned char*>(pszA), reinterpret_cast<const unsigned char*>(pszB));
+ }
+
+ static LPCSTR MIR_SYSCALL StringFindString(LPCSTR pszBlock, LPCSTR pszMatch)
+ {
+ return reinterpret_cast<LPCSTR>(_mbsstr(reinterpret_cast<const unsigned char*>(pszBlock),
+ reinterpret_cast<const unsigned char*>(pszMatch)));
+ }
+
+ static LPSTR MIR_SYSCALL StringFindString(LPSTR pszBlock, LPCSTR pszMatch)
+ {
+ return const_cast<LPSTR>(StringFindString(const_cast<LPCSTR>(pszBlock), pszMatch));
+ }
+
+ static LPCSTR MIR_SYSCALL StringFindChar(LPCSTR pszBlock, char chMatch)
+ {
+ return reinterpret_cast<LPCSTR>(_mbschr(reinterpret_cast<const unsigned char*>(pszBlock), (unsigned char)chMatch));
+ }
+
+ static LPCSTR MIR_SYSCALL StringFindCharRev(LPCSTR psz, char ch)
+ {
+ return reinterpret_cast<LPCSTR>(_mbsrchr(reinterpret_cast<const unsigned char*>(psz), (unsigned char)ch));
+ }
+
+ static LPCSTR MIR_SYSCALL StringScanSet(LPCSTR pszBlock, LPCSTR pszMatch)
+ {
+ return reinterpret_cast<LPCSTR>(_mbspbrk(reinterpret_cast<const unsigned char*>(pszBlock),
+ reinterpret_cast<const unsigned char*>(pszMatch)));
+ }
+
+ static int MIR_SYSCALL StringSpanIncluding(LPCSTR pszBlock, LPCSTR pszSet)
+ {
+ return (int)_mbsspn(reinterpret_cast<const unsigned char*>(pszBlock), reinterpret_cast<const unsigned char*>(pszSet));
+ }
+
+ static int MIR_SYSCALL StringSpanExcluding(LPCSTR pszBlock, LPCSTR pszSet)
+ {
+ return (int)_mbscspn(reinterpret_cast<const unsigned char*>(pszBlock), reinterpret_cast<const unsigned char*>(pszSet));
+ }
+
+ static LPSTR MIR_SYSCALL StringUppercase(LPSTR psz)
+ {
+ CharUpperBuffA(psz, (DWORD)strlen(psz));
+ return psz;
+ }
+
+ static LPSTR MIR_SYSCALL StringLowercase(LPSTR psz)
+ {
+ CharLowerBuffA(psz, (DWORD)strlen(psz));
+ return psz;
+ }
+
+ static LPSTR MIR_SYSCALL StringUppercase(LPSTR psz, size_t size)
+ {
+ CharUpperBuffA(psz, (DWORD)size);
+ return psz;
+ }
+
+ static LPSTR MIR_SYSCALL StringLowercase(LPSTR psz, size_t size)
+ {
+ CharLowerBuffA(psz, (DWORD)size);
+ return psz;
+ }
+
+ static LPSTR MIR_SYSCALL StringReverse(LPSTR psz)
+ {
+ return reinterpret_cast<LPSTR>(_mbsrev(reinterpret_cast<unsigned char*>(psz)));
+ }
+
+ static int MIR_SYSCALL GetFormattedLength(_Printf_format_string_ LPCSTR pszFormat, va_list args)
+ {
+ return _vscprintf(pszFormat, args);
+ }
+
+ static int MIR_SYSCALL Format(LPSTR pszBuffer, size_t nlength, _Printf_format_string_ LPCSTR pszFormat, va_list args)
+ {
+ return vsprintf_s(pszBuffer, nlength, pszFormat, args);
+ }
+
+ static int MIR_SYSCALL GetBaseTypeLength(LPCSTR pszSrc)
+ {
+ // Returns required buffer length in XCHARs
+ return int(strlen(pszSrc));
+ }
+
+ static int MIR_SYSCALL GetBaseTypeLength(LPCSTR pszSrc, int nLength)
+ {
+ (void)pszSrc;
+ // Returns required buffer length in XCHARs
+ return nLength;
+ }
+
+ static int MIR_SYSCALL GetBaseTypeLength(LPCWSTR pszSource)
+ {
+ // Returns required buffer length in XCHARs
+ #ifdef _MSC_VER
+ return ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
+ #else
+ return 0;
+ #endif
+ }
+
+ static int MIR_SYSCALL GetBaseTypeLength(LPCWSTR pszSource, int nLength)
+ {
+ // Returns required buffer length in XCHARs
+ #ifdef _MSC_VER
+ return ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSource, nLength, NULL, 0, NULL, NULL);
+ #else
+ return 0;
+ #endif
+ }
+
+ static void MIR_SYSCALL ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1)
+ {
+ if (nSrcLength == -1) { nSrcLength = 1 + GetBaseTypeLength(pszSrc); }
+ // nLen is in XCHARs
+ memcpy_s(pszDest, nDestLength*sizeof(char), pszSrc, nSrcLength*sizeof(char));
+ }
+
+ static void MIR_SYSCALL ConvertToBaseType(LPSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1)
+ {
+ // nLen is in XCHARs
+ #ifdef _MSC_VER
+ ::WideCharToMultiByte(Langpack_GetDefaultCodePage(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL);
+ #endif
+ }
+
+ static void ConvertToOem(_CharType* pstrString)
+ {
+ #ifdef _MSC_VER
+ BOOL fSuccess = ::CharToOemA(pstrString, pstrString);
+ #endif // _MSC_VER
+ }
+
+ static void ConvertToAnsi(_CharType* pstrString)
+ {
+ #ifdef _MSC_VER
+ BOOL fSuccess = ::OemToCharA(pstrString, pstrString);
+ #endif
+ }
+
+ static void ConvertToOem(_CharType* pstrString, size_t size)
+ {
+ #ifdef _MSC_VER
+ DWORD dwSize = static_cast<DWORD>(size);
+ ::CharToOemBuffA(pstrString, pstrString, dwSize);
+ #endif
+ }
+
+ static void ConvertToAnsi(_CharType* pstrString, size_t size)
+ {
+ #ifdef _MSC_VER
+ DWORD dwSize = static_cast<DWORD>(size);
+ ::OemToCharBuffA(pstrString, pstrString, dwSize);
+ #endif
+ }
+
+ static void MIR_SYSCALL FloodCharacters(char ch, int nLength, char* pch)
+ {
+ // nLength is in XCHARs
+ memset(pch, ch, nLength);
+ }
+
+ static int MIR_SYSCALL SafeStringLen(LPCSTR psz)
+ {
+ // returns length in bytes
+ return (psz != NULL) ? int(strlen(psz)) : 0;
+ }
+
+ static int MIR_SYSCALL SafeStringLen(LPCWSTR psz)
+ {
+ // returns length in wchar_ts
+ return (psz != NULL) ? int(wcslen(psz)) : 0;
+ }
+
+ static int MIR_SYSCALL GetCharLen(const wchar_t* pch)
+ {
+ // returns char length
+ return 1;
+ }
+
+ static int MIR_SYSCALL GetCharLen(const char* pch)
+ {
+ // returns char length
+ return int(_mbclen(reinterpret_cast<const unsigned char*>(pch)));
+ }
+
+ static DWORD MIR_SYSCALL GetEnvironmentVariable(LPCSTR pszVar, LPSTR pszBuffer, DWORD dwSize)
+ {
+ #ifdef _MSC_VER
+ return ::GetEnvironmentVariableA(pszVar, pszBuffer, dwSize);
+ #endif // _MSC_VER
+ }
+
+ static char* MirCopy(const char *pstrString, size_t size)
+ {
+ return mir_strndup(pstrString, size);
+ }
+};
+
+// specialization for wchar_t
+template<>
+class ChTraitsCRT< wchar_t > : public ChTraitsBase< wchar_t >
+{
+ static DWORD MIR_SYSCALL _GetEnvironmentVariableW(LPCWSTR pszName, LPWSTR pszBuffer, DWORD nSize)
+ {
+ #ifdef _MSC_VER
+ return ::GetEnvironmentVariableW(pszName, pszBuffer, nSize);
+ #endif // _MSC_VER
+ }
+
+public:
+ static LPWSTR MIR_SYSCALL CharNext(LPCWSTR psz)
+ {
+ return const_cast< LPWSTR >(psz+1);
+ }
+
+ static int MIR_SYSCALL IsDigit(wchar_t ch)
+ {
+ #ifdef _MSC_VER
+ return iswdigit(static_cast<unsigned short>(ch));
+ #else
+ return 0;
+ #endif
+ }
+
+ static int MIR_SYSCALL IsSpace(wchar_t ch)
+ {
+ #ifdef _MSC_VER
+ return iswspace(static_cast<unsigned short>(ch));
+ #else
+ return 0;
+ #endif
+ }
+
+ static int MIR_SYSCALL StringCompare(LPCWSTR pszA, LPCWSTR pszB)
+ {
+ return wcscmp(pszA, pszB);
+ }
+
+ static int MIR_SYSCALL StringCompareIgnore(LPCWSTR pszA, LPCWSTR pszB)
+ {
+ #ifdef _MSC_VER
+ return _wcsicmp(pszA, pszB);
+ #else
+ return 0;
+ #endif
+ }
+
+ static int MIR_SYSCALL StringCollate(LPCWSTR pszA, LPCWSTR pszB)
+ {
+ return wcscoll(pszA, pszB);
+ }
+
+ static int MIR_SYSCALL StringCollateIgnore(LPCWSTR pszA, LPCWSTR pszB)
+ {
+ #ifdef _MSC_VER
+ return _wcsicoll(pszA, pszB);
+ #else
+ return 0;
+ #endif
+ }
+
+ static LPCWSTR MIR_SYSCALL StringFindString(LPCWSTR pszBlock, LPCWSTR pszMatch)
+ {
+ return wcsstr(pszBlock, pszMatch);
+ }
+
+ static LPWSTR MIR_SYSCALL StringFindString(LPWSTR pszBlock, LPCWSTR pszMatch)
+ {
+ return const_cast< LPWSTR >(StringFindString(const_cast< LPCWSTR >(pszBlock), pszMatch));
+ }
+
+ static LPCWSTR MIR_SYSCALL StringFindChar(LPCWSTR pszBlock, wchar_t chMatch)
+ {
+ return wcschr(pszBlock, chMatch);
+ }
+
+ static LPCWSTR MIR_SYSCALL StringFindCharRev(LPCWSTR psz, wchar_t ch)
+ {
+ return wcsrchr(psz, ch);
+ }
+
+ static LPCWSTR MIR_SYSCALL StringScanSet(LPCWSTR pszBlock, LPCWSTR pszMatch)
+ {
+ return wcspbrk(pszBlock, pszMatch);
+ }
+
+ static int MIR_SYSCALL StringSpanIncluding(LPCWSTR pszBlock, LPCWSTR pszSet)
+ {
+ return (int)wcsspn(pszBlock, pszSet);
+ }
+
+ static int MIR_SYSCALL StringSpanExcluding(LPCWSTR pszBlock, LPCWSTR pszSet)
+ {
+ return (int)wcscspn(pszBlock, pszSet);
+ }
+
+ static LPWSTR MIR_SYSCALL StringUppercase(LPWSTR psz)
+ {
+ #ifdef _MSC_VER
+ CharUpperBuffW(psz, (DWORD)wcslen(psz));
+ #endif
+ return psz;
+ }
+
+ static LPWSTR MIR_SYSCALL StringLowercase(LPWSTR psz)
+ {
+ #ifdef _MSC_VER
+ CharLowerBuffW(psz, (DWORD)wcslen(psz));
+ #endif
+ return psz;
+ }
+
+ static LPWSTR MIR_SYSCALL StringUppercase(LPWSTR psz, size_t len)
+ {
+ #ifdef _MSC_VER
+ CharUpperBuffW(psz, (DWORD)len);
+ #endif
+ return psz;
+ }
+
+ static LPWSTR MIR_SYSCALL StringLowercase(LPWSTR psz, size_t len)
+ {
+ #ifdef _MSC_VER
+ CharLowerBuffW(psz, (DWORD)len);
+ #endif
+ return psz;
+ }
+
+ static LPWSTR MIR_SYSCALL StringReverse(LPWSTR psz)
+ {
+ #ifdef _MSC_VER
+ return _wcsrev(psz);
+ #else
+ return psz;
+ #endif
+ }
+
+ static int MIR_SYSCALL GetFormattedLength(_Printf_format_string_ LPCWSTR pszFormat, va_list args)
+ {
+ #ifdef _MSC_VER
+ return _vscwprintf(pszFormat, args);
+ #else
+ return 0;
+ #endif
+ }
+
+ static int MIR_SYSCALL Format(LPWSTR pszBuffer, _Printf_format_string_ LPCWSTR pszFormat, va_list args)
+ {
+ #pragma warning(push)
+ #pragma warning(disable : 4996)
+
+ #ifdef _MSC_VER
+ return vswprintf(pszBuffer, pszFormat, args);
+ #else
+ return 0;
+ #endif
+ #pragma warning(pop)
+ }
+
+ static int MIR_SYSCALL Format(LPWSTR pszBuffer, size_t nLength, _Printf_format_string_ LPCWSTR pszFormat, va_list args)
+ {
+ #pragma warning(push)
+ #pragma warning(disable : 4996)
+
+ #ifdef _MSC_VER
+ return _vsnwprintf(pszBuffer, nLength, pszFormat, args);
+ #else
+ return 0;
+ #endif
+
+ #pragma warning(pop)
+ }
+
+ static int MIR_SYSCALL GetBaseTypeLength(LPCSTR pszSrc)
+ {
+ // Returns required buffer size in wchar_ts
+ #ifdef _MSC_VER
+ return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, -1, nullptr, 0)-1;
+ #else
+ return 0;
+ #endif
+ }
+
+ static int MIR_SYSCALL GetBaseTypeLength(LPCSTR pszSrc, int nLength)
+ {
+ // Returns required buffer size in wchar_ts
+ #ifdef _MSC_VER
+ return ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nLength, nullptr, 0);
+ #else
+ return 0;
+ #endif
+ }
+
+ static int MIR_SYSCALL GetBaseTypeLength(LPCWSTR pszSrc)
+ {
+ // Returns required buffer size in wchar_ts
+ return (int)wcslen(pszSrc);
+ }
+
+ static int MIR_SYSCALL GetBaseTypeLength(LPCWSTR pszSrc, int nLength)
+ {
+ (void)pszSrc;
+ // Returns required buffer size in wchar_ts
+ return nLength;
+ }
+
+ static void MIR_SYSCALL ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1)
+ {
+ // nLen is in wchar_ts
+ #ifdef _MSC_VER
+ ::MultiByteToWideChar(CP_ACP, 0, pszSrc, nSrcLength, pszDest, nDestLength);
+ #endif
+ }
+
+ static void MIR_SYSCALL ConvertToBaseType(LPWSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1)
+ {
+ if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
+ // nLen is in wchar_ts
+ #if _MSC_VER >= 1400
+ wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength);
+ #else
+ wmemcpy(pszDest, pszSrc, nDestLength);
+ #endif
+ }
+
+ static void MIR_SYSCALL FloodCharacters(wchar_t ch, int nLength, LPWSTR psz)
+ {
+ // nLength is in XCHARs
+ for (int i = 0; i < nLength; i++)
+ {
+ psz[i] = ch;
+ }
+ }
+
+ static int MIR_SYSCALL SafeStringLen(LPCSTR psz)
+ {
+ // returns length in bytes
+ return (psz != nullptr) ? (int)strlen(psz) : 0;
+ }
+
+ static int MIR_SYSCALL SafeStringLen(LPCWSTR psz)
+ {
+ // returns length in wchar_ts
+ return (psz != nullptr) ? (int)wcslen(psz) : 0;
+ }
+
+ static int MIR_SYSCALL GetCharLen(const wchar_t* pch)
+ {
+ (void)pch;
+ // returns char length
+ return 1;
+ }
+
+ static int MIR_SYSCALL GetCharLen(const char* pch)
+ {
+ // returns char length
+ #ifdef _MSC_VER
+ return (int)(_mbclen(reinterpret_cast< const unsigned char* >(pch)));
+ #else
+ return mblen(pch, strlen(pch));
+ #endif
+ }
+
+ static DWORD MIR_SYSCALL GetEnvironmentVariable(LPCWSTR pszVar, LPWSTR pszBuffer, DWORD dwSize)
+ {
+ return _GetEnvironmentVariableW(pszVar, pszBuffer, dwSize);
+ }
+
+ static void MIR_SYSCALL ConvertToOem(LPWSTR /*psz*/)
+ {
+ }
+
+ static void MIR_SYSCALL ConvertToAnsi(LPWSTR /*psz*/)
+ {
+ }
+
+ static void MIR_SYSCALL ConvertToOem(LPWSTR /*psz*/, size_t)
+ {
+ }
+
+ static void MIR_SYSCALL ConvertToAnsi(LPWSTR /*psz*/, size_t)
+ {
+ }
+
+ static LPWSTR MirCopy(LPCWSTR pstrString, size_t size)
+ {
+ return mir_wstrndup(pstrString, size);
+ }
+};
+
+template< typename BaseType, class StringTraits >
+class MIR_CORE_EXPORT CMStringT : public CMSimpleStringT< BaseType >
+{
+public:
+ typedef CMSimpleStringT< BaseType> CThisSimpleString;
+ typedef typename CThisSimpleString::XCHAR XCHAR;
+ typedef typename CThisSimpleString::PXSTR PXSTR;
+ typedef typename CThisSimpleString::PCXSTR PCXSTR;
+ typedef typename CThisSimpleString::YCHAR YCHAR;
+ typedef typename CThisSimpleString::PYSTR PYSTR;
+ typedef typename CThisSimpleString::PCYSTR PCYSTR;
+
+public:
+ CMStringT();
+
+ // Copy constructor
+ CMStringT(const CMStringT& strSrc);
+
+ CMStringT(const XCHAR* pszSrc);
+ CMStringT(CMStringDataFormat, _Printf_format_string_ const XCHAR* pszFormat, ...);
+
+ CMStringT(const YCHAR* pszSrc);
+ CMStringT(const unsigned char* pszSrc);
+
+ CMStringT(char ch, int nLength = 1);
+ CMStringT(wchar_t ch, int nLength = 1);
+
+ CMStringT(const XCHAR* pch, int nLength);
+ CMStringT(const YCHAR* pch, int nLength);
+
+ // Destructor
+ ~CMStringT();
+
+ // Assignment operators
+ CMStringT& operator=(const CMStringT& strSrc);
+ CMStringT& operator=(PCXSTR pszSrc);
+ CMStringT& operator=(PCYSTR pszSrc);
+ CMStringT& operator=(const unsigned char* pszSrc);
+ CMStringT& operator=(char ch);
+ CMStringT& operator=(wchar_t ch);
+
+ CMStringT& operator+=(const CMStringT& str);
+ CMStringT& operator+=(const CThisSimpleString& str);
+ CMStringT& operator+=(PCXSTR pszSrc);
+ CMStringT& operator+=(PCYSTR pszSrc);
+ CMStringT& operator+=(char ch);
+ CMStringT& operator+=(unsigned char ch);
+ CMStringT& operator+=(wchar_t ch);
+
+ // Comparison
+
+ int Compare(PCXSTR psz) const;
+ int CompareNoCase(PCXSTR psz) const;
+ int Collate(PCXSTR psz) const;
+ int CollateNoCase(PCXSTR psz) const;
+
+ // Advanced manipulation
+
+ // Delete 'nCount' characters, starting at index 'iIndex'
+ int Delete(int iIndex, int nCount = 1);
+
+ // Insert character 'ch' before index 'iIndex'
+ int Insert(int iIndex, XCHAR ch);
+
+ // Insert string 'psz' before index 'iIndex'
+ int Insert(int iIndex, PCXSTR psz);
+
+ // Replace all occurrences of character 'chOld' with character 'chNew'
+ int Replace(XCHAR chOld, XCHAR chNew);
+
+ // Replace all occurrences of string 'pszOld' with string 'pszNew'
+ int Replace(PCXSTR pszOld, PCXSTR pszNew);
+
+ // Remove all occurrences of character 'chRemove'
+ int Remove(XCHAR chRemove);
+
+ CMStringT Tokenize(PCXSTR pszTokens, int& iStart) const;
+
+ // find routines
+
+ // Find the first occurrence of character 'ch', starting at index 'iStart'
+ int Find(XCHAR ch, int iStart = 0) const;
+
+ // look for a specific sub-string
+
+ // Find the first occurrence of string 'pszSub', starting at index 'iStart'
+ int Find(PCXSTR pszSub, int iStart = 0) const;
+
+ // Find the first occurrence of any of the characters in string 'pszCharSet'
+ int FindOneOf(PCXSTR pszCharSet) const;
+
+ // Find the last occurrence of character 'ch'
+ int ReverseFind(XCHAR ch) const;
+
+ // manipulation
+
+ // Convert the string to uppercase
+ CMStringT& MakeUpper();
+
+ // Convert the string to lowercase
+ CMStringT& MakeLower();
+
+ // Reverse the string
+ CMStringT& MakeReverse();
+
+ // trimming
+
+ // Remove all trailing whitespace
+ CMStringT& TrimRight();
+
+ // Remove all leading whitespace
+ CMStringT& TrimLeft();
+
+ // Remove all leading and trailing whitespace
+ CMStringT& Trim();
+
+ // Remove all leading and trailing occurrences of character 'chTarget'
+ CMStringT& Trim(XCHAR chTarget);
+
+ // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
+ CMStringT& Trim(PCXSTR pszTargets);
+
+ // trimming anything (either side)
+
+ // Remove all trailing occurrences of character 'chTarget'
+ CMStringT& TrimRight(XCHAR chTarget);
+
+ // Remove all trailing occurrences of any of the characters in string 'pszTargets'
+ CMStringT& TrimRight(PCXSTR pszTargets);
+
+ // Remove all leading occurrences of character 'chTarget'
+ CMStringT& TrimLeft(XCHAR chTarget);
+
+ // Remove all leading occurrences of any of the characters in string 'pszTargets'
+ CMStringT& TrimLeft(PCXSTR pszTargets);
+
+ // Convert the string to the OEM character set
+ void AnsiToOem();
+
+ // Convert the string to the ANSI character set
+ void OemToAnsi();
+
+ // Very simple sub-string extraction
+
+ // Return the substring starting at index 'iFirst'
+ CMStringT Mid(int iFirst) const;
+
+ // Return the substring starting at index 'iFirst', with length 'nCount'
+ CMStringT Mid(int iFirst, int nCount) const;
+
+ // Return the substring consisting of the rightmost 'nCount' characters
+ CMStringT Right(int nCount) const;
+
+ // Return the substring consisting of the leftmost 'nCount' characters
+ CMStringT Left(int nCount) const;
+
+ // Return the substring consisting of the leftmost characters in the set 'pszCharSet'
+ CMStringT SpanIncluding(PCXSTR pszCharSet) const;
+
+ // Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
+ CMStringT SpanExcluding(PCXSTR pszCharSet) const;
+
+ // Format data using format string 'pszFormat'
+ PCXSTR Format(PCXSTR _Printf_format_string_ pszFormat, ...);
+ PCXSTR FormatV(PCXSTR _Printf_format_string_ pszFormat, va_list args);
+
+ // Append formatted data using format string 'pszFormat'
+ PCXSTR AppendFormat(PCXSTR _Printf_format_string_ pszFormat, ...);
+ void AppendFormatV(PCXSTR _Printf_format_string_ pszFormat, va_list args);
+
+ // return a copy of string to be freed by mir_free()
+ PXSTR Detach() const;
+
+ // Set the string to the value of environment variable 'pszVar'
+ BOOL GetEnvironmentVariable(PCXSTR pszVar);
+
+ friend bool __forceinline operator==(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) == 0; }
+ friend bool __forceinline operator==(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) == 0; }
+ friend bool __forceinline operator==(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) == 0; }
+ friend bool __forceinline operator==(const CMStringT& str1, PCYSTR psz2) { return str1 == CMStringT(psz2); }
+ friend bool __forceinline operator==(PCYSTR psz1, const CMStringT& str2) { return CMStringT(psz1) == str2; }
+
+ friend bool __forceinline operator!=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) != 0; }
+ friend bool __forceinline operator!=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) != 0; }
+ friend bool __forceinline operator!=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) != 0; }
+ friend bool __forceinline operator!=(const CMStringT& str1, PCYSTR psz2) { return str1 != CMStringT(psz2); }
+ friend bool __forceinline operator!=(PCYSTR psz1, const CMStringT& str2) { return CMStringT(psz1) != str2; }
+
+ friend bool __forceinline operator<(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) < 0; }
+ friend bool __forceinline operator<(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) < 0; }
+ friend bool __forceinline operator<(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) > 0; }
+
+ friend bool __forceinline operator>(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) > 0; }
+ friend bool __forceinline operator>(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) > 0; }
+ friend bool __forceinline operator>(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) < 0; }
+
+ friend bool __forceinline operator<=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) <= 0; }
+ friend bool __forceinline operator<=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) <= 0; }
+ friend bool __forceinline operator<=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) >= 0; }
+
+ friend bool __forceinline operator>=(const CMStringT& str1, const CMStringT& str2) { return str1.Compare(str2) >= 0; }
+ friend bool __forceinline operator>=(const CMStringT& str1, PCXSTR psz2) { return str1.Compare(psz2) >= 0; }
+ friend bool __forceinline operator>=(PCXSTR psz1, const CMStringT& str2) { return str2.Compare(psz1) <= 0; }
+
+ friend bool __forceinline operator==(XCHAR ch1, const CMStringT& str2) { return (str2.GetLength() == 1) && (str2[0] == ch1); }
+ friend bool __forceinline operator==(const CMStringT& str1, XCHAR ch2) { return (str1.GetLength() == 1) && (str1[0] == ch2); }
+
+ friend bool __forceinline operator!=(XCHAR ch1, const CMStringT& str2) { return (str2.GetLength() != 1) || (str2[0] != ch1); }
+ friend bool __forceinline operator!=(const CMStringT& str1, XCHAR ch2) { return (str1.GetLength() != 1) || (str1[0] != ch2); }
+};
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, const CMStringT<BaseType, StringTraits>& str2);
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, typename CMStringT<BaseType, StringTraits>::PCXSTR psz2);
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(typename CMStringT<BaseType, StringTraits>::PCXSTR psz1, const CMStringT<BaseType, StringTraits>& str2);
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, wchar_t ch2);
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, char ch2);
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator + (wchar_t ch1, const CMStringT<BaseType, StringTraits>& str2);
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(char ch1, const CMStringT<BaseType, StringTraits>& str2);
+
+typedef CMStringT< wchar_t, ChTraitsCRT< wchar_t > > CMStringW;
+typedef CMStringT< char, ChTraitsCRT< char > > CMStringA;
+
+#endif // M_STRING_H__
diff --git a/include/m_string.inl b/include/m_string.inl
index 78c393e19b..6a4ec0f35b 100644
--- a/include/m_string.inl
+++ b/include/m_string.inl
@@ -1,1466 +1,1466 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-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.
-*/
-
-#pragma once
-
-#ifndef M_STRING_INL__
-
-template<typename BaseType>
-CMSimpleStringT<BaseType>::CMSimpleStringT()
-{
- CMStringData* pData = mirstr_getNil();
- Attach(pData);
-}
-
-template<typename BaseType>
-CMSimpleStringT<BaseType>::CMSimpleStringT(const CMSimpleStringT& strSrc)
-{
- CMStringData* pSrcData = strSrc.GetData();
- CMStringData* pNewData = CloneData(pSrcData);
- Attach(pNewData);
-}
-
-template<typename BaseType>
-CMSimpleStringT<BaseType>::CMSimpleStringT(PCXSTR pszSrc)
-{
- int nLength = StringLength(pszSrc);
- CMStringData* pData = mirstr_allocate(nLength, sizeof(XCHAR));
- if (pData != nullptr) {
- Attach(pData);
- SetLength(nLength);
- CopyChars(m_pszData, nLength, pszSrc, nLength);
- }
-}
-
-template<typename BaseType>
-CMSimpleStringT<BaseType>::CMSimpleStringT(const XCHAR* pchSrc, int nLength)
-{
- CMStringData* pData = mirstr_allocate(nLength, sizeof(XCHAR));
- if (pData != nullptr) {
- Attach(pData);
- SetLength(nLength);
- CopyChars(m_pszData, nLength, pchSrc, nLength);
- }
-}
-
-template<typename BaseType>
-CMSimpleStringT<BaseType>::~CMSimpleStringT()
-{
- CMStringData* pData = GetData();
- pData->Release();
-}
-
-template<typename BaseType>
-CMSimpleStringT<BaseType>& CMSimpleStringT<BaseType>::operator=(const CMSimpleStringT& strSrc)
-{
- CMStringData* pSrcData = strSrc.GetData();
- CMStringData* pOldData = GetData();
- if (pSrcData != pOldData) {
- if (pOldData->IsLocked())
- SetString(strSrc.GetString(), strSrc.GetLength());
- else {
- CMStringData* pNewData = CloneData(pSrcData);
- pOldData->Release();
- Attach(pNewData);
- }
- }
-
- return *this;
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::Append(PCXSTR pszSrc)
-{
- Append(pszSrc, StringLength(pszSrc));
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::Append(PCXSTR pszSrc, int nLength)
-{
- // See comment in SetString() about why we do this
- UINT_PTR nOffset = UINT_PTR(pszSrc - GetString());
-
- int nOldLength = GetLength();
- if (nOldLength < 0) {
- // protects from underflow
- nOldLength = 0;
- }
-
- //Make sure we don't read pass end of the terminating NULL
- int nSrcLength = StringLength(pszSrc);
- nLength = nLength > nSrcLength ? nSrcLength : nLength;
-
- int nNewLength = nOldLength + nLength;
- PXSTR pszBuffer = GetBuffer(nNewLength);
- if (nOffset <= UINT_PTR(nOldLength)) {
- pszSrc = pszBuffer + nOffset;
- // No need to call CopyCharsOverlapped, since the destination is
- // beyond the end of the original buffer
- }
- CopyChars(pszBuffer + nOldLength, nLength, pszSrc, nLength);
- ReleaseBufferSetLength(nNewLength);
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::AppendChar(XCHAR ch)
-{
- UINT nOldLength = GetLength();
- int nNewLength = nOldLength + 1;
- PXSTR pszBuffer = GetBuffer(nNewLength);
- pszBuffer[nOldLength] = ch;
- ReleaseBufferSetLength(nNewLength);
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::Append(const CMSimpleStringT<BaseType>& strSrc)
-{
- Append(strSrc.GetString(), strSrc.GetLength());
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::Empty()
-{
- CMStringData* pOldData = GetData();
- if (pOldData->nDataLength == 0)
- return;
-
- if (pOldData->IsLocked()) {
- // Don't reallocate a locked buffer that's shrinking
- SetLength(0);
- }
- else {
- pOldData->Release();
- CMStringData* pNewData = mirstr_getNil();
- Attach(pNewData);
- }
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::FreeExtra()
-{
- CMStringData* pOldData = GetData();
- int nLength = pOldData->nDataLength;
- if (pOldData->nAllocLength == nLength)
- return;
-
- if (!pOldData->IsLocked()) { // Don't reallocate a locked buffer that's shrinking
- CMStringData* pNewData = mirstr_allocate(nLength, sizeof(XCHAR));
- if (pNewData == nullptr) {
- SetLength(nLength);
- return;
- }
-
- CopyChars(PXSTR(pNewData->data()), nLength, PCXSTR(pOldData->data()), nLength);
-
- pOldData->Release();
- Attach(pNewData);
- SetLength(nLength);
- }
-}
-
-template<typename BaseType>
-typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::GetBuffer()
-{
- CMStringData* pData = GetData();
- if (pData->IsShared())
- Fork(pData->nDataLength);
-
- return m_pszData;
-}
-
-template<typename BaseType>
-typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::GetBufferSetLength(int nLength)
-{
- PXSTR pszBuffer = GetBuffer(nLength);
- SetLength(nLength);
-
- return pszBuffer;
-}
-
-template<typename BaseType>
-typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::LockBuffer()
-{
- CMStringData* pData = GetData();
- if (pData->IsShared()) {
- Fork(pData->nDataLength);
- pData = GetData(); // Do it again, because the fork might have changed it
- }
- pData->Lock();
-
- return m_pszData;
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::UnlockBuffer()
-{
- CMStringData* pData = GetData();
- pData->Unlock();
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::ReleaseBuffer(int nNewLength)
-{
- if (nNewLength == -1) {
- int nAlloc = GetData()->nAllocLength;
- nNewLength = StringLengthN(m_pszData, nAlloc);
- }
- SetLength(nNewLength);
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::Truncate(int nNewLength)
-{
- GetBuffer(nNewLength);
- ReleaseBufferSetLength(nNewLength);
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::SetAt(int iChar, XCHAR ch)
-{
- int nLength = GetLength();
- PXSTR pszBuffer = GetBuffer();
- pszBuffer[iChar] = ch;
- ReleaseBufferSetLength(nLength);
-
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::SetString(PCXSTR pszSrc)
-{
- SetString(pszSrc, StringLength(pszSrc));
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::SetString(PCXSTR pszSrc, int nLength)
-{
- if (nLength == 0)
- Empty();
- else {
- UINT nOldLength = GetLength();
- UINT_PTR nOffset = pszSrc - GetString();
-
- PXSTR pszBuffer = GetBuffer(nLength);
- if (nOffset <= nOldLength)
- CopyCharsOverlapped(pszBuffer, GetAllocLength(), pszBuffer + nOffset, nLength);
- else
- CopyChars(pszBuffer, GetAllocLength(), pszSrc, nLength);
-
- ReleaseBufferSetLength(nLength);
- }
-}
-
-template<typename BaseType>
-typename CMSimpleStringT<BaseType> operator+(const CMSimpleStringT<BaseType>& str1, const CMSimpleStringT<BaseType>& str2)
-{
- CMSimpleStringT s;
- Concatenate(s, str1, str1.GetLength(), str2, str2.GetLength());
- return s;
-}
-
-template<typename BaseType>
-typename CMSimpleStringT<BaseType> operator+(const CMSimpleStringT<BaseType>& str1, typename CMSimpleStringT<BaseType>::PCXSTR psz2)
-{
- CMSimpleStringT s;
- Concatenate(s, str1, str1.GetLength(), psz2, StringLength(psz2));
- return s;
-}
-
-template<typename BaseType>
-CMSimpleStringT<BaseType> operator+(typename CMSimpleStringT<BaseType>::PCXSTR psz1, const CMSimpleStringT<BaseType>& str2)
-{
- CMSimpleStringT s;
- Concatenate(s, psz1, StringLength(psz1), str2, str2.GetLength());
- return s;
-}
-
-template<typename BaseType>
-void __stdcall CMSimpleStringT<BaseType>::CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars)
-{
- #pragma warning (push)
- #pragma warning(disable : 4996)
- memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR));
- #pragma warning (pop)
-}
-
-template<typename BaseType>
-void __stdcall CMSimpleStringT<BaseType>::CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars)
-{
- memcpy_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
-}
-
-template<typename BaseType>
-void __stdcall CMSimpleStringT<BaseType>::CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars)
-{
- #pragma warning (push)
- #pragma warning(disable : 4996)
- memmove(pchDest, pchSrc, nChars * sizeof(XCHAR));
- #pragma warning (pop)
-}
-
-template<typename BaseType>
-void __stdcall CMSimpleStringT<BaseType>::CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars)
-{
- memmove_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
-}
-
-template<typename BaseType>
-int __stdcall CMSimpleStringT<BaseType>::StringLength(const char* psz)
-{
- if (psz == nullptr)
- return(0);
-
- return (int(strlen(psz)));
-}
-
-template<typename BaseType>
-int __stdcall CMSimpleStringT<BaseType>::StringLength(const wchar_t* psz)
-{
- if (psz == nullptr)
- return 0;
-
- return int(wcslen(psz));
-}
-
-template<typename BaseType>
-int __stdcall CMSimpleStringT<BaseType>::StringLengthN(const char* psz, size_t sizeInXChar)
-{
- if (psz == nullptr)
- return 0;
-
- return int(strnlen(psz, sizeInXChar));
-}
-
-template<typename BaseType>
-int __stdcall CMSimpleStringT<BaseType>::StringLengthN(const wchar_t* psz, size_t sizeInXChar)
-{
- if (psz == nullptr)
- return 0;
-
- return int(wcsnlen(psz, sizeInXChar));
-}
-
-template<typename BaseType>
-void __stdcall CMSimpleStringT<BaseType>::Concatenate(CMSimpleStringT<BaseType>& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2)
-{
- int nNewLength = nLength1 + nLength2;
- PXSTR pszBuffer = strResult.GetBuffer(nNewLength);
- CopyChars(pszBuffer, nLength1, psz1, nLength1);
- CopyChars(pszBuffer + nLength1, nLength2, psz2, nLength2);
- strResult.ReleaseBufferSetLength(nNewLength);
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::Attach(CMStringData* pData)
-{
- m_pszData = static_cast<PXSTR>(pData->data());
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::Fork(int nLength)
-{
- CMStringData* pOldData = GetData();
- int nOldLength = pOldData->nDataLength;
- CMStringData* pNewData = mirstr_allocate(nLength, sizeof(XCHAR));
- if (pNewData != nullptr) {
- int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength) + 1; // Copy '\0'
- CopyChars(PXSTR(pNewData->data()), nCharsToCopy, PCXSTR(pOldData->data()), nCharsToCopy);
- pNewData->nDataLength = nOldLength;
- pOldData->Release();
- Attach(pNewData);
- }
-}
-
-template<typename BaseType>
-typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::PrepareWrite(int nLength)
-{
- CMStringData* pOldData = GetData();
- int nShared = 1 - pOldData->nRefs; // nShared < 0 means true, >= 0 means false
- int nTooShort = pOldData->nAllocLength - nLength; // nTooShort < 0 means true, >= 0 means false
- if ((nShared | nTooShort) < 0) // If either sign bit is set (i.e. either is less than zero), we need to copy data
- PrepareWrite2(nLength);
-
- return m_pszData;
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::PrepareWrite2(int nLength)
-{
- CMStringData* pOldData = GetData();
- if (pOldData->nDataLength > nLength)
- nLength = pOldData->nDataLength;
-
- if (pOldData->IsShared()) {
- Fork(nLength);
- }
- else if (pOldData->nAllocLength < nLength) {
- // Grow exponentially, until we hit 1K.
- int nNewLength = pOldData->nAllocLength;
- if (nNewLength > 1024)
- nNewLength += 1024;
- else
- nNewLength *= 2;
-
- if (nNewLength < nLength)
- nNewLength = nLength;
-
- Reallocate(nNewLength);
- }
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::Reallocate(int nLength)
-{
- CMStringData* pOldData = GetData();
- if (pOldData->nAllocLength >= nLength || nLength <= 0)
- return;
-
- CMStringData* pNewData = mirstr_realloc(pOldData, nLength, sizeof(XCHAR));
- if (pNewData != nullptr)
- Attach(pNewData);
-}
-
-template<typename BaseType>
-void CMSimpleStringT<BaseType>::SetLength(int nLength)
-{
- GetData()->nDataLength = nLength;
- m_pszData[nLength] = 0;
-}
-
-template<typename BaseType>
-CMStringData* __stdcall CMSimpleStringT<BaseType>::CloneData(CMStringData* pData)
-{
- CMStringData* pNewData = nullptr;
-
- if (!pData->IsLocked()) {
- pNewData = pData;
- pNewData->AddRef();
- }
-
- return pNewData;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT() :
- CThisSimpleString()
-{
-}
-
-// Copy constructor
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(const CMStringT<BaseType, StringTraits>& strSrc) :
- CThisSimpleString(strSrc)
-{
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(const XCHAR* pszSrc) :
- CThisSimpleString()
-{
- *this = pszSrc;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(CMStringDataFormat, const XCHAR* pszFormat, ...) :
- CThisSimpleString()
-{
- va_list args;
- va_start(args, pszFormat);
- FormatV(pszFormat, args);
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(const YCHAR* pszSrc) :
- CThisSimpleString()
-{
- *this = pszSrc;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(const unsigned char* pszSrc) :
- CThisSimpleString()
-{
- *this = reinterpret_cast<const char*>(pszSrc);
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(char ch, int nLength) :
- CThisSimpleString()
-{
- if (nLength > 0) {
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::FloodCharacters(XCHAR(ch), nLength, pszBuffer);
- this->ReleaseBufferSetLength(nLength);
- }
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(wchar_t ch, int nLength) :
- CThisSimpleString()
-{
- if (nLength > 0) {
- //Convert ch to the BaseType
- wchar_t pszCh[2] = { ch, 0 };
- int nBaseTypeCharLen = 1;
-
- if (ch != L'\0')
- nBaseTypeCharLen = StringTraits::GetBaseTypeLength(pszCh);
-
- XCHAR *buffBaseTypeChar = new XCHAR[nBaseTypeCharLen + 1];
- StringTraits::ConvertToBaseType(buffBaseTypeChar, nBaseTypeCharLen + 1, pszCh, 1);
- //allocate enough characters in String and flood (replicate) with the (converted character)*nLength
- PXSTR pszBuffer = this->GetBuffer(nLength*nBaseTypeCharLen);
- if (nBaseTypeCharLen == 1) //Optimization for a common case - wide char translates to 1 ansi/wide char.
- StringTraits::FloodCharacters(buffBaseTypeChar[0], nLength, pszBuffer);
- else {
- XCHAR* p = pszBuffer;
- for (int i = 0; i < nLength; i++) {
- for (int j = 0; j < nBaseTypeCharLen; ++j) {
- *p = buffBaseTypeChar[j];
- ++p;
- }
- }
- }
- this->ReleaseBufferSetLength(nLength*nBaseTypeCharLen);
- delete[] buffBaseTypeChar;
- }
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(const XCHAR* pch, int nLength) :
- CThisSimpleString(pch, nLength)
-{
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::CMStringT(const YCHAR* pch, int nLength) :
- CThisSimpleString()
-{
- if (nLength > 0) {
- int nDestLength = StringTraits::GetBaseTypeLength(pch, nLength);
- PXSTR pszBuffer = this->GetBuffer(nDestLength);
- StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pch, nLength);
- this->ReleaseBufferSetLength(nDestLength);
- }
-}
-
-// Destructor
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>::~CMStringT()
-{
-}
-
-// Assignment operators
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(const CMStringT& strSrc)
-{
- CThisSimpleString::operator=(strSrc);
- return *this;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(PCXSTR pszSrc)
-{
- CThisSimpleString::operator=(pszSrc);
- return *this;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(PCYSTR pszSrc)
-{
- // nDestLength is in XCHARs
- int nDestLength = (pszSrc != nullptr) ? StringTraits::GetBaseTypeLength(pszSrc) : 0;
- if (nDestLength > 0) {
- PXSTR pszBuffer = this->GetBuffer(nDestLength);
- StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pszSrc);
- this->ReleaseBufferSetLength(nDestLength);
- }
- else this->Empty();
-
- return *this;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(const unsigned char* pszSrc)
-{
- return operator=(reinterpret_cast<const char*>(pszSrc));
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(char ch)
-{
- char ach[2] = { ch, 0 };
- return operator=(ach);
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(wchar_t ch)
-{
- wchar_t ach[2] = { ch, 0 };
- return operator=(ach);
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(const CMStringT& str)
-{
- CThisSimpleString::operator+=(str);
- return *this;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(const CThisSimpleString& str)
-{
- CThisSimpleString::operator+=(str);
- return *this;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(PCXSTR pszSrc)
-{
- CThisSimpleString::operator+=(pszSrc);
- return *this;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(PCYSTR pszSrc)
-{
- CMStringT str(pszSrc);
- return operator+=(str);
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(char ch)
-{
- CThisSimpleString::operator+=(ch);
- return *this;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(unsigned char ch)
-{
- CThisSimpleString::operator+=(ch);
- return *this;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(wchar_t ch)
-{
- CThisSimpleString::operator+=(ch);
- return *this;
-}
-
-// Comparison
-
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Compare(PCXSTR psz) const
-{
- return StringTraits::StringCompare(this->GetString(), psz);
-}
-
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::CompareNoCase(PCXSTR psz) const
-{
- return StringTraits::StringCompareIgnore(this->GetString(), psz);
-}
-
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Collate(PCXSTR psz) const
-{
- return StringTraits::StringCollate(this->GetString(), psz);
-}
-
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::CollateNoCase(PCXSTR psz) const
-{
- return StringTraits::StringCollateIgnore(this->GetString(), psz);
-}
-
-// Advanced manipulation
-
-// Delete 'nCount' characters, starting at index 'iIndex'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Delete(int iIndex, int nCount)
-{
- if (iIndex < 0)
- iIndex = 0;
-
- if (nCount < 0)
- nCount = 0;
-
- int nLength = this->GetLength();
- if (nCount + iIndex > nLength)
- nCount = nLength - iIndex;
-
- if (nCount > 0) {
- int nNewLength = nLength - nCount;
- int nXCHARsToCopy = nLength - (iIndex + nCount) + 1;
- PXSTR pszBuffer = this->GetBuffer();
-#if _MSC_VER >= 1400
- memmove_s(pszBuffer + iIndex, nXCHARsToCopy*sizeof(XCHAR), pszBuffer + iIndex + nCount, nXCHARsToCopy*sizeof(XCHAR));
-#else
- memmove(pszBuffer+iIndex, pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof(XCHAR));
-#endif
- this->ReleaseBufferSetLength(nNewLength);
- }
-
- return this->GetLength();
-}
-
-// Insert character 'ch' before index 'iIndex'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Insert(int iIndex, XCHAR ch)
-{
- if (iIndex < 0)
- iIndex = 0;
-
- if (iIndex > this->GetLength())
- iIndex = this->GetLength();
-
- int nNewLength = this->GetLength() + 1;
-
- PXSTR pszBuffer = this->GetBuffer(nNewLength);
-
- // move existing bytes down
-#if _MSC_VER >= 1400
- memmove_s(pszBuffer + iIndex + 1, (nNewLength - iIndex)*sizeof(XCHAR), pszBuffer + iIndex, (nNewLength - iIndex)*sizeof(XCHAR));
-#else
- memmove(pszBuffer+iIndex+1, pszBuffer+iIndex, (nNewLength-iIndex)*sizeof(XCHAR));
-#endif
- pszBuffer[iIndex] = ch;
-
- this->ReleaseBufferSetLength(nNewLength);
- return nNewLength;
-}
-
-// Insert string 'psz' before index 'iIndex'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Insert(int iIndex, PCXSTR psz)
-{
- if (iIndex < 0)
- iIndex = 0;
-
- if (iIndex > this->GetLength())
- iIndex = this->GetLength();
-
- // nInsertLength and nNewLength are in XCHARs
- int nInsertLength = StringTraits::SafeStringLen(psz);
- int nNewLength = this->GetLength();
- if (nInsertLength > 0) {
- nNewLength += nInsertLength;
-
- PXSTR pszBuffer = this->GetBuffer(nNewLength);
- // move existing bytes down
-#if _MSC_VER >= 1400
- memmove_s(pszBuffer + iIndex + nInsertLength, (nNewLength - iIndex - nInsertLength + 1)*sizeof(XCHAR), pszBuffer + iIndex, (nNewLength - iIndex - nInsertLength + 1)*sizeof(XCHAR));
- memcpy_s(pszBuffer + iIndex, nInsertLength*sizeof(XCHAR), psz, nInsertLength*sizeof(XCHAR));
-#else
- memmove(pszBuffer+iIndex+nInsertLength, pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR));
- memcpy(pszBuffer+iIndex, psz, nInsertLength*sizeof(XCHAR));
-#endif
- this->ReleaseBufferSetLength(nNewLength);
- }
-
- return nNewLength;
-}
-
-// Replace all occurrences of character 'chOld' with character 'chNew'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Replace(XCHAR chOld, XCHAR chNew)
-{
- int nCount = 0;
-
- // short-circuit the nop case
- if (chOld != chNew) {
- // otherwise modify each character that matches in the string
- bool bCopied = false;
- PXSTR pszBuffer = const_cast<PXSTR>(this->GetString()); // We don't actually write to pszBuffer until we've called GetBuffer().
-
- int nLength = this->GetLength();
- int iChar = 0;
- while (iChar < nLength) {
- // replace instances of the specified character only
- if (pszBuffer[iChar] == chOld) {
- if (!bCopied) {
- bCopied = true;
- pszBuffer = this->GetBuffer(nLength);
- }
- pszBuffer[iChar] = chNew;
- nCount++;
- }
- iChar = int(StringTraits::CharNext(pszBuffer + iChar) - pszBuffer);
- }
-
- if (bCopied)
- this->ReleaseBufferSetLength(nLength);
- }
-
- return nCount;
-}
-
-// Replace all occurrences of string 'pszOld' with string 'pszNew'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Replace(PCXSTR pszOld, PCXSTR pszNew)
-{
- // can't have empty or NULL lpszOld
-
- // nSourceLen is in XCHARs
- int nSourceLen = StringTraits::SafeStringLen(pszOld);
- if (nSourceLen == 0)
- return 0;
- // nReplacementLen is in XCHARs
- int nReplacementLen = StringTraits::SafeStringLen(pszNew);
-
- // loop once to figure out the size of the result string
- int nCount = 0;
- {
- PCXSTR pszStart = this->GetString();
- PCXSTR pszEnd = pszStart + this->GetLength();
- while (pszStart < pszEnd) {
- PCXSTR pszTarget;
- while ((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != nullptr) {
- nCount++;
- pszStart = pszTarget + nSourceLen;
- }
- pszStart += StringTraits::SafeStringLen(pszStart) + 1;
- }
- }
-
- // if any changes were made, make them
- if (nCount > 0) {
- // if the buffer is too small, just
- // allocate a new buffer (slow but sure)
- int nOldLength = this->GetLength();
- int nNewLength = nOldLength + (nReplacementLen - nSourceLen)*nCount;
-
- PXSTR pszBuffer = this->GetBuffer(__max(nNewLength, nOldLength));
-
- PXSTR pszStart = pszBuffer;
- PXSTR pszEnd = pszStart + nOldLength;
-
- // loop again to actually do the work
- while (pszStart < pszEnd) {
- PXSTR pszTarget;
- while ((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != nullptr) {
- int nBalance = nOldLength - int(pszTarget - pszBuffer + nSourceLen);
- memmove_s(pszTarget + nReplacementLen, nBalance*sizeof(XCHAR),
- pszTarget + nSourceLen, nBalance*sizeof(XCHAR));
- memcpy_s(pszTarget, nReplacementLen*sizeof(XCHAR),
- pszNew, nReplacementLen*sizeof(XCHAR));
- pszStart = pszTarget + nReplacementLen;
- pszTarget[nReplacementLen + nBalance] = 0;
- nOldLength += (nReplacementLen - nSourceLen);
- }
- pszStart += StringTraits::SafeStringLen(pszStart) + 1;
- }
- this->ReleaseBufferSetLength(nNewLength);
- }
-
- return nCount;
-}
-
-// Remove all occurrences of character 'chRemove'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Remove(XCHAR chRemove)
-{
- int nLength = this->GetLength();
- PXSTR pszBuffer = this->GetBuffer(nLength);
-
- PXSTR pszSource = pszBuffer;
- PXSTR pszDest = pszBuffer;
- PXSTR pszEnd = pszBuffer + nLength;
-
- while (pszSource < pszEnd) {
- PXSTR pszNewSource = StringTraits::CharNext(pszSource);
- if (*pszSource != chRemove) {
- // Copy the source to the destination. Remember to copy all bytes of an MBCS character
- size_t NewSourceGap = (pszNewSource - pszSource);
- PXSTR pszNewDest = pszDest + NewSourceGap;
- for (size_t i = 0; pszDest != pszNewDest && i < NewSourceGap; i++) {
- *pszDest = *pszSource;
- pszSource++;
- pszDest++;
- }
- }
- pszSource = pszNewSource;
- }
- *pszDest = 0;
- int nCount = int(pszSource - pszDest);
- this->ReleaseBufferSetLength(nLength - nCount);
-
- return nCount;
-}
-
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Tokenize(PCXSTR pszTokens, int& iStart) const
-{
- if ((pszTokens == nullptr) || (*pszTokens == (XCHAR)0)) {
- if (iStart < this->GetLength())
- return CMStringT(this->GetString() + iStart);
- }
- else {
- PCXSTR pszPlace = this->GetString() + iStart;
- PCXSTR pszEnd = this->GetString() + this->GetLength();
- if (pszPlace < pszEnd) {
- int nIncluding = StringTraits::StringSpanIncluding(pszPlace, pszTokens);
-
- if ((pszPlace + nIncluding) < pszEnd) {
- pszPlace += nIncluding;
- int nExcluding = StringTraits::StringSpanExcluding(pszPlace, pszTokens);
-
- int iFrom = iStart + nIncluding;
- int nUntil = nExcluding;
- iStart = iFrom + nUntil + 1;
-
- return Mid(iFrom, nUntil);
- }
- }
- }
-
- // return empty string, done tokenizing
- iStart = -1;
-
- return CMStringT();
-}
-
-// find routines
-
-// Find the first occurrence of character 'ch', starting at index 'iStart'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Find(XCHAR ch, int iStart) const
-{
- // nLength is in XCHARs
- int nLength = this->GetLength();
- if (iStart < 0 || iStart >= nLength)
- return -1;
-
- // find first single character
- PCXSTR psz = StringTraits::StringFindChar(this->GetString() + iStart, ch);
-
- // return -1 if not found and index otherwise
- return (psz == nullptr) ? -1 : int(psz - this->GetString());
-}
-
-// look for a specific sub-string
-
-// Find the first occurrence of string 'pszSub', starting at index 'iStart'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::Find(PCXSTR pszSub, int iStart) const
-{
- // iStart is in XCHARs
- if (pszSub == nullptr)
- return -1;
-
- // nLength is in XCHARs
- int nLength = this->GetLength();
- if (iStart < 0 || iStart > nLength)
- return -1;
-
- // find first matching substring
- PCXSTR psz = StringTraits::StringFindString(this->GetString() + iStart, pszSub);
-
- // return -1 for not found, distance from beginning otherwise
- return (psz == nullptr) ? -1 : int(psz - this->GetString());
-}
-
-// Find the first occurrence of any of the characters in string 'pszCharSet'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::FindOneOf(PCXSTR pszCharSet) const
-{
- PCXSTR psz = StringTraits::StringScanSet(this->GetString(), pszCharSet);
- return (psz == nullptr) ? -1 : int(psz - this->GetString());
-}
-
-// Find the last occurrence of character 'ch'
-template< typename BaseType, class StringTraits >
-int CMStringT<BaseType, StringTraits>::ReverseFind(XCHAR ch) const
-{
- // find last single character
- PCXSTR psz = StringTraits::StringFindCharRev(this->GetString(), ch);
-
- // return -1 if not found, distance from beginning otherwise
- return (psz == nullptr) ? -1 : int(psz - this->GetString());
-}
-
-// manipulation
-
-// Convert the string to uppercase
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::MakeUpper()
-{
- int nLength = this->GetLength();
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::StringUppercase(pszBuffer, nLength + 1);
- this->ReleaseBufferSetLength(nLength);
-
- return *this;
-}
-
-// Convert the string to lowercase
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::MakeLower()
-{
- int nLength = this->GetLength();
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::StringLowercase(pszBuffer, nLength + 1);
- this->ReleaseBufferSetLength(nLength);
-
- return *this;
-}
-
-// Reverse the string
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::MakeReverse()
-{
- int nLength = this->GetLength();
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::StringReverse(pszBuffer);
- this->ReleaseBufferSetLength(nLength);
-
- return *this;
-}
-
-// trimming
-
-// Remove all trailing whitespace
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimRight()
-{
- // find beginning of trailing spaces by starting
- // at beginning (DBCS aware)
-
- PCXSTR psz = this->GetString();
- PCXSTR pszLast = nullptr;
-
- while (*psz != 0) {
- if (StringTraits::IsSpace(*psz)) {
- if (pszLast == nullptr)
- pszLast = psz;
- }
- else pszLast = nullptr;
-
- psz = StringTraits::CharNext(psz);
- }
-
- if (pszLast != nullptr) {
- // truncate at trailing space start
- int iLast = int(pszLast - this->GetString());
-
- this->Truncate(iLast);
- }
-
- return *this;
-}
-
-// Remove all leading whitespace
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimLeft()
-{
- // find first non-space character
-
- PCXSTR psz = this->GetString();
- while (StringTraits::IsSpace(*psz))
- psz = StringTraits::CharNext(psz);
-
- if (psz != this->GetString()) {
- // fix up data and length
- int iFirst = int(psz - this->GetString());
- PXSTR pszBuffer = this->GetBuffer(this->GetLength());
- psz = pszBuffer + iFirst;
- int nDataLength = this->GetLength() - iFirst;
- memmove_s(pszBuffer, (this->GetLength() + 1)*sizeof(XCHAR),
- psz, (nDataLength + 1)*sizeof(XCHAR));
- this->ReleaseBufferSetLength(nDataLength);
- }
-
- return *this;
-}
-
-// Remove all leading and trailing whitespace
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim()
-{
- return TrimRight().TrimLeft();
-}
-
-// Remove all leading and trailing occurrences of character 'chTarget'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim(XCHAR chTarget)
-{
- return TrimRight(chTarget).TrimLeft(chTarget);
-}
-
-// Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim(PCXSTR pszTargets)
-{
- return TrimRight(pszTargets).TrimLeft(pszTargets);
-}
-
-// trimming anything (either side)
-
-// Remove all trailing occurrences of character 'chTarget'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimRight(XCHAR chTarget)
-{
- // find beginning of trailing matches
- // by starting at beginning (DBCS aware)
-
- PCXSTR psz = this->GetString();
- PCXSTR pszLast = nullptr;
-
- while (*psz != 0) {
- if (*psz == chTarget) {
- if (pszLast == nullptr)
- pszLast = psz;
- }
- else pszLast = nullptr;
-
- psz = StringTraits::CharNext(psz);
- }
-
- if (pszLast != nullptr) {
- // truncate at left-most matching character
- int iLast = int(pszLast - this->GetString());
- this->Truncate(iLast);
- }
-
- return *this;
-}
-
-// Remove all trailing occurrences of any of the characters in string 'pszTargets'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimRight(PCXSTR pszTargets)
-{
- // if we're not trimming anything, we're not doing any work
- if ((pszTargets == nullptr) || (*pszTargets == 0)) {
- return *this;
- }
-
- // find beginning of trailing matches
- // by starting at beginning (DBCS aware)
-
- PCXSTR psz = this->GetString();
- PCXSTR pszLast = nullptr;
-
- while (*psz != 0) {
- if (StringTraits::StringFindChar(pszTargets, *psz) != nullptr) {
- if (pszLast == nullptr) {
- pszLast = psz;
- }
- }
- else {
- pszLast = nullptr;
- }
- psz = StringTraits::CharNext(psz);
- }
-
- if (pszLast != nullptr) {
- // truncate at left-most matching character
- int iLast = int(pszLast - this->GetString());
- this->Truncate(iLast);
- }
-
- return *this;
-}
-
-// Remove all leading occurrences of character 'chTarget'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimLeft(XCHAR chTarget)
-{
- // find first non-matching character
- PCXSTR psz = this->GetString();
-
- while (chTarget == *psz) {
- psz = StringTraits::CharNext(psz);
- }
-
- if (psz != this->GetString()) {
- // fix up data and length
- int iFirst = int(psz - this->GetString());
- PXSTR pszBuffer = this->GetBuffer(this->GetLength());
- psz = pszBuffer + iFirst;
- int nDataLength = this->GetLength() - iFirst;
- memmove_s(pszBuffer, (this->GetLength() + 1)*sizeof(XCHAR),
- psz, (nDataLength + 1)*sizeof(XCHAR));
- this->ReleaseBufferSetLength(nDataLength);
- }
-
- return *this;
-}
-
-// Remove all leading occurrences of any of the characters in string 'pszTargets'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimLeft(PCXSTR pszTargets)
-{
- // if we're not trimming anything, we're not doing any work
- if ((pszTargets == nullptr) || (*pszTargets == 0)) {
- return *this;
- }
-
- PCXSTR psz = this->GetString();
- while ((*psz != 0) && (StringTraits::StringFindChar(pszTargets, *psz) != nullptr)) {
- psz = StringTraits::CharNext(psz);
- }
-
- if (psz != this->GetString()) {
- // fix up data and length
- int iFirst = int(psz - this->GetString());
- PXSTR pszBuffer = this->GetBuffer(this->GetLength());
- psz = pszBuffer + iFirst;
- int nDataLength = this->GetLength() - iFirst;
- memmove_s(pszBuffer, (this->GetLength() + 1)*sizeof(XCHAR),
- psz, (nDataLength + 1)*sizeof(XCHAR));
- this->ReleaseBufferSetLength(nDataLength);
- }
-
- return *this;
-}
-
-// Convert the string to the OEM character set
-template< typename BaseType, class StringTraits >
-void CMStringT<BaseType, StringTraits>::AnsiToOem()
-{
- int nLength = this->GetLength();
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::ConvertToOem(pszBuffer, nLength + 1);
- this->ReleaseBufferSetLength(nLength);
-}
-
-// Convert the string to the ANSI character set
-template< typename BaseType, class StringTraits >
-void CMStringT<BaseType, StringTraits>::OemToAnsi()
-{
- int nLength = this->GetLength();
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::ConvertToAnsi(pszBuffer, nLength + 1);
- this->ReleaseBufferSetLength(nLength);
-}
-
-// Very simple sub-string extraction
-
-// Return the substring starting at index 'iFirst'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Mid(int iFirst) const
-{
- return Mid(iFirst, this->GetLength() - iFirst);
-}
-
-// Return the substring starting at index 'iFirst', with length 'nCount'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Mid(int iFirst, int nCount) const
-{
- // nCount is in XCHARs
-
- // out-of-bounds requests return sensible things
- if (iFirst < 0)
- iFirst = 0;
- if (nCount < 0)
- nCount = 0;
-
- if ((iFirst + nCount) > this->GetLength())
- nCount = this->GetLength() - iFirst;
-
- if (iFirst > this->GetLength())
- nCount = 0;
-
- // optimize case of returning entire string
- if ((iFirst == 0) && ((iFirst + nCount) == this->GetLength()))
- return *this;
-
- return CMStringT(this->GetString() + iFirst, nCount);
-}
-
-// Return the substring consisting of the rightmost 'nCount' characters
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Right(int nCount) const
-{
- // nCount is in XCHARs
- if (nCount < 0)
- nCount = 0;
-
- int nLength = this->GetLength();
- if (nCount >= nLength)
- return *this;
-
- return CMStringT(this->GetString() + nLength - nCount, nCount);
-}
-
-// Return the substring consisting of the leftmost 'nCount' characters
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Left(int nCount) const
-{
- // nCount is in XCHARs
- if (nCount < 0)
- nCount = 0;
-
- int nLength = this->GetLength();
- if (nCount >= nLength)
- return *this;
-
- return CMStringT(this->GetString(), nCount);
-}
-
-// Return the substring consisting of the leftmost characters in the set 'pszCharSet'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::SpanIncluding(PCXSTR pszCharSet) const
-{
- return Left(StringTraits::StringSpanIncluding(this->GetString(), pszCharSet));
-}
-
-// Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
-template< typename BaseType, class StringTraits >
-CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::SpanExcluding(PCXSTR pszCharSet) const
-{
- return Left(StringTraits::StringSpanExcluding(this->GetString(), pszCharSet));
-}
-
-// Format data using format string 'pszFormat'
-template< typename BaseType, class StringTraits >
-typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::Format(PCXSTR pszFormat, ...)
-{
- va_list argList;
- va_start(argList, pszFormat);
- FormatV(pszFormat, argList);
- va_end(argList);
- return GetString();
-}
-
-// Append formatted data using format string 'pszFormat'
-template< typename BaseType, class StringTraits >
-typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::AppendFormat(PCXSTR pszFormat, ...)
-{
- va_list argList;
- va_start(argList, pszFormat);
- AppendFormatV(pszFormat, argList);
- va_end(argList);
- return GetString();
-}
-
-template< typename BaseType, class StringTraits >
-void CMStringT<BaseType, StringTraits>::AppendFormatV(PCXSTR pszFormat, va_list args)
-{
- int nCurrentLength = this->GetLength();
- int nAppendLength = StringTraits::GetFormattedLength(pszFormat, args);
- PXSTR pszBuffer = this->GetBuffer(nCurrentLength + nAppendLength);
- StringTraits::Format(pszBuffer + nCurrentLength, nAppendLength + 1, pszFormat, args);
- this->ReleaseBufferSetLength(nCurrentLength + nAppendLength);
-}
-
-template< typename BaseType, class StringTraits >
-typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::FormatV(PCXSTR pszFormat, va_list args)
-{
- int nLength = StringTraits::GetFormattedLength(pszFormat, args);
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::Format(pszBuffer, nLength + 1, pszFormat, args);
- this->ReleaseBufferSetLength(nLength);
- return GetString();
-}
-
-// Set the string to the value of environment variable 'pszVar'
-template< typename BaseType, class StringTraits >
-BOOL CMStringT<BaseType, StringTraits>::GetEnvironmentVariable(PCXSTR pszVar)
-{
- ULONG nLength = StringTraits::GetEnvironmentVariable(pszVar, nullptr, 0);
- BOOL bRetVal = FALSE;
-
- if (nLength == 0)
- this->Empty();
- else {
- PXSTR pszBuffer = this->GetBuffer(nLength);
- StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength);
- this->ReleaseBuffer();
- bRetVal = TRUE;
- }
-
- return bRetVal;
-}
-
-// Set the string to the value of environment variable 'pszVar'
-template< typename BaseType, class StringTraits >
-typename CMStringT<BaseType, StringTraits>::PXSTR CMStringT<BaseType, StringTraits>::Detach() const
-{
- return StringTraits::MirCopy(CMStringT<BaseType, StringTraits>::GetString(), GetLength());
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, const CMStringT<BaseType, StringTraits>& str2)
-{
- CMStringT<BaseType, StringTraits> strResult;
- CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), str2, str2.GetLength());
- return strResult;
-}
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, typename CMStringT<BaseType, StringTraits>::PCXSTR psz2)
-{
- CMStringT<BaseType, StringTraits> strResult;
- CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), psz2, CMStringT<BaseType, StringTraits>::StringLength(psz2));
- return strResult;
-}
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(typename CMStringT<BaseType, StringTraits>::PCXSTR psz1, const CMStringT<BaseType, StringTraits>& str2)
-{
- CMStringT<BaseType, StringTraits> strResult;
- CMStringT<BaseType, StringTraits>::Concatenate(strResult, psz1, CMStringT<BaseType, StringTraits>::StringLength(psz1), str2, str2.GetLength());
- return strResult;
-}
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, wchar_t ch2)
-{
- CMStringT<BaseType, StringTraits> strResult;
- typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch2);
- CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
- return strResult;
-}
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, char ch2)
-{
- CMStringT<BaseType, StringTraits> strResult;
- typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch2);
- CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
- return strResult;
-}
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(wchar_t ch1, const CMStringT<BaseType, StringTraits>& str2)
-{
- CMStringT<BaseType, StringTraits> strResult;
- typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch1);
- CMStringT<BaseType, StringTraits>::Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
- return strResult;
-}
-
-template< typename BaseType, class StringTraits >
-MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(char ch1, const CMStringT<BaseType, StringTraits>& str2)
-{
- CMStringT<BaseType, StringTraits> strResult;
- typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch1);
- CMStringT<BaseType, StringTraits>::Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
- return strResult;
-}
-
-#endif // M_STRING_INL__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+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.
+*/
+
+#pragma once
+
+#ifndef M_STRING_INL__
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::CMSimpleStringT()
+{
+ CMStringData* pData = mirstr_getNil();
+ Attach(pData);
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::CMSimpleStringT(const CMSimpleStringT& strSrc)
+{
+ CMStringData* pSrcData = strSrc.GetData();
+ CMStringData* pNewData = CloneData(pSrcData);
+ Attach(pNewData);
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::CMSimpleStringT(PCXSTR pszSrc)
+{
+ int nLength = StringLength(pszSrc);
+ CMStringData* pData = mirstr_allocate(nLength, sizeof(XCHAR));
+ if (pData != nullptr) {
+ Attach(pData);
+ SetLength(nLength);
+ CopyChars(m_pszData, nLength, pszSrc, nLength);
+ }
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::CMSimpleStringT(const XCHAR* pchSrc, int nLength)
+{
+ CMStringData* pData = mirstr_allocate(nLength, sizeof(XCHAR));
+ if (pData != nullptr) {
+ Attach(pData);
+ SetLength(nLength);
+ CopyChars(m_pszData, nLength, pchSrc, nLength);
+ }
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>::~CMSimpleStringT()
+{
+ CMStringData* pData = GetData();
+ pData->Release();
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType>& CMSimpleStringT<BaseType>::operator=(const CMSimpleStringT& strSrc)
+{
+ CMStringData* pSrcData = strSrc.GetData();
+ CMStringData* pOldData = GetData();
+ if (pSrcData != pOldData) {
+ if (pOldData->IsLocked())
+ SetString(strSrc.GetString(), strSrc.GetLength());
+ else {
+ CMStringData* pNewData = CloneData(pSrcData);
+ pOldData->Release();
+ Attach(pNewData);
+ }
+ }
+
+ return *this;
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Append(PCXSTR pszSrc)
+{
+ Append(pszSrc, StringLength(pszSrc));
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Append(PCXSTR pszSrc, int nLength)
+{
+ // See comment in SetString() about why we do this
+ UINT_PTR nOffset = UINT_PTR(pszSrc - GetString());
+
+ int nOldLength = GetLength();
+ if (nOldLength < 0) {
+ // protects from underflow
+ nOldLength = 0;
+ }
+
+ //Make sure we don't read pass end of the terminating NULL
+ int nSrcLength = StringLength(pszSrc);
+ nLength = nLength > nSrcLength ? nSrcLength : nLength;
+
+ int nNewLength = nOldLength + nLength;
+ PXSTR pszBuffer = GetBuffer(nNewLength);
+ if (nOffset <= UINT_PTR(nOldLength)) {
+ pszSrc = pszBuffer + nOffset;
+ // No need to call CopyCharsOverlapped, since the destination is
+ // beyond the end of the original buffer
+ }
+ CopyChars(pszBuffer + nOldLength, nLength, pszSrc, nLength);
+ ReleaseBufferSetLength(nNewLength);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::AppendChar(XCHAR ch)
+{
+ UINT nOldLength = GetLength();
+ int nNewLength = nOldLength + 1;
+ PXSTR pszBuffer = GetBuffer(nNewLength);
+ pszBuffer[nOldLength] = ch;
+ ReleaseBufferSetLength(nNewLength);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Append(const CMSimpleStringT<BaseType>& strSrc)
+{
+ Append(strSrc.GetString(), strSrc.GetLength());
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Empty()
+{
+ CMStringData* pOldData = GetData();
+ if (pOldData->nDataLength == 0)
+ return;
+
+ if (pOldData->IsLocked()) {
+ // Don't reallocate a locked buffer that's shrinking
+ SetLength(0);
+ }
+ else {
+ pOldData->Release();
+ CMStringData* pNewData = mirstr_getNil();
+ Attach(pNewData);
+ }
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::FreeExtra()
+{
+ CMStringData* pOldData = GetData();
+ int nLength = pOldData->nDataLength;
+ if (pOldData->nAllocLength == nLength)
+ return;
+
+ if (!pOldData->IsLocked()) { // Don't reallocate a locked buffer that's shrinking
+ CMStringData* pNewData = mirstr_allocate(nLength, sizeof(XCHAR));
+ if (pNewData == nullptr) {
+ SetLength(nLength);
+ return;
+ }
+
+ CopyChars(PXSTR(pNewData->data()), nLength, PCXSTR(pOldData->data()), nLength);
+
+ pOldData->Release();
+ Attach(pNewData);
+ SetLength(nLength);
+ }
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::GetBuffer()
+{
+ CMStringData* pData = GetData();
+ if (pData->IsShared())
+ Fork(pData->nDataLength);
+
+ return m_pszData;
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::GetBufferSetLength(int nLength)
+{
+ PXSTR pszBuffer = GetBuffer(nLength);
+ SetLength(nLength);
+
+ return pszBuffer;
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::LockBuffer()
+{
+ CMStringData* pData = GetData();
+ if (pData->IsShared()) {
+ Fork(pData->nDataLength);
+ pData = GetData(); // Do it again, because the fork might have changed it
+ }
+ pData->Lock();
+
+ return m_pszData;
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::UnlockBuffer()
+{
+ CMStringData* pData = GetData();
+ pData->Unlock();
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::ReleaseBuffer(int nNewLength)
+{
+ if (nNewLength == -1) {
+ int nAlloc = GetData()->nAllocLength;
+ nNewLength = StringLengthN(m_pszData, nAlloc);
+ }
+ SetLength(nNewLength);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Truncate(int nNewLength)
+{
+ GetBuffer(nNewLength);
+ ReleaseBufferSetLength(nNewLength);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::SetAt(int iChar, XCHAR ch)
+{
+ int nLength = GetLength();
+ PXSTR pszBuffer = GetBuffer();
+ pszBuffer[iChar] = ch;
+ ReleaseBufferSetLength(nLength);
+
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::SetString(PCXSTR pszSrc)
+{
+ SetString(pszSrc, StringLength(pszSrc));
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::SetString(PCXSTR pszSrc, int nLength)
+{
+ if (nLength == 0)
+ Empty();
+ else {
+ UINT nOldLength = GetLength();
+ UINT_PTR nOffset = pszSrc - GetString();
+
+ PXSTR pszBuffer = GetBuffer(nLength);
+ if (nOffset <= nOldLength)
+ CopyCharsOverlapped(pszBuffer, GetAllocLength(), pszBuffer + nOffset, nLength);
+ else
+ CopyChars(pszBuffer, GetAllocLength(), pszSrc, nLength);
+
+ ReleaseBufferSetLength(nLength);
+ }
+}
+
+template<typename BaseType>
+class CMSimpleStringT<BaseType> operator+(const CMSimpleStringT<BaseType>& str1, const CMSimpleStringT<BaseType>& str2)
+{
+ CMSimpleStringT<BaseType> s;
+ Concatenate(s, str1, str1.GetLength(), str2, str2.GetLength());
+ return s;
+}
+
+template<typename BaseType>
+class CMSimpleStringT<BaseType> operator+(const CMSimpleStringT<BaseType>& str1, typename CMSimpleStringT<BaseType>::PCXSTR psz2)
+{
+ CMSimpleStringT<BaseType> s;
+ Concatenate(s, str1, str1.GetLength(), psz2, StringLength(psz2));
+ return s;
+}
+
+template<typename BaseType>
+CMSimpleStringT<BaseType> operator+(typename CMSimpleStringT<BaseType>::PCXSTR psz1, const CMSimpleStringT<BaseType>& str2)
+{
+ CMSimpleStringT<BaseType> s;
+ Concatenate(s, psz1, StringLength(psz1), str2, str2.GetLength());
+ return s;
+}
+
+template<typename BaseType>
+void MIR_SYSCALL CMSimpleStringT<BaseType>::CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars)
+{
+ #pragma warning (push)
+ #pragma warning(disable : 4996)
+ memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR));
+ #pragma warning (pop)
+}
+
+template<typename BaseType>
+void MIR_SYSCALL CMSimpleStringT<BaseType>::CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars)
+{
+ memcpy_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
+}
+
+template<typename BaseType>
+void MIR_SYSCALL CMSimpleStringT<BaseType>::CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars)
+{
+ #pragma warning (push)
+ #pragma warning(disable : 4996)
+ memmove(pchDest, pchSrc, nChars * sizeof(XCHAR));
+ #pragma warning (pop)
+}
+
+template<typename BaseType>
+void MIR_SYSCALL CMSimpleStringT<BaseType>::CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars)
+{
+ memmove_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
+}
+
+template<typename BaseType>
+int MIR_SYSCALL CMSimpleStringT<BaseType>::StringLength(const char* psz)
+{
+ if (psz == nullptr)
+ return(0);
+
+ return (int(strlen(psz)));
+}
+
+template<typename BaseType>
+int MIR_SYSCALL CMSimpleStringT<BaseType>::StringLength(const wchar_t* psz)
+{
+ if (psz == nullptr)
+ return 0;
+
+ return int(wcslen(psz));
+}
+
+template<typename BaseType>
+int MIR_SYSCALL CMSimpleStringT<BaseType>::StringLengthN(const char* psz, size_t sizeInXChar)
+{
+ if (psz == nullptr)
+ return 0;
+
+ return int(strnlen(psz, sizeInXChar));
+}
+
+template<typename BaseType>
+int MIR_SYSCALL CMSimpleStringT<BaseType>::StringLengthN(const wchar_t* psz, size_t sizeInXChar)
+{
+ if (psz == nullptr)
+ return 0;
+
+ return int(wcsnlen(psz, sizeInXChar));
+}
+
+template<typename BaseType>
+void MIR_SYSCALL CMSimpleStringT<BaseType>::Concatenate(CMSimpleStringT<BaseType>& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2)
+{
+ int nNewLength = nLength1 + nLength2;
+ PXSTR pszBuffer = strResult.GetBuffer(nNewLength);
+ CopyChars(pszBuffer, nLength1, psz1, nLength1);
+ CopyChars(pszBuffer + nLength1, nLength2, psz2, nLength2);
+ strResult.ReleaseBufferSetLength(nNewLength);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Attach(CMStringData* pData)
+{
+ m_pszData = static_cast<PXSTR>(pData->data());
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Fork(int nLength)
+{
+ CMStringData* pOldData = GetData();
+ int nOldLength = pOldData->nDataLength;
+ CMStringData* pNewData = mirstr_allocate(nLength, sizeof(XCHAR));
+ if (pNewData != nullptr) {
+ int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength) + 1; // Copy '\0'
+ CopyChars(PXSTR(pNewData->data()), nCharsToCopy, PCXSTR(pOldData->data()), nCharsToCopy);
+ pNewData->nDataLength = nOldLength;
+ pOldData->Release();
+ Attach(pNewData);
+ }
+}
+
+template<typename BaseType>
+typename CMSimpleStringT<BaseType>::PXSTR CMSimpleStringT<BaseType>::PrepareWrite(int nLength)
+{
+ CMStringData* pOldData = GetData();
+ int nShared = 1 - pOldData->nRefs; // nShared < 0 means true, >= 0 means false
+ int nTooShort = pOldData->nAllocLength - nLength; // nTooShort < 0 means true, >= 0 means false
+ if ((nShared | nTooShort) < 0) // If either sign bit is set (i.e. either is less than zero), we need to copy data
+ PrepareWrite2(nLength);
+
+ return m_pszData;
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::PrepareWrite2(int nLength)
+{
+ CMStringData* pOldData = GetData();
+ if (pOldData->nDataLength > nLength)
+ nLength = pOldData->nDataLength;
+
+ if (pOldData->IsShared()) {
+ Fork(nLength);
+ }
+ else if (pOldData->nAllocLength < nLength) {
+ // Grow exponentially, until we hit 1K.
+ int nNewLength = pOldData->nAllocLength;
+ if (nNewLength > 1024)
+ nNewLength += 1024;
+ else
+ nNewLength *= 2;
+
+ if (nNewLength < nLength)
+ nNewLength = nLength;
+
+ Reallocate(nNewLength);
+ }
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::Reallocate(int nLength)
+{
+ CMStringData* pOldData = GetData();
+ if (pOldData->nAllocLength >= nLength || nLength <= 0)
+ return;
+
+ CMStringData* pNewData = mirstr_realloc(pOldData, nLength, sizeof(XCHAR));
+ if (pNewData != nullptr)
+ Attach(pNewData);
+}
+
+template<typename BaseType>
+void CMSimpleStringT<BaseType>::SetLength(int nLength)
+{
+ GetData()->nDataLength = nLength;
+ m_pszData[nLength] = 0;
+}
+
+template<typename BaseType>
+CMStringData* MIR_SYSCALL CMSimpleStringT<BaseType>::CloneData(CMStringData* pData)
+{
+ CMStringData* pNewData = nullptr;
+
+ if (!pData->IsLocked()) {
+ pNewData = pData;
+ pNewData->AddRef();
+ }
+
+ return pNewData;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT() :
+ CThisSimpleString()
+{
+}
+
+// Copy constructor
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const CMStringT<BaseType, StringTraits>& strSrc) :
+ CThisSimpleString(strSrc)
+{
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const XCHAR* pszSrc) :
+ CThisSimpleString()
+{
+ *this = pszSrc;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(CMStringDataFormat, const XCHAR* pszFormat, ...) :
+ CThisSimpleString()
+{
+ va_list args;
+ va_start(args, pszFormat);
+ FormatV(pszFormat, args);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const YCHAR* pszSrc) :
+ CThisSimpleString()
+{
+ *this = pszSrc;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const unsigned char* pszSrc) :
+ CThisSimpleString()
+{
+ *this = reinterpret_cast<const char*>(pszSrc);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(char ch, int nLength) :
+ CThisSimpleString()
+{
+ if (nLength > 0) {
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::FloodCharacters(XCHAR(ch), nLength, pszBuffer);
+ this->ReleaseBufferSetLength(nLength);
+ }
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(wchar_t ch, int nLength) :
+ CThisSimpleString()
+{
+ if (nLength > 0) {
+ //Convert ch to the BaseType
+ wchar_t pszCh[2] = { ch, 0 };
+ int nBaseTypeCharLen = 1;
+
+ if (ch != L'\0')
+ nBaseTypeCharLen = StringTraits::GetBaseTypeLength(pszCh);
+
+ XCHAR *buffBaseTypeChar = new XCHAR[nBaseTypeCharLen + 1];
+ StringTraits::ConvertToBaseType(buffBaseTypeChar, nBaseTypeCharLen + 1, pszCh, 1);
+ //allocate enough characters in String and flood (replicate) with the (converted character)*nLength
+ PXSTR pszBuffer = this->GetBuffer(nLength*nBaseTypeCharLen);
+ if (nBaseTypeCharLen == 1) //Optimization for a common case - wide char translates to 1 ansi/wide char.
+ StringTraits::FloodCharacters(buffBaseTypeChar[0], nLength, pszBuffer);
+ else {
+ XCHAR* p = pszBuffer;
+ for (int i = 0; i < nLength; i++) {
+ for (int j = 0; j < nBaseTypeCharLen; ++j) {
+ *p = buffBaseTypeChar[j];
+ ++p;
+ }
+ }
+ }
+ this->ReleaseBufferSetLength(nLength*nBaseTypeCharLen);
+ delete[] buffBaseTypeChar;
+ }
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const XCHAR* pch, int nLength) :
+ CThisSimpleString(pch, nLength)
+{
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::CMStringT(const YCHAR* pch, int nLength) :
+ CThisSimpleString()
+{
+ if (nLength > 0) {
+ int nDestLength = StringTraits::GetBaseTypeLength(pch, nLength);
+ PXSTR pszBuffer = this->GetBuffer(nDestLength);
+ StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pch, nLength);
+ this->ReleaseBufferSetLength(nDestLength);
+ }
+}
+
+// Destructor
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>::~CMStringT()
+{
+}
+
+// Assignment operators
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(const CMStringT& strSrc)
+{
+ CThisSimpleString::operator=(strSrc);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(PCXSTR pszSrc)
+{
+ CThisSimpleString::operator=(pszSrc);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(PCYSTR pszSrc)
+{
+ // nDestLength is in XCHARs
+ int nDestLength = (pszSrc != nullptr) ? StringTraits::GetBaseTypeLength(pszSrc) : 0;
+ if (nDestLength > 0) {
+ PXSTR pszBuffer = this->GetBuffer(nDestLength);
+ StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pszSrc);
+ this->ReleaseBufferSetLength(nDestLength);
+ }
+ else this->Empty();
+
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(const unsigned char* pszSrc)
+{
+ return operator=(reinterpret_cast<const char*>(pszSrc));
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(char ch)
+{
+ char ach[2] = { ch, 0 };
+ return operator=(ach);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator=(wchar_t ch)
+{
+ wchar_t ach[2] = { ch, 0 };
+ return operator=(ach);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(const CMStringT& str)
+{
+ CThisSimpleString::operator+=(str);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(const CThisSimpleString& str)
+{
+ CThisSimpleString::operator+=(str);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(PCXSTR pszSrc)
+{
+ CThisSimpleString::operator+=(pszSrc);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(PCYSTR pszSrc)
+{
+ CMStringT str(pszSrc);
+ return operator+=(str);
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(char ch)
+{
+ CThisSimpleString::operator+=(ch);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(unsigned char ch)
+{
+ CThisSimpleString::operator+=(ch);
+ return *this;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::operator+=(wchar_t ch)
+{
+ CThisSimpleString::operator+=(ch);
+ return *this;
+}
+
+// Comparison
+
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Compare(PCXSTR psz) const
+{
+ return StringTraits::StringCompare(this->GetString(), psz);
+}
+
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::CompareNoCase(PCXSTR psz) const
+{
+ return StringTraits::StringCompareIgnore(this->GetString(), psz);
+}
+
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Collate(PCXSTR psz) const
+{
+ return StringTraits::StringCollate(this->GetString(), psz);
+}
+
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::CollateNoCase(PCXSTR psz) const
+{
+ return StringTraits::StringCollateIgnore(this->GetString(), psz);
+}
+
+// Advanced manipulation
+
+// Delete 'nCount' characters, starting at index 'iIndex'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Delete(int iIndex, int nCount)
+{
+ if (iIndex < 0)
+ iIndex = 0;
+
+ if (nCount < 0)
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if (nCount + iIndex > nLength)
+ nCount = nLength - iIndex;
+
+ if (nCount > 0) {
+ int nNewLength = nLength - nCount;
+ int nXCHARsToCopy = nLength - (iIndex + nCount) + 1;
+ PXSTR pszBuffer = this->GetBuffer();
+#if _MSC_VER >= 1400
+ memmove_s(pszBuffer + iIndex, nXCHARsToCopy*sizeof(XCHAR), pszBuffer + iIndex + nCount, nXCHARsToCopy*sizeof(XCHAR));
+#else
+ memmove(pszBuffer+iIndex, pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof(XCHAR));
+#endif
+ this->ReleaseBufferSetLength(nNewLength);
+ }
+
+ return this->GetLength();
+}
+
+// Insert character 'ch' before index 'iIndex'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Insert(int iIndex, XCHAR ch)
+{
+ if (iIndex < 0)
+ iIndex = 0;
+
+ if (iIndex > this->GetLength())
+ iIndex = this->GetLength();
+
+ int nNewLength = this->GetLength() + 1;
+
+ PXSTR pszBuffer = this->GetBuffer(nNewLength);
+
+ // move existing bytes down
+#if _MSC_VER >= 1400
+ memmove_s(pszBuffer + iIndex + 1, (nNewLength - iIndex)*sizeof(XCHAR), pszBuffer + iIndex, (nNewLength - iIndex)*sizeof(XCHAR));
+#else
+ memmove(pszBuffer+iIndex+1, pszBuffer+iIndex, (nNewLength-iIndex)*sizeof(XCHAR));
+#endif
+ pszBuffer[iIndex] = ch;
+
+ this->ReleaseBufferSetLength(nNewLength);
+ return nNewLength;
+}
+
+// Insert string 'psz' before index 'iIndex'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Insert(int iIndex, PCXSTR psz)
+{
+ if (iIndex < 0)
+ iIndex = 0;
+
+ if (iIndex > this->GetLength())
+ iIndex = this->GetLength();
+
+ // nInsertLength and nNewLength are in XCHARs
+ int nInsertLength = StringTraits::SafeStringLen(psz);
+ int nNewLength = this->GetLength();
+ if (nInsertLength > 0) {
+ nNewLength += nInsertLength;
+
+ PXSTR pszBuffer = this->GetBuffer(nNewLength);
+ // move existing bytes down
+#if _MSC_VER >= 1400
+ memmove_s(pszBuffer + iIndex + nInsertLength, (nNewLength - iIndex - nInsertLength + 1)*sizeof(XCHAR), pszBuffer + iIndex, (nNewLength - iIndex - nInsertLength + 1)*sizeof(XCHAR));
+ memcpy_s(pszBuffer + iIndex, nInsertLength*sizeof(XCHAR), psz, nInsertLength*sizeof(XCHAR));
+#else
+ memmove(pszBuffer+iIndex+nInsertLength, pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR));
+ memcpy(pszBuffer+iIndex, psz, nInsertLength*sizeof(XCHAR));
+#endif
+ this->ReleaseBufferSetLength(nNewLength);
+ }
+
+ return nNewLength;
+}
+
+// Replace all occurrences of character 'chOld' with character 'chNew'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Replace(XCHAR chOld, XCHAR chNew)
+{
+ int nCount = 0;
+
+ // short-circuit the nop case
+ if (chOld != chNew) {
+ // otherwise modify each character that matches in the string
+ bool bCopied = false;
+ PXSTR pszBuffer = const_cast<PXSTR>(this->GetString()); // We don't actually write to pszBuffer until we've called GetBuffer().
+
+ int nLength = this->GetLength();
+ int iChar = 0;
+ while (iChar < nLength) {
+ // replace instances of the specified character only
+ if (pszBuffer[iChar] == chOld) {
+ if (!bCopied) {
+ bCopied = true;
+ pszBuffer = this->GetBuffer(nLength);
+ }
+ pszBuffer[iChar] = chNew;
+ nCount++;
+ }
+ iChar = int(StringTraits::CharNext(pszBuffer + iChar) - pszBuffer);
+ }
+
+ if (bCopied)
+ this->ReleaseBufferSetLength(nLength);
+ }
+
+ return nCount;
+}
+
+// Replace all occurrences of string 'pszOld' with string 'pszNew'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Replace(PCXSTR pszOld, PCXSTR pszNew)
+{
+ // can't have empty or NULL lpszOld
+
+ // nSourceLen is in XCHARs
+ int nSourceLen = StringTraits::SafeStringLen(pszOld);
+ if (nSourceLen == 0)
+ return 0;
+ // nReplacementLen is in XCHARs
+ int nReplacementLen = StringTraits::SafeStringLen(pszNew);
+
+ // loop once to figure out the size of the result string
+ int nCount = 0;
+ {
+ PCXSTR pszStart = this->GetString();
+ PCXSTR pszEnd = pszStart + this->GetLength();
+ while (pszStart < pszEnd) {
+ PCXSTR pszTarget;
+ while ((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != nullptr) {
+ nCount++;
+ pszStart = pszTarget + nSourceLen;
+ }
+ pszStart += StringTraits::SafeStringLen(pszStart) + 1;
+ }
+ }
+
+ // if any changes were made, make them
+ if (nCount > 0) {
+ // if the buffer is too small, just
+ // allocate a new buffer (slow but sure)
+ int nOldLength = this->GetLength();
+ int nNewLength = nOldLength + (nReplacementLen - nSourceLen)*nCount;
+
+ PXSTR pszBuffer = this->GetBuffer(__max(nNewLength, nOldLength));
+
+ PXSTR pszStart = pszBuffer;
+ PXSTR pszEnd = pszStart + nOldLength;
+
+ // loop again to actually do the work
+ while (pszStart < pszEnd) {
+ PXSTR pszTarget;
+ while ((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != nullptr) {
+ int nBalance = nOldLength - int(pszTarget - pszBuffer + nSourceLen);
+ memmove_s(pszTarget + nReplacementLen, nBalance*sizeof(XCHAR),
+ pszTarget + nSourceLen, nBalance*sizeof(XCHAR));
+ memcpy_s(pszTarget, nReplacementLen*sizeof(XCHAR),
+ pszNew, nReplacementLen*sizeof(XCHAR));
+ pszStart = pszTarget + nReplacementLen;
+ pszTarget[nReplacementLen + nBalance] = 0;
+ nOldLength += (nReplacementLen - nSourceLen);
+ }
+ pszStart += StringTraits::SafeStringLen(pszStart) + 1;
+ }
+ this->ReleaseBufferSetLength(nNewLength);
+ }
+
+ return nCount;
+}
+
+// Remove all occurrences of character 'chRemove'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Remove(XCHAR chRemove)
+{
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+
+ PXSTR pszSource = pszBuffer;
+ PXSTR pszDest = pszBuffer;
+ PXSTR pszEnd = pszBuffer + nLength;
+
+ while (pszSource < pszEnd) {
+ PXSTR pszNewSource = StringTraits::CharNext(pszSource);
+ if (*pszSource != chRemove) {
+ // Copy the source to the destination. Remember to copy all bytes of an MBCS character
+ size_t NewSourceGap = (pszNewSource - pszSource);
+ PXSTR pszNewDest = pszDest + NewSourceGap;
+ for (size_t i = 0; pszDest != pszNewDest && i < NewSourceGap; i++) {
+ *pszDest = *pszSource;
+ pszSource++;
+ pszDest++;
+ }
+ }
+ pszSource = pszNewSource;
+ }
+ *pszDest = 0;
+ int nCount = int(pszSource - pszDest);
+ this->ReleaseBufferSetLength(nLength - nCount);
+
+ return nCount;
+}
+
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Tokenize(PCXSTR pszTokens, int& iStart) const
+{
+ if ((pszTokens == nullptr) || (*pszTokens == (XCHAR)0)) {
+ if (iStart < this->GetLength())
+ return CMStringT(this->GetString() + iStart);
+ }
+ else {
+ PCXSTR pszPlace = this->GetString() + iStart;
+ PCXSTR pszEnd = this->GetString() + this->GetLength();
+ if (pszPlace < pszEnd) {
+ int nIncluding = StringTraits::StringSpanIncluding(pszPlace, pszTokens);
+
+ if ((pszPlace + nIncluding) < pszEnd) {
+ pszPlace += nIncluding;
+ int nExcluding = StringTraits::StringSpanExcluding(pszPlace, pszTokens);
+
+ int iFrom = iStart + nIncluding;
+ int nUntil = nExcluding;
+ iStart = iFrom + nUntil + 1;
+
+ return Mid(iFrom, nUntil);
+ }
+ }
+ }
+
+ // return empty string, done tokenizing
+ iStart = -1;
+
+ return CMStringT();
+}
+
+// find routines
+
+// Find the first occurrence of character 'ch', starting at index 'iStart'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Find(XCHAR ch, int iStart) const
+{
+ // nLength is in XCHARs
+ int nLength = this->GetLength();
+ if (iStart < 0 || iStart >= nLength)
+ return -1;
+
+ // find first single character
+ PCXSTR psz = StringTraits::StringFindChar(this->GetString() + iStart, ch);
+
+ // return -1 if not found and index otherwise
+ return (psz == nullptr) ? -1 : int(psz - this->GetString());
+}
+
+// look for a specific sub-string
+
+// Find the first occurrence of string 'pszSub', starting at index 'iStart'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::Find(PCXSTR pszSub, int iStart) const
+{
+ // iStart is in XCHARs
+ if (pszSub == nullptr)
+ return -1;
+
+ // nLength is in XCHARs
+ int nLength = this->GetLength();
+ if (iStart < 0 || iStart > nLength)
+ return -1;
+
+ // find first matching substring
+ PCXSTR psz = StringTraits::StringFindString(this->GetString() + iStart, pszSub);
+
+ // return -1 for not found, distance from beginning otherwise
+ return (psz == nullptr) ? -1 : int(psz - this->GetString());
+}
+
+// Find the first occurrence of any of the characters in string 'pszCharSet'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::FindOneOf(PCXSTR pszCharSet) const
+{
+ PCXSTR psz = StringTraits::StringScanSet(this->GetString(), pszCharSet);
+ return (psz == nullptr) ? -1 : int(psz - this->GetString());
+}
+
+// Find the last occurrence of character 'ch'
+template< typename BaseType, class StringTraits >
+int CMStringT<BaseType, StringTraits>::ReverseFind(XCHAR ch) const
+{
+ // find last single character
+ PCXSTR psz = StringTraits::StringFindCharRev(this->GetString(), ch);
+
+ // return -1 if not found, distance from beginning otherwise
+ return (psz == nullptr) ? -1 : int(psz - this->GetString());
+}
+
+// manipulation
+
+// Convert the string to uppercase
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::MakeUpper()
+{
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::StringUppercase(pszBuffer, nLength + 1);
+ this->ReleaseBufferSetLength(nLength);
+
+ return *this;
+}
+
+// Convert the string to lowercase
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::MakeLower()
+{
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::StringLowercase(pszBuffer, nLength + 1);
+ this->ReleaseBufferSetLength(nLength);
+
+ return *this;
+}
+
+// Reverse the string
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::MakeReverse()
+{
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::StringReverse(pszBuffer);
+ this->ReleaseBufferSetLength(nLength);
+
+ return *this;
+}
+
+// trimming
+
+// Remove all trailing whitespace
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimRight()
+{
+ // find beginning of trailing spaces by starting
+ // at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = nullptr;
+
+ while (*psz != 0) {
+ if (StringTraits::IsSpace(*psz)) {
+ if (pszLast == nullptr)
+ pszLast = psz;
+ }
+ else pszLast = nullptr;
+
+ psz = StringTraits::CharNext(psz);
+ }
+
+ if (pszLast != nullptr) {
+ // truncate at trailing space start
+ int iLast = int(pszLast - this->GetString());
+
+ this->Truncate(iLast);
+ }
+
+ return *this;
+}
+
+// Remove all leading whitespace
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimLeft()
+{
+ // find first non-space character
+
+ PCXSTR psz = this->GetString();
+ while (StringTraits::IsSpace(*psz))
+ psz = StringTraits::CharNext(psz);
+
+ if (psz != this->GetString()) {
+ // fix up data and length
+ int iFirst = int(psz - this->GetString());
+ PXSTR pszBuffer = this->GetBuffer(this->GetLength());
+ psz = pszBuffer + iFirst;
+ int nDataLength = this->GetLength() - iFirst;
+ memmove_s(pszBuffer, (this->GetLength() + 1)*sizeof(XCHAR),
+ psz, (nDataLength + 1)*sizeof(XCHAR));
+ this->ReleaseBufferSetLength(nDataLength);
+ }
+
+ return *this;
+}
+
+// Remove all leading and trailing whitespace
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim()
+{
+ return TrimRight().TrimLeft();
+}
+
+// Remove all leading and trailing occurrences of character 'chTarget'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim(XCHAR chTarget)
+{
+ return TrimRight(chTarget).TrimLeft(chTarget);
+}
+
+// Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::Trim(PCXSTR pszTargets)
+{
+ return TrimRight(pszTargets).TrimLeft(pszTargets);
+}
+
+// trimming anything (either side)
+
+// Remove all trailing occurrences of character 'chTarget'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimRight(XCHAR chTarget)
+{
+ // find beginning of trailing matches
+ // by starting at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = nullptr;
+
+ while (*psz != 0) {
+ if (*psz == chTarget) {
+ if (pszLast == nullptr)
+ pszLast = psz;
+ }
+ else pszLast = nullptr;
+
+ psz = StringTraits::CharNext(psz);
+ }
+
+ if (pszLast != nullptr) {
+ // truncate at left-most matching character
+ int iLast = int(pszLast - this->GetString());
+ this->Truncate(iLast);
+ }
+
+ return *this;
+}
+
+// Remove all trailing occurrences of any of the characters in string 'pszTargets'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimRight(PCXSTR pszTargets)
+{
+ // if we're not trimming anything, we're not doing any work
+ if ((pszTargets == nullptr) || (*pszTargets == 0)) {
+ return *this;
+ }
+
+ // find beginning of trailing matches
+ // by starting at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = nullptr;
+
+ while (*psz != 0) {
+ if (StringTraits::StringFindChar(pszTargets, *psz) != nullptr) {
+ if (pszLast == nullptr) {
+ pszLast = psz;
+ }
+ }
+ else {
+ pszLast = nullptr;
+ }
+ psz = StringTraits::CharNext(psz);
+ }
+
+ if (pszLast != nullptr) {
+ // truncate at left-most matching character
+ int iLast = int(pszLast - this->GetString());
+ this->Truncate(iLast);
+ }
+
+ return *this;
+}
+
+// Remove all leading occurrences of character 'chTarget'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimLeft(XCHAR chTarget)
+{
+ // find first non-matching character
+ PCXSTR psz = this->GetString();
+
+ while (chTarget == *psz) {
+ psz = StringTraits::CharNext(psz);
+ }
+
+ if (psz != this->GetString()) {
+ // fix up data and length
+ int iFirst = int(psz - this->GetString());
+ PXSTR pszBuffer = this->GetBuffer(this->GetLength());
+ psz = pszBuffer + iFirst;
+ int nDataLength = this->GetLength() - iFirst;
+ memmove_s(pszBuffer, (this->GetLength() + 1)*sizeof(XCHAR),
+ psz, (nDataLength + 1)*sizeof(XCHAR));
+ this->ReleaseBufferSetLength(nDataLength);
+ }
+
+ return *this;
+}
+
+// Remove all leading occurrences of any of the characters in string 'pszTargets'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits>& CMStringT<BaseType, StringTraits>::TrimLeft(PCXSTR pszTargets)
+{
+ // if we're not trimming anything, we're not doing any work
+ if ((pszTargets == nullptr) || (*pszTargets == 0)) {
+ return *this;
+ }
+
+ PCXSTR psz = this->GetString();
+ while ((*psz != 0) && (StringTraits::StringFindChar(pszTargets, *psz) != nullptr)) {
+ psz = StringTraits::CharNext(psz);
+ }
+
+ if (psz != this->GetString()) {
+ // fix up data and length
+ int iFirst = int(psz - this->GetString());
+ PXSTR pszBuffer = this->GetBuffer(this->GetLength());
+ psz = pszBuffer + iFirst;
+ int nDataLength = this->GetLength() - iFirst;
+ memmove_s(pszBuffer, (this->GetLength() + 1)*sizeof(XCHAR),
+ psz, (nDataLength + 1)*sizeof(XCHAR));
+ this->ReleaseBufferSetLength(nDataLength);
+ }
+
+ return *this;
+}
+
+// Convert the string to the OEM character set
+template< typename BaseType, class StringTraits >
+void CMStringT<BaseType, StringTraits>::AnsiToOem()
+{
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::ConvertToOem(pszBuffer, nLength + 1);
+ this->ReleaseBufferSetLength(nLength);
+}
+
+// Convert the string to the ANSI character set
+template< typename BaseType, class StringTraits >
+void CMStringT<BaseType, StringTraits>::OemToAnsi()
+{
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::ConvertToAnsi(pszBuffer, nLength + 1);
+ this->ReleaseBufferSetLength(nLength);
+}
+
+// Very simple sub-string extraction
+
+// Return the substring starting at index 'iFirst'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Mid(int iFirst) const
+{
+ return Mid(iFirst, this->GetLength() - iFirst);
+}
+
+// Return the substring starting at index 'iFirst', with length 'nCount'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Mid(int iFirst, int nCount) const
+{
+ // nCount is in XCHARs
+
+ // out-of-bounds requests return sensible things
+ if (iFirst < 0)
+ iFirst = 0;
+ if (nCount < 0)
+ nCount = 0;
+
+ if ((iFirst + nCount) > this->GetLength())
+ nCount = this->GetLength() - iFirst;
+
+ if (iFirst > this->GetLength())
+ nCount = 0;
+
+ // optimize case of returning entire string
+ if ((iFirst == 0) && ((iFirst + nCount) == this->GetLength()))
+ return *this;
+
+ return CMStringT(this->GetString() + iFirst, nCount);
+}
+
+// Return the substring consisting of the rightmost 'nCount' characters
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Right(int nCount) const
+{
+ // nCount is in XCHARs
+ if (nCount < 0)
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if (nCount >= nLength)
+ return *this;
+
+ return CMStringT(this->GetString() + nLength - nCount, nCount);
+}
+
+// Return the substring consisting of the leftmost 'nCount' characters
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::Left(int nCount) const
+{
+ // nCount is in XCHARs
+ if (nCount < 0)
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if (nCount >= nLength)
+ return *this;
+
+ return CMStringT(this->GetString(), nCount);
+}
+
+// Return the substring consisting of the leftmost characters in the set 'pszCharSet'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::SpanIncluding(PCXSTR pszCharSet) const
+{
+ return Left(StringTraits::StringSpanIncluding(this->GetString(), pszCharSet));
+}
+
+// Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
+template< typename BaseType, class StringTraits >
+CMStringT<BaseType, StringTraits> CMStringT<BaseType, StringTraits>::SpanExcluding(PCXSTR pszCharSet) const
+{
+ return Left(StringTraits::StringSpanExcluding(this->GetString(), pszCharSet));
+}
+
+// Format data using format string 'pszFormat'
+template< typename BaseType, class StringTraits >
+typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::Format(PCXSTR pszFormat, ...)
+{
+ va_list argList;
+ va_start(argList, pszFormat);
+ FormatV(pszFormat, argList);
+ va_end(argList);
+ return GetString();
+}
+
+// Append formatted data using format string 'pszFormat'
+template< typename BaseType, class StringTraits >
+typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::AppendFormat(PCXSTR pszFormat, ...)
+{
+ va_list argList;
+ va_start(argList, pszFormat);
+ AppendFormatV(pszFormat, argList);
+ va_end(argList);
+ return GetString();
+}
+
+template< typename BaseType, class StringTraits >
+void CMStringT<BaseType, StringTraits>::AppendFormatV(PCXSTR pszFormat, va_list args)
+{
+ int nCurrentLength = this->GetLength();
+ int nAppendLength = StringTraits::GetFormattedLength(pszFormat, args);
+ PXSTR pszBuffer = this->GetBuffer(nCurrentLength + nAppendLength);
+ StringTraits::Format(pszBuffer + nCurrentLength, nAppendLength + 1, pszFormat, args);
+ this->ReleaseBufferSetLength(nCurrentLength + nAppendLength);
+}
+
+template< typename BaseType, class StringTraits >
+typename CMStringT<BaseType, StringTraits>::PCXSTR CMStringT<BaseType, StringTraits>::FormatV(PCXSTR pszFormat, va_list args)
+{
+ int nLength = StringTraits::GetFormattedLength(pszFormat, args);
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::Format(pszBuffer, nLength + 1, pszFormat, args);
+ this->ReleaseBufferSetLength(nLength);
+ return GetString();
+}
+
+// Set the string to the value of environment variable 'pszVar'
+template< typename BaseType, class StringTraits >
+BOOL CMStringT<BaseType, StringTraits>::GetEnvironmentVariable(PCXSTR pszVar)
+{
+ int nLength = StringTraits::GetEnvironmentVariable(pszVar, nullptr, 0);
+ BOOL bRetVal = FALSE;
+
+ if (nLength == 0)
+ this->Empty();
+ else {
+ PXSTR pszBuffer = this->GetBuffer(nLength);
+ StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength);
+ this->ReleaseBuffer();
+ bRetVal = TRUE;
+ }
+
+ return bRetVal;
+}
+
+// Set the string to the value of environment variable 'pszVar'
+template< typename BaseType, class StringTraits >
+typename CMStringT<BaseType, StringTraits>::PXSTR CMStringT<BaseType, StringTraits>::Detach() const
+{
+ return StringTraits::MirCopy(CMStringT<BaseType, StringTraits>::GetString(), GetLength());
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, const CMStringT<BaseType, StringTraits>& str2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), str2, str2.GetLength());
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, typename CMStringT<BaseType, StringTraits>::PCXSTR psz2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), psz2, CMStringT<BaseType, StringTraits>::StringLength(psz2));
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(typename CMStringT<BaseType, StringTraits>::PCXSTR psz1, const CMStringT<BaseType, StringTraits>& str2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, psz1, CMStringT<BaseType, StringTraits>::StringLength(psz1), str2, str2.GetLength());
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, wchar_t ch2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch2);
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(const CMStringT<BaseType, StringTraits>& str1, char ch2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch2);
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(wchar_t ch1, const CMStringT<BaseType, StringTraits>& str2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch1);
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
+ return strResult;
+}
+
+template< typename BaseType, class StringTraits >
+MIR_CORE_EXPORT CMStringT<BaseType, StringTraits> CALLBACK operator+(char ch1, const CMStringT<BaseType, StringTraits>& str2)
+{
+ CMStringT<BaseType, StringTraits> strResult;
+ typename CMStringT<BaseType, StringTraits>::XCHAR chTemp = typename CMStringT<BaseType, StringTraits>::XCHAR(ch1);
+ CMStringT<BaseType, StringTraits>::Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
+ return strResult;
+}
+
+#endif // M_STRING_INL__
diff --git a/include/m_system.h b/include/m_system.h
index 5226961d0f..9994da7c67 100644
--- a/include/m_system.h
+++ b/include/m_system.h
@@ -1,652 +1,654 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-Copyright (c) 2000-08 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.
-*/
-
-#pragma once
-
-#ifndef M_SYSTEM_H__
-#define M_SYSTEM_H__ 1
-
-#ifndef MIRANDANAME
- #define MIRANDANAME "Miranda NG"
-#endif
-#ifndef MIRANDACLASS
- #define MIRANDACLASS "Miranda"
-#endif
-
-// set the default compatibility lever for Miranda 0.4.x
-#ifndef MIRANDA_VER
- #define MIRANDA_VER 0x0A00
-#endif
-
-#ifndef _MSC_VER
- #define __forceinline inline __attribute__ ((always_inline))
-#else
- #pragma warning(disable:4244 4245)
-#endif
-
-#define NEWSTR_ALLOCA(A) (A == NULL)?NULL:strcpy((char*)alloca(strlen(A)+1), A)
-#define NEWWSTR_ALLOCA(A) ((A==NULL)?NULL:wcscpy((wchar_t*)alloca(sizeof(wchar_t)*(wcslen(A)+1)),A))
-
-#include <m_core.h>
-
-// miranda/system/modulesloaded
-// called after all modules have been successfully initialised
-// wParam = lParam = 0
-// used to resolve double-dependencies in the module load order
-#define ME_SYSTEM_MODULESLOADED "Miranda/System/ModulesLoaded"
-
-// miranda/system/shutdown event
-// called just before the application terminates
-// the database is still guaranteed to be running during this hook.
-// wParam = lParam = 0
-#define ME_SYSTEM_SHUTDOWN "Miranda/System/Shutdown"
-
-// restarts miranda (0.8+)
-// wParam = 0 or 1. 1 - restart with current profile, 0 - restart in default profile or profile manager
-// lParam = (wchar_t*)path to a new miranda32.exe binary or NULL to use current
-#define MS_SYSTEM_RESTART "Miranda/System/Restart"
-
-// miranda/system/oktoexit event
-// called before the app goes into shutdown routine to make sure everyone is
-// happy to exit
-// wParam = lParam = 0
-// return nonzero to stop the exit cycle
-#define ME_SYSTEM_OKTOEXIT "Miranda/System/OkToExitEvent"
-
-// gets the version number of Miranda encoded as a DWORD
-// returns the version number, encoded as one version per byte, therefore
-// version 1.2.3.10 is 0x0102030a
-EXTERN_C MIR_APP_DLL(DWORD) Miranda_GetVersion(void);
-
-// gets the version number of Miranda encoded as four WORDs v0.92.2+
-// returns the version number, encoded as one version per word, therefore
-// version 1.2.3.3210 is 0x0001, 0x0002, 0x0003, 0x0C8a
-typedef WORD MFileVersion[4];
-EXTERN_C MIR_APP_DLL(void) Miranda_GetFileVersion(MFileVersion*);
-
-// gets the version of Miranda encoded as text
-// cch is the size of the buffer pointed to by pszVersion, in bytes
-// may return a build qualifier, such as "0.1.0.1 alpha"
-// returns 0 on success, nonzero on failure
-EXTERN_C MIR_APP_DLL(void) Miranda_GetVersionText(char *pDest, size_t cbSize);
-
-// returns a system window that can handle global timers
-// a usual practice is to use a unique pointer as a timer id
-EXTERN_C MIR_APP_DLL(class CDlgBase *) Miranda_GetSystemWindow();
-
-// Adds an event to the list to be checked in the main message loop
-// when a handle gets triggered, an appopriate stub gets called
-typedef void (CALLBACK *MWaitableStub)(void);
-typedef void (CALLBACK *MWaitableStubEx)(void*);
-
-EXTERN_C MIR_APP_DLL(void) Miranda_WaitOnHandle(MWaitableStub pFunc, HANDLE hEvent = nullptr);
-EXTERN_C MIR_APP_DLL(void) Miranda_WaitOnHandleEx(MWaitableStubEx pFunc, void *pInfo);
-
-// wParam = 0 (ignored)
-// lParam = 0 (ignored)
-//
-// This hook is fired just before the thread unwind stack is used,
-// it allows MT plugins to shutdown threads if they have any special
-// processing to do, etc.
-#define ME_SYSTEM_PRESHUTDOWN "Miranda/System/PShutdown"
-
-// Returns true when Miranda has got WM_QUIT and is in the process of shutting down
-EXTERN_C MIR_APP_DLL(bool) Miranda_IsTerminated(void);
-
-// Check if everyone is happy to exit
-// if everyone acknowleges OK to exit then returns true, otherwise false
-EXTERN_C MIR_APP_DLL(bool) Miranda_OkToExit(void);
-
-// Used by contact lists inside CloseAction
-// Waits for a permission to exit and destroys contact list
-EXTERN_C MIR_APP_DLL(void) Miranda_Close(void);
-
-// Sets up a function pointer to be called after main loop iterations, suitable for idle processing
-EXTERN_C MIR_APP_DLL(void) Miranda_SetIdleCallback(void(__cdecl *pfnCallback)(void));
-
-// returns the last window tick where a monitored event was seen, currently WM_CHAR/WM_MOUSEMOVE
-EXTERN_C MIR_APP_DLL(DWORD) Miranda_GetIdle(void);
-
-///////////////////////////////////////////////////////////////////////////////
-
-#if defined(__cplusplus)
-
-#ifndef M_STRING_H__
- #include <m_string.h>
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// general lists' templates
-
-struct MIR_CORE_EXPORT MNonCopyable
-{
- __inline MNonCopyable() {}
-
- MNonCopyable(const MNonCopyable &) = delete;
- MNonCopyable &operator=(const MNonCopyable &) = delete;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// mir_ptr - automatic pointer for buffers, allocated using mir_alloc/mir_calloc
-
-template<class T> class mir_ptr
-{
-protected:
- T *data;
-
-public:
- __inline explicit mir_ptr() : data(nullptr) {}
- __inline explicit mir_ptr(T *_p) : data(_p) {}
- __inline ~mir_ptr() { mir_free(data); }
- __inline T *get() const { return data; }
- __inline T *operator=(T *_p) { if (data) mir_free(data); data = _p; return data; }
- __inline T *operator->() const { return data; }
- __inline operator T *() const { return data; }
- __inline operator INT_PTR() const { return (INT_PTR)data; }
- __inline T *detach() { T *res = data; data = nullptr; return res; }
-};
-
-typedef mir_ptr<char> ptrA;
-typedef mir_ptr<wchar_t> ptrW;
-
-///////////////////////////////////////////////////////////////////////////////
-// mir_cs - simple wrapper for the critical sections
-
-class MIR_CORE_EXPORT mir_cs : public MNonCopyable
-{
- CRITICAL_SECTION m_cs;
-
-public:
- mir_cs();
- ~mir_cs();
-
- void Lock();
- void Unlock();
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// mir_cslock - simple locker for the critical sections
-
-class mir_cslock : public MNonCopyable
-{
- mir_cs &cs;
-
-public:
- __inline mir_cslock(mir_cs &_cs) : cs(_cs) { cs.Lock(); }
- __inline ~mir_cslock() { cs.Unlock(); }
-};
-
-class mir_cslockfull : public MNonCopyable
-{
- mir_cs &cs;
- bool bIsLocked = false;
-
-public:
- __inline void lock() { bIsLocked = true; cs.Lock(); }
- __inline void unlock() { bIsLocked = false; cs.Unlock(); }
-
- __inline mir_cslockfull(mir_cs &_cs) : cs(_cs) { lock(); }
- __inline ~mir_cslockfull() { if (bIsLocked) unlock(); }
-};
-
-//////////////////////////////////////////////////////////////////////////////
-//pass_ptrA, pass_ptrW and pass_ptrT - automatic pointer for passwords
-
-class pass_ptrA : public mir_ptr<char>
-{
-public:
- __inline explicit pass_ptrA() : mir_ptr() {}
- __inline explicit pass_ptrA(char *_p) : mir_ptr(_p) {}
- __inline ~pass_ptrA() { zero(); }
- __inline char *operator=(char *_p) { zero(); return mir_ptr::operator=(_p); }
- __inline void zero()
- {
- if (data) SecureZeroMemory(data, mir_strlen(data));
- }
-};
-
-class pass_ptrW : public mir_ptr<wchar_t>
-{
-public:
- __inline explicit pass_ptrW() : mir_ptr() {}
- __inline explicit pass_ptrW(wchar_t *_p) : mir_ptr(_p) {}
- __inline ~pass_ptrW() { zero(); }
- __inline wchar_t *operator=(wchar_t *_p) { zero(); return mir_ptr::operator=(_p); }
- __inline void zero()
- {
- if (data) SecureZeroMemory(data, mir_wstrlen(data) * sizeof(wchar_t));
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// basic class for classes that should be cleared inside new()
-
-class MZeroedObject
-{
-public:
- __inline void *operator new(size_t size)
- {
- return calloc(1, size);
- }
-
- __inline void operator delete(void *p)
- {
- free(p);
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// general lists' templates
-
-#define NumericKeySortT -1
-#define HandleKeySortT -2
-#define PtrKeySortT -3
-
-template<class T> struct LIST
-{
- typedef int (*FTSortFunc)(const T *p1, const T *p2);
-
- __inline LIST(int aincr, FTSortFunc afunc = nullptr)
- {
- memset(this, 0, sizeof(*this));
- increment = aincr;
- sortFunc = afunc;
- }
-
- __inline LIST(int aincr, INT_PTR id)
- {
- memset(this, 0, sizeof(*this));
- increment = aincr;
- sortFunc = FTSortFunc(id);
- }
-
- __inline LIST(const LIST &x)
- {
- items = nullptr;
- List_Copy((SortedList *)&x, (SortedList *)this, sizeof(T));
- }
-
- __inline LIST &operator = (const LIST &x)
- {
- destroy();
- List_Copy((SortedList *)&x, (SortedList *)this, sizeof(T));
- return *this;
- }
-
- __inline ~LIST()
- {
- destroy();
- }
-
- __inline T *operator[](int idx) const { return (idx >= 0 && idx < count) ? items[idx] : nullptr; }
- __inline int getCount(void) const { return count; }
- __inline T **getArray(void) const { return items; }
-
- __inline int getIndex(T *p) const
- {
- int idx;
- return (!List_GetIndex((SortedList *)this, p, &idx)) ? -1 : idx;
- }
-
- class reverse_iterator
- {
- int index;
- T **base;
-
- public:
- reverse_iterator(const LIST &_lst) :
- index(_lst.getCount() - 1),
- base(_lst.getArray())
- {
- }
-
- class iterator
- {
- T **ptr;
-
- public:
- iterator(T **_p) : ptr(_p) {}
- iterator operator++() { --ptr; return *this; }
- bool operator!=(const iterator &p) { return ptr != p.ptr; }
- operator T **() const { return ptr; }
- };
-
- __inline iterator begin() const { return iterator(base + index); }
- __inline iterator end() const { return iterator(base - 1); }
- __inline int indexOf(T **p) const { return int(p - base); }
- };
-
- __inline void destroy(void) { List_Destroy((SortedList *)this); }
- __inline T* find(T *p) const { return (T *)List_Find((SortedList *)this, p); }
- __inline int indexOf(T *p) const { return List_IndexOf((SortedList *)this, p); }
- __inline int insert(T *p, int idx) { return List_Insert((SortedList *)this, p, idx); }
- __inline int remove(int idx) { return List_Remove((SortedList *)this, idx); }
-
- __inline int insert(T *p) { return List_InsertPtr((SortedList *)this, p); }
- __inline int remove(T *p) { return List_RemovePtr((SortedList *)this, p); }
-
- __inline int indexOf(T **p) const { return int(p - items); }
-
- __inline T* removeItem(T **p)
- {
- T *savePtr = *p;
- List_Remove((SortedList *)this, int(p - items));
- return savePtr;
- }
-
- __inline void put(int idx, T *p) { items[idx] = p; }
-
- __inline T **begin() const { return items; }
- __inline T **end() const { return items + count; }
-
- __inline reverse_iterator rev_iter() const { return reverse_iterator(*this); }
-
-protected:
- T **items;
- int count, limit, increment;
- FTSortFunc sortFunc;
-};
-
-template<class T> struct OBJLIST : public LIST<T>
-{
- typedef int (*FTSortFunc)(const T *p1, const T *p2);
-
- __inline OBJLIST(int aincr, FTSortFunc afunc = nullptr) :
- LIST<T>(aincr, afunc)
- {
- }
-
- __inline OBJLIST(int aincr, INT_PTR id) :
- LIST<T>(aincr, (FTSortFunc)id)
- {
- }
-
- __inline OBJLIST(const OBJLIST &x) :
- LIST<T>(x.increment, x.sortFunc)
- {
- this->items = nullptr;
- List_ObjCopy((SortedList *)&x, (SortedList *)this, sizeof(T));
- }
-
- __inline OBJLIST &operator = (const OBJLIST &x)
- {
- destroy();
- List_ObjCopy((SortedList *)&x, (SortedList *)this, sizeof(T));
- return *this;
- }
-
- ~OBJLIST()
- {
- destroy();
- }
-
- __inline void destroy(void)
- {
- for (int i = 0; i < this->count; i++)
- delete this->items[i];
-
- List_Destroy((SortedList *)this);
- }
-
- __inline int remove(int idx)
- {
- delete this->items[idx];
- return List_Remove((SortedList *)this, idx);
- }
-
- __inline int remove(T *p)
- {
- int i = this->getIndex(p);
- if (i != -1) {
- remove(i);
- return 1;
- }
- return 0;
- }
-
- __inline T &operator[](int idx) const { return *this->items[idx]; }
-};
-
-#define __A2W(s) L ## s
-#define _A2W(s) __A2W(s)
-
-class _A2T : public ptrW
-{
-public:
- __inline _A2T(const char *s) : ptrW(mir_a2u(s)) {}
- __inline _A2T(const char *s, int cp) : ptrW(mir_a2u_cp(s, cp)) {}
-};
-
-class _T2A : public ptrA
-{
-public:
- __forceinline _T2A(const wchar_t *s) : ptrA(mir_u2a(s)) {}
- __forceinline _T2A(const wchar_t *s, int cp) : ptrA(mir_u2a_cp(s, cp)) {}
-};
-
-class T2Utf : public ptrA
-{
-public:
- __forceinline T2Utf(const wchar_t *str) : ptrA(mir_utf8encodeW(str)) {}
- __forceinline operator BYTE *() const { return (BYTE *)data; }
-#ifdef _XSTRING_
- std::string str() const { return std::string(data); }
-#endif
-};
-
-class Utf2T : public ptrW
-{
-public:
- __forceinline Utf2T(const char *str) : ptrW(mir_utf8decodeW(str)) {}
- __forceinline operator wchar_t *() const { return data; }
-#ifdef _XSTRING_
- std::wstring str() const { return std::wstring(data); }
-#endif
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// basic class for classes that should be cleared inside new()
-
-class MIR_CORE_EXPORT MBinBuffer
-{
- char *m_buf;
- size_t m_len;
-
-public:
- MBinBuffer();
- ~MBinBuffer();
-
- __forceinline char *data() const { return m_buf; }
- __forceinline bool isEmpty() const { return m_len == 0; }
- __forceinline size_t length() const { return m_len; }
-
- // adds a buffer to the end
- void append(const void *pBuf, size_t bufLen);
-
- // adds a buffer to the beginning
- void appendBefore(const void *pBuf, size_t bufLen);
-
- // replaces buffer contents
- void assign(const void *pBuf, size_t bufLen);
-
- // drops a part of buffer
- void remove(size_t sz);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// thread handle controller
-
-class MThreadLock
-{
- HANDLE &m_pHandle;
-
-public:
- __forceinline MThreadLock(HANDLE &pHandle) :
- m_pHandle(pHandle)
- {
- }
-
- __forceinline ~MThreadLock()
- {
- m_pHandle = nullptr;
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// parameter classes for XML, JSON & HTTP requests
-
-struct PARAM
-{
- const char *szName;
- __forceinline PARAM(const char *_name) : szName(_name)
- {
- }
-};
-
-struct BOOL_PARAM : public PARAM
-{
- bool bValue;
- __forceinline BOOL_PARAM(const char *_name, bool _value) :
- PARAM(_name), bValue(_value)
- {
- }
-};
-
-struct INT_PARAM : public PARAM
-{
- int32_t iValue;
- __forceinline INT_PARAM(const char *_name, int32_t _value) :
- PARAM(_name), iValue(_value)
- {
- }
-};
-
-struct INT64_PARAM : public PARAM
-{
- int64_t iValue;
- __forceinline INT64_PARAM(const char *_name, int64_t _value) :
- PARAM(_name), iValue(_value)
- {
- }
-};
-
-struct SINT64_PARAM : public PARAM
-{
- int64_t iValue;
- __forceinline SINT64_PARAM(const char *_name, int64_t _value) :
- PARAM(_name), iValue(_value)
- {
- }
-};
-
-struct CHAR_PARAM : public PARAM
-{
- const char *szValue;
- __forceinline CHAR_PARAM(const char *_name, const char *_value) :
- PARAM(_name), szValue(_value)
- {
- }
-};
-
-struct WCHAR_PARAM : public PARAM
-{
- const wchar_t *wszValue;
- __forceinline WCHAR_PARAM(const char *_name, const wchar_t *_value) :
- PARAM(_name), wszValue(_value)
- {
- }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Callbacks
-
-class CCallbackImp
-{
- struct CDummy
- {
- int foo;
- };
-
- typedef void (CDummy:: *TFnCallback)(void *argument);
-
- CDummy *m_object;
- TFnCallback m_func;
-
-protected:
- template<typename TClass, typename TArgument>
- __inline CCallbackImp(TClass *object, void (TClass:: *func)(TArgument *argument)) :
- m_object((CDummy *)object),
- m_func((TFnCallback)func)
- {
- }
-
- __inline void Invoke(void *argument) const { if (m_func && m_object) (m_object->*m_func)(argument); }
-
-public:
- __inline CCallbackImp() : m_object(nullptr), m_func(nullptr) {}
-
- __inline CCallbackImp(const CCallbackImp &other) : m_object(other.m_object), m_func(other.m_func) {}
- __inline CCallbackImp &operator=(const CCallbackImp &other) { m_object = other.m_object; m_func = other.m_func; return *this; }
-
- __inline bool operator==(const CCallbackImp &other) const { return (m_object == other.m_object) && (m_func == other.m_func); }
- __inline bool operator!=(const CCallbackImp &other) const { return (m_object != other.m_object) || (m_func != other.m_func); }
-
- __inline operator bool() const { return m_object && m_func; }
-};
-
-template<typename TArgument>
-struct CCallback : public CCallbackImp
-{
- typedef CCallbackImp CSuper;
-
-public:
- __inline CCallback() {}
-
- template<typename TClass>
- __inline CCallback(TClass *object, void (TClass:: *func)(TArgument *argument)) : CCallbackImp(object, func) {}
-
- __inline CCallback &operator=(const CCallbackImp &x) { CSuper::operator =(x); return *this; }
-
- __inline void operator()(TArgument *argument) const { Invoke((void *)argument); }
-};
-
-template<typename TClass, typename TArgument>
-__inline CCallback<TArgument> Callback(TClass *object, void (TClass:: *func)(TArgument *argument))
-{
- return CCallback<TArgument>(object, func);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// http support
-
-// works inline, in the same buffer, thus destroying its contents
-// returns the address of buffer passed
-
-MIR_CORE_DLL(char *) mir_urlDecode(char *szUrl);
-
-MIR_CORE_DLL(CMStringA) mir_urlEncode(const char *szUrl);
-
-#endif // __cpluscplus
-
-#endif // M_SYSTEM_H
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+Copyright (c) 2000-08 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.
+*/
+
+#pragma once
+
+#ifndef M_SYSTEM_H__
+#define M_SYSTEM_H__ 1
+
+#ifndef MIRANDANAME
+ #define MIRANDANAME "Miranda NG"
+#endif
+#ifndef MIRANDACLASS
+ #define MIRANDACLASS "Miranda"
+#endif
+
+// set the default compatibility lever for Miranda 0.4.x
+#ifndef MIRANDA_VER
+ #define MIRANDA_VER 0x0A00
+#endif
+
+#ifndef _MSC_VER
+ #define __forceinline inline __attribute__ ((always_inline))
+#else
+ #pragma warning(disable:4244 4245)
+#endif
+
+#define NEWSTR_ALLOCA(A) (A == NULL)?NULL:strcpy((char*)alloca(strlen(A)+1), A)
+#define NEWWSTR_ALLOCA(A) ((A==NULL)?NULL:wcscpy((wchar_t*)alloca(sizeof(wchar_t)*(wcslen(A)+1)),A))
+
+#include <m_core.h>
+
+// miranda/system/modulesloaded
+// called after all modules have been successfully initialised
+// wParam = lParam = 0
+// used to resolve double-dependencies in the module load order
+#define ME_SYSTEM_MODULESLOADED "Miranda/System/ModulesLoaded"
+
+// miranda/system/shutdown event
+// called just before the application terminates
+// the database is still guaranteed to be running during this hook.
+// wParam = lParam = 0
+#define ME_SYSTEM_SHUTDOWN "Miranda/System/Shutdown"
+
+// restarts miranda (0.8+)
+// wParam = 0 or 1. 1 - restart with current profile, 0 - restart in default profile or profile manager
+// lParam = (wchar_t*)path to a new miranda32.exe binary or NULL to use current
+#define MS_SYSTEM_RESTART "Miranda/System/Restart"
+
+// miranda/system/oktoexit event
+// called before the app goes into shutdown routine to make sure everyone is
+// happy to exit
+// wParam = lParam = 0
+// return nonzero to stop the exit cycle
+#define ME_SYSTEM_OKTOEXIT "Miranda/System/OkToExitEvent"
+
+// gets the version number of Miranda encoded as a DWORD
+// returns the version number, encoded as one version per byte, therefore
+// version 1.2.3.10 is 0x0102030a
+EXTERN_C MIR_APP_DLL(DWORD) Miranda_GetVersion(void);
+
+// gets the version number of Miranda encoded as four WORDs v0.92.2+
+// returns the version number, encoded as one version per word, therefore
+// version 1.2.3.3210 is 0x0001, 0x0002, 0x0003, 0x0C8a
+typedef uint16_t MFileVersion[4];
+EXTERN_C MIR_APP_DLL(void) Miranda_GetFileVersion(MFileVersion*);
+
+// gets the version of Miranda encoded as text
+// cch is the size of the buffer pointed to by pszVersion, in bytes
+// may return a build qualifier, such as "0.1.0.1 alpha"
+// returns 0 on success, nonzero on failure
+EXTERN_C MIR_APP_DLL(void) Miranda_GetVersionText(char *pDest, size_t cbSize);
+
+// returns a system window that can handle global timers
+// a usual practice is to use a unique pointer as a timer id
+EXTERN_C MIR_APP_DLL(class CDlgBase *) Miranda_GetSystemWindow();
+
+// Adds an event to the list to be checked in the main message loop
+// when a handle gets triggered, an appopriate stub gets called
+typedef void (CALLBACK *MWaitableStub)(void);
+typedef void (CALLBACK *MWaitableStubEx)(void*);
+
+EXTERN_C MIR_APP_DLL(void) Miranda_WaitOnHandle(MWaitableStub pFunc, HANDLE hEvent = nullptr);
+EXTERN_C MIR_APP_DLL(void) Miranda_WaitOnHandleEx(MWaitableStubEx pFunc, void *pInfo);
+
+// wParam = 0 (ignored)
+// lParam = 0 (ignored)
+//
+// This hook is fired just before the thread unwind stack is used,
+// it allows MT plugins to shutdown threads if they have any special
+// processing to do, etc.
+#define ME_SYSTEM_PRESHUTDOWN "Miranda/System/PShutdown"
+
+// Returns true when Miranda has got WM_QUIT and is in the process of shutting down
+EXTERN_C MIR_APP_DLL(bool) Miranda_IsTerminated(void);
+
+// Check if everyone is happy to exit
+// if everyone acknowleges OK to exit then returns true, otherwise false
+EXTERN_C MIR_APP_DLL(bool) Miranda_OkToExit(void);
+
+// Used by contact lists inside CloseAction
+// Waits for a permission to exit and destroys contact list
+EXTERN_C MIR_APP_DLL(void) Miranda_Close(void);
+
+// Sets up a function pointer to be called after main loop iterations, suitable for idle processing
+EXTERN_C MIR_APP_DLL(void) Miranda_SetIdleCallback(void(MIR_CDECL *pfnCallback)(void));
+
+// returns the last window tick where a monitored event was seen, currently WM_CHAR/WM_MOUSEMOVE
+EXTERN_C MIR_APP_DLL(DWORD) Miranda_GetIdle(void);
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(__cplusplus)
+
+#ifndef M_STRING_H__
+ #include <m_string.h>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// general lists' templates
+
+struct MIR_CORE_EXPORT MNonCopyable
+{
+ __inline MNonCopyable() {}
+
+ MNonCopyable(const MNonCopyable &) = delete;
+ MNonCopyable &operator=(const MNonCopyable &) = delete;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// mir_ptr - automatic pointer for buffers, allocated using mir_alloc/mir_calloc
+
+template<class T> class mir_ptr
+{
+protected:
+ T *data;
+
+public:
+ __inline explicit mir_ptr() : data(nullptr) {}
+ __inline explicit mir_ptr(T *_p) : data(_p) {}
+ __inline ~mir_ptr() { mir_free(data); }
+ __inline T *get() const { return data; }
+ __inline T *operator=(T *_p) { if (data) mir_free(data); data = _p; return data; }
+ __inline T *operator->() const { return data; }
+ __inline operator T *() const { return data; }
+ __inline operator INT_PTR() const { return (INT_PTR)data; }
+ __inline T *detach() { T *res = data; data = nullptr; return res; }
+};
+
+typedef mir_ptr<char> ptrA;
+typedef mir_ptr<wchar_t> ptrW;
+
+///////////////////////////////////////////////////////////////////////////////
+// mir_cs - simple wrapper for the critical sections
+
+class MIR_CORE_EXPORT mir_cs : public MNonCopyable
+{
+ #ifdef _MSC_VER
+ CRITICAL_SECTION m_cs;
+ #endif
+
+public:
+ mir_cs();
+ ~mir_cs();
+
+ void Lock();
+ void Unlock();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// mir_cslock - simple locker for the critical sections
+
+class mir_cslock : public MNonCopyable
+{
+ mir_cs &cs;
+
+public:
+ __inline mir_cslock(mir_cs &_cs) : cs(_cs) { cs.Lock(); }
+ __inline ~mir_cslock() { cs.Unlock(); }
+};
+
+class mir_cslockfull : public MNonCopyable
+{
+ mir_cs &cs;
+ bool bIsLocked = false;
+
+public:
+ __inline void lock() { bIsLocked = true; cs.Lock(); }
+ __inline void unlock() { bIsLocked = false; cs.Unlock(); }
+
+ __inline mir_cslockfull(mir_cs &_cs) : cs(_cs) { lock(); }
+ __inline ~mir_cslockfull() { if (bIsLocked) unlock(); }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+//pass_ptrA, pass_ptrW and pass_ptrT - automatic pointer for passwords
+
+class pass_ptrA : public mir_ptr<char>
+{
+public:
+ __inline explicit pass_ptrA() : mir_ptr() {}
+ __inline explicit pass_ptrA(char *_p) : mir_ptr(_p) {}
+ __inline ~pass_ptrA() { zero(); }
+ __inline char *operator=(char *_p) { zero(); return mir_ptr::operator=(_p); }
+ __inline void zero()
+ {
+ if (data) SecureZeroMemory(data, mir_strlen(data));
+ }
+};
+
+class pass_ptrW : public mir_ptr<wchar_t>
+{
+public:
+ __inline explicit pass_ptrW() : mir_ptr() {}
+ __inline explicit pass_ptrW(wchar_t *_p) : mir_ptr(_p) {}
+ __inline ~pass_ptrW() { zero(); }
+ __inline wchar_t *operator=(wchar_t *_p) { zero(); return mir_ptr::operator=(_p); }
+ __inline void zero()
+ {
+ if (data) SecureZeroMemory(data, mir_wstrlen(data) * sizeof(wchar_t));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// basic class for classes that should be cleared inside new()
+
+class MZeroedObject
+{
+public:
+ __inline void *operator new(size_t size)
+ {
+ return calloc(1, size);
+ }
+
+ __inline void operator delete(void *p)
+ {
+ free(p);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// general lists' templates
+
+#define NumericKeySortT -1
+#define HandleKeySortT -2
+#define PtrKeySortT -3
+
+template<class T> struct LIST
+{
+ typedef int (*FTSortFunc)(const T *p1, const T *p2);
+
+ __inline LIST(int aincr, FTSortFunc afunc = nullptr)
+ {
+ memset(this, 0, sizeof(*this));
+ increment = aincr;
+ sortFunc = afunc;
+ }
+
+ __inline LIST(int aincr, INT_PTR id)
+ {
+ memset(this, 0, sizeof(*this));
+ increment = aincr;
+ sortFunc = FTSortFunc(id);
+ }
+
+ __inline LIST(const LIST &x)
+ {
+ items = nullptr;
+ List_Copy((SortedList *)&x, (SortedList *)this, sizeof(T));
+ }
+
+ __inline LIST &operator = (const LIST &x)
+ {
+ destroy();
+ List_Copy((SortedList *)&x, (SortedList *)this, sizeof(T));
+ return *this;
+ }
+
+ __inline ~LIST()
+ {
+ destroy();
+ }
+
+ __inline T *operator[](int idx) const { return (idx >= 0 && idx < count) ? items[idx] : nullptr; }
+ __inline int getCount(void) const { return count; }
+ __inline T **getArray(void) const { return items; }
+
+ __inline int getIndex(T *p) const
+ {
+ int idx;
+ return (!List_GetIndex((SortedList *)this, p, &idx)) ? -1 : idx;
+ }
+
+ class reverse_iterator
+ {
+ int index;
+ T **base;
+
+ public:
+ reverse_iterator(const LIST &_lst) :
+ index(_lst.getCount() - 1),
+ base(_lst.getArray())
+ {
+ }
+
+ class iterator
+ {
+ T **ptr;
+
+ public:
+ iterator(T **_p) : ptr(_p) {}
+ iterator operator++() { --ptr; return *this; }
+ bool operator!=(const iterator &p) { return ptr != p.ptr; }
+ operator T **() const { return ptr; }
+ };
+
+ __inline iterator begin() const { return iterator(base + index); }
+ __inline iterator end() const { return iterator(base - 1); }
+ __inline int indexOf(T **p) const { return int(p - base); }
+ };
+
+ __inline void destroy(void) { List_Destroy((SortedList *)this); }
+ __inline T* find(T *p) const { return (T *)List_Find((SortedList *)this, p); }
+ __inline int indexOf(T *p) const { return List_IndexOf((SortedList *)this, p); }
+ __inline int insert(T *p, int idx) { return List_Insert((SortedList *)this, p, idx); }
+ __inline int remove(int idx) { return List_Remove((SortedList *)this, idx); }
+
+ __inline int insert(T *p) { return List_InsertPtr((SortedList *)this, p); }
+ __inline int remove(T *p) { return List_RemovePtr((SortedList *)this, p); }
+
+ __inline int indexOf(T **p) const { return int(p - items); }
+
+ __inline T* removeItem(T **p)
+ {
+ T *savePtr = *p;
+ List_Remove((SortedList *)this, int(p - items));
+ return savePtr;
+ }
+
+ __inline void put(int idx, T *p) { items[idx] = p; }
+
+ __inline T **begin() const { return items; }
+ __inline T **end() const { return items + count; }
+
+ __inline reverse_iterator rev_iter() const { return reverse_iterator(*this); }
+
+protected:
+ T **items;
+ int count, limit, increment;
+ FTSortFunc sortFunc;
+};
+
+template<class T> struct OBJLIST : public LIST<T>
+{
+ typedef int (*FTSortFunc)(const T *p1, const T *p2);
+
+ __inline OBJLIST(int aincr, FTSortFunc afunc = nullptr) :
+ LIST<T>(aincr, afunc)
+ {
+ }
+
+ __inline OBJLIST(int aincr, INT_PTR id) :
+ LIST<T>(aincr, (FTSortFunc)id)
+ {
+ }
+
+ __inline OBJLIST(const OBJLIST &x) :
+ LIST<T>(x.increment, x.sortFunc)
+ {
+ this->items = nullptr;
+ List_ObjCopy((SortedList *)&x, (SortedList *)this, sizeof(T));
+ }
+
+ __inline OBJLIST &operator = (const OBJLIST &x)
+ {
+ destroy();
+ List_ObjCopy((SortedList *)&x, (SortedList *)this, sizeof(T));
+ return *this;
+ }
+
+ ~OBJLIST()
+ {
+ destroy();
+ }
+
+ __inline void destroy(void)
+ {
+ for (int i = 0; i < this->count; i++)
+ delete this->items[i];
+
+ List_Destroy((SortedList *)this);
+ }
+
+ __inline int remove(int idx)
+ {
+ delete this->items[idx];
+ return List_Remove((SortedList *)this, idx);
+ }
+
+ __inline int remove(T *p)
+ {
+ int i = this->getIndex(p);
+ if (i != -1) {
+ remove(i);
+ return 1;
+ }
+ return 0;
+ }
+
+ __inline T &operator[](int idx) const { return *this->items[idx]; }
+};
+
+#define __A2W(s) L ## s
+#define _A2W(s) __A2W(s)
+
+class _A2T : public ptrW
+{
+public:
+ __inline _A2T(const char *s) : ptrW(mir_a2u(s)) {}
+ __inline _A2T(const char *s, int cp) : ptrW(mir_a2u_cp(s, cp)) {}
+};
+
+class _T2A : public ptrA
+{
+public:
+ __forceinline _T2A(const wchar_t *s) : ptrA(mir_u2a(s)) {}
+ __forceinline _T2A(const wchar_t *s, int cp) : ptrA(mir_u2a_cp(s, cp)) {}
+};
+
+class T2Utf : public ptrA
+{
+public:
+ __forceinline T2Utf(const wchar_t *str) : ptrA(mir_utf8encodeW(str)) {}
+ __forceinline operator BYTE *() const { return (BYTE *)data; }
+#ifdef _XSTRING_
+ std::string str() const { return std::string(data); }
+#endif
+};
+
+class Utf2T : public ptrW
+{
+public:
+ __forceinline Utf2T(const char *str) : ptrW(mir_utf8decodeW(str)) {}
+ __forceinline operator wchar_t *() const { return data; }
+#ifdef _XSTRING_
+ std::wstring str() const { return std::wstring(data); }
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// basic class for classes that should be cleared inside new()
+
+class MIR_CORE_EXPORT MBinBuffer
+{
+ char *m_buf;
+ size_t m_len;
+
+public:
+ MBinBuffer();
+ ~MBinBuffer();
+
+ __forceinline char *data() const { return m_buf; }
+ __forceinline bool isEmpty() const { return m_len == 0; }
+ __forceinline size_t length() const { return m_len; }
+
+ // adds a buffer to the end
+ void append(const void *pBuf, size_t bufLen);
+
+ // adds a buffer to the beginning
+ void appendBefore(const void *pBuf, size_t bufLen);
+
+ // replaces buffer contents
+ void assign(const void *pBuf, size_t bufLen);
+
+ // drops a part of buffer
+ void remove(size_t sz);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// thread handle controller
+
+class MThreadLock
+{
+ HANDLE &m_pHandle;
+
+public:
+ __forceinline MThreadLock(HANDLE &pHandle) :
+ m_pHandle(pHandle)
+ {
+ }
+
+ __forceinline ~MThreadLock()
+ {
+ m_pHandle = nullptr;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// parameter classes for XML, JSON & HTTP requests
+
+struct PARAM
+{
+ const char *szName;
+ __forceinline PARAM(const char *_name) : szName(_name)
+ {
+ }
+};
+
+struct BOOL_PARAM : public PARAM
+{
+ bool bValue;
+ __forceinline BOOL_PARAM(const char *_name, bool _value) :
+ PARAM(_name), bValue(_value)
+ {
+ }
+};
+
+struct INT_PARAM : public PARAM
+{
+ int32_t iValue;
+ __forceinline INT_PARAM(const char *_name, int32_t _value) :
+ PARAM(_name), iValue(_value)
+ {
+ }
+};
+
+struct INT64_PARAM : public PARAM
+{
+ int64_t iValue;
+ __forceinline INT64_PARAM(const char *_name, int64_t _value) :
+ PARAM(_name), iValue(_value)
+ {
+ }
+};
+
+struct SINT64_PARAM : public PARAM
+{
+ int64_t iValue;
+ __forceinline SINT64_PARAM(const char *_name, int64_t _value) :
+ PARAM(_name), iValue(_value)
+ {
+ }
+};
+
+struct CHAR_PARAM : public PARAM
+{
+ const char *szValue;
+ __forceinline CHAR_PARAM(const char *_name, const char *_value) :
+ PARAM(_name), szValue(_value)
+ {
+ }
+};
+
+struct WCHAR_PARAM : public PARAM
+{
+ const wchar_t *wszValue;
+ __forceinline WCHAR_PARAM(const char *_name, const wchar_t *_value) :
+ PARAM(_name), wszValue(_value)
+ {
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Callbacks
+
+class CCallbackImp
+{
+ struct CDummy
+ {
+ int foo;
+ };
+
+ typedef void (CDummy:: *TFnCallback)(void *argument);
+
+ CDummy *m_object;
+ TFnCallback m_func;
+
+protected:
+ template<typename TClass, typename TArgument>
+ __inline CCallbackImp(TClass *object, void (TClass:: *func)(TArgument *argument)) :
+ m_object((CDummy *)object),
+ m_func((TFnCallback)func)
+ {
+ }
+
+ __inline void Invoke(void *argument) const { if (m_func && m_object) (m_object->*m_func)(argument); }
+
+public:
+ __inline CCallbackImp() : m_object(nullptr), m_func(nullptr) {}
+
+ __inline CCallbackImp(const CCallbackImp &other) : m_object(other.m_object), m_func(other.m_func) {}
+ __inline CCallbackImp &operator=(const CCallbackImp &other) { m_object = other.m_object; m_func = other.m_func; return *this; }
+
+ __inline bool operator==(const CCallbackImp &other) const { return (m_object == other.m_object) && (m_func == other.m_func); }
+ __inline bool operator!=(const CCallbackImp &other) const { return (m_object != other.m_object) || (m_func != other.m_func); }
+
+ __inline operator bool() const { return m_object && m_func; }
+};
+
+template<typename TArgument>
+struct CCallback : public CCallbackImp
+{
+ typedef CCallbackImp CSuper;
+
+public:
+ __inline CCallback() {}
+
+ template<typename TClass>
+ __inline CCallback(TClass *object, void (TClass:: *func)(TArgument *argument)) : CCallbackImp(object, func) {}
+
+ __inline CCallback &operator=(const CCallbackImp &x) { CSuper::operator =(x); return *this; }
+
+ __inline void operator()(TArgument *argument) const { Invoke((void *)argument); }
+};
+
+template<typename TClass, typename TArgument>
+__inline CCallback<TArgument> Callback(TClass *object, void (TClass:: *func)(TArgument *argument))
+{
+ return CCallback<TArgument>(object, func);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// http support
+
+// works inline, in the same buffer, thus destroying its contents
+// returns the address of buffer passed
+
+MIR_CORE_DLL(char *) mir_urlDecode(char *szUrl);
+
+MIR_CORE_DLL(CMStringA) mir_urlEncode(const char *szUrl);
+
+#endif // __cpluscplus
+
+#endif // M_SYSTEM_H
diff --git a/include/m_timezones.h b/include/m_timezones.h
index ef85448a90..920712a865 100644
--- a/include/m_timezones.h
+++ b/include/m_timezones.h
@@ -1,134 +1,139 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-Copyright (c) 2000-10 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 __M_TIMEZONES_H
-#define __M_TIMEZONES_H
-
-#ifndef M_CORE_H__
-#include <m_core.h>
-#endif
-
-#define MIM_TZ_NAMELEN 64
-
-#define TZF_PLF_CB 1 // UI element is assumed to be a combo box
-#define TZF_PLF_LB 2 // UI element is assumed to be a list box
-#define TZF_DIFONLY 4
-#define TZF_KNOWNONLY 8
-
-#define LOCAL_TIME_HANDLE NULL
-#define UTC_TIME_HANDLE ((void*)-1)
-
-typedef INT_PTR mir_time;
-
-EXTERN_C MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, DWORD dwFlags);
-EXTERN_C MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags);
-
-EXTERN_C MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ);
-EXTERN_C MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags);
-
-EXTERN_C MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags);
-EXTERN_C MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags);
-
-EXTERN_C MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags);
-EXTERN_C MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags);
-
-EXTERN_C MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st);
-EXTERN_C MIR_CORE_DLL(int) TimeZone_GetSystemTime(HANDLE hTZ, mir_time src, SYSTEMTIME *dest, DWORD dwFlags);
-EXTERN_C MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts);
-
-EXTERN_C MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ);
-EXTERN_C MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ);
-EXTERN_C MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname);
-
-#ifdef __cplusplus
-
-__forceinline int printDateTimeByContact (MCONTACT hContact, LPCTSTR szFormat, LPTSTR szDest, int cbDest, DWORD dwFlags)
-{
- return TimeZone_PrintDateTime(TimeZone_CreateByContact(hContact, nullptr, dwFlags), szFormat, szDest, cbDest, dwFlags);
-}
-
-__forceinline int printTimeStampByContact(MCONTACT hContact, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, int cbDest, DWORD dwFlags)
-{
- return TimeZone_PrintTimeStamp(TimeZone_CreateByContact(hContact, nullptr, dwFlags), ts, szFormat, szDest, cbDest, dwFlags);
-}
-
-__forceinline LPTIME_ZONE_INFORMATION getTziByContact(MCONTACT hContact)
-{
- return TimeZone_GetInfo(TimeZone_CreateByContact(hContact, nullptr, 0));
-}
-
-__forceinline int getTimeZoneTimeByContact(MCONTACT hContact, SYSTEMTIME *st)
-{
- return TimeZone_GetTimeZoneTime(TimeZone_CreateByContact(hContact, nullptr, 0), st);
-}
-
-__forceinline mir_time timeStampToTimeZoneTimeStampByContact(MCONTACT hContact, mir_time ts)
-{
- return TimeZone_UtcToLocal(TimeZone_CreateByContact(hContact, nullptr, 0), ts);
-}
-
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Time services
-//
-// Converts a GMT timestamp into local time
-// Returns the converted value
-//
-// Timestamps have zero at midnight 1/1/1970 GMT, this service converts such a
-// value to be based at midnight 1/1/1970 local time.
-// This service does not use a simple conversion based on the current offset
-// between GMT and local. Rather, it figures out whether daylight savings time
-// would have been in place at the time of the stamp and gives the local time as
-// it would have been at the time and date the stamp contains.
-// This service isn't nearly as useful as db/time/TimestampToString below and I
-// recommend avoiding its use when possible so that you don't get your timezones
-// mixed up (like I did. Living at GMT makes things easier for me, but has certain
-// disadvantages :-)).
-
-EXTERN_C MIR_CORE_DLL(DWORD) TimeZone_ToLocal(DWORD);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Converts a GMT timestamp into a customisable local time string
-// Returns the destination buffer
-//
-// Uses db/time/timestamptolocal for the conversion so read that description to
-// see what's going on.
-// The string is formatted according to the current user's locale, language and
-// preferences.
-// szFormat can have the following special characters:
-// t Time without seconds, eg hh:mm
-// s Time with seconds, eg hh:mm:ss
-// m Time without minutes, eg hh
-// d Short date, eg dd/mm/yyyy
-// D Long date, eg d mmmm yyyy
-// I ISO 8061 Time yyyy-mm-ddThh:mm:ssZ
-// All other characters are copied across to szDest as-is
-
-EXTERN_C MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest);
-EXTERN_C MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest);
-
-#define TimeZone_ToStringT TimeZone_ToStringW
-
-#endif /* __M_TIMEZONES_H */
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+Copyright (c) 2000-10 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 __M_TIMEZONES_H
+#define __M_TIMEZONES_H
+
+#ifndef M_CORE_H__
+#include <m_core.h>
+#endif
+
+#define MIM_TZ_NAMELEN 64
+
+#define TZF_PLF_CB 1 // UI element is assumed to be a combo box
+#define TZF_PLF_LB 2 // UI element is assumed to be a list box
+#define TZF_DIFONLY 4
+#define TZF_KNOWNONLY 8
+
+#define LOCAL_TIME_HANDLE NULL
+#define UTC_TIME_HANDLE ((void*)-1)
+
+typedef INT_PTR mir_time;
+
+EXTERN_C MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, DWORD dwFlags);
+EXTERN_C MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags);
+
+EXTERN_C MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ);
+EXTERN_C MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags);
+
+EXTERN_C MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags);
+EXTERN_C MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags);
+
+EXTERN_C MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags);
+EXTERN_C MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags);
+
+#ifdef _MSC_VER
+EXTERN_C MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st);
+EXTERN_C MIR_CORE_DLL(int) TimeZone_GetSystemTime(HANDLE hTZ, mir_time src, SYSTEMTIME *dest, DWORD dwFlags);
+
+EXTERN_C MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ);
+#endif
+EXTERN_C MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts);
+
+EXTERN_C MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ);
+EXTERN_C MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname);
+
+#ifdef __cplusplus
+
+__forceinline int printDateTimeByContact (MCONTACT hContact, LPCTSTR szFormat, LPTSTR szDest, int cbDest, DWORD dwFlags)
+{
+ return TimeZone_PrintDateTime(TimeZone_CreateByContact(hContact, nullptr, dwFlags), szFormat, szDest, cbDest, dwFlags);
+}
+
+__forceinline int printTimeStampByContact(MCONTACT hContact, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, int cbDest, DWORD dwFlags)
+{
+ return TimeZone_PrintTimeStamp(TimeZone_CreateByContact(hContact, nullptr, dwFlags), ts, szFormat, szDest, cbDest, dwFlags);
+}
+
+#ifdef _MSC_VER
+__forceinline LPTIME_ZONE_INFORMATION getTziByContact(MCONTACT hContact)
+{
+ return TimeZone_GetInfo(TimeZone_CreateByContact(hContact, nullptr, 0));
+}
+
+__forceinline int getTimeZoneTimeByContact(MCONTACT hContact, SYSTEMTIME *st)
+{
+ return TimeZone_GetTimeZoneTime(TimeZone_CreateByContact(hContact, nullptr, 0), st);
+}
+#endif
+
+__forceinline mir_time timeStampToTimeZoneTimeStampByContact(MCONTACT hContact, mir_time ts)
+{
+ return TimeZone_UtcToLocal(TimeZone_CreateByContact(hContact, nullptr, 0), ts);
+}
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Time services
+//
+// Converts a GMT timestamp into local time
+// Returns the converted value
+//
+// Timestamps have zero at midnight 1/1/1970 GMT, this service converts such a
+// value to be based at midnight 1/1/1970 local time.
+// This service does not use a simple conversion based on the current offset
+// between GMT and local. Rather, it figures out whether daylight savings time
+// would have been in place at the time of the stamp and gives the local time as
+// it would have been at the time and date the stamp contains.
+// This service isn't nearly as useful as db/time/TimestampToString below and I
+// recommend avoiding its use when possible so that you don't get your timezones
+// mixed up (like I did. Living at GMT makes things easier for me, but has certain
+// disadvantages :-)).
+
+EXTERN_C MIR_CORE_DLL(DWORD) TimeZone_ToLocal(DWORD);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Converts a GMT timestamp into a customisable local time string
+// Returns the destination buffer
+//
+// Uses db/time/timestamptolocal for the conversion so read that description to
+// see what's going on.
+// The string is formatted according to the current user's locale, language and
+// preferences.
+// szFormat can have the following special characters:
+// t Time without seconds, eg hh:mm
+// s Time with seconds, eg hh:mm:ss
+// m Time without minutes, eg hh
+// d Short date, eg dd/mm/yyyy
+// D Long date, eg d mmmm yyyy
+// I ISO 8061 Time yyyy-mm-ddThh:mm:ssZ
+// All other characters are copied across to szDest as-is
+
+EXTERN_C MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest);
+EXTERN_C MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest);
+
+#define TimeZone_ToStringT TimeZone_ToStringW
+
+#endif /* __M_TIMEZONES_H */
diff --git a/include/m_types.h b/include/m_types.h
index 005d289b24..236adfbb1f 100644
--- a/include/m_types.h
+++ b/include/m_types.h
@@ -1,44 +1,126 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-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 M_TYPES_H__
-#define M_TYPES_H__ 1
-
-#ifdef Q_OS_WIN
-
-#define FALSE 0
-#define TRUE 1
-
-typedef void *HANDLE, *HINSTANCE, *HICON, *HBITMAP, *HWND, *HGENMENU;
-typedef int BOOL;
-typedef unsigned char BYTE;
-typedef unsigned int DWORD;
-typedef intptr_t WPARAM, LPARAM, INT_PTR;
-typedef char *LPSTR;
-typedef const char *LPCSTR;
-typedef wchar_t *LPWSTR, *LPTSTR;
-typedef const wchar_t *LPCWSTR, *LPCTSTR;
-
-#endif
-
-#endif // M_TYPES_H__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+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 M_TYPES_H__
+#define M_TYPES_H__ 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Linux
+
+#include <wchar.h>
+#include <netinet/in.h>
+
+#ifndef _MSC_VER
+
+#define CALLBACK
+#define EXTERN_C extern "C"
+
+#define PURE = 0
+#define STDMETHOD(method) virtual HRESULT method
+#define STDMETHOD_(ret, method) virtual ret method
+#define STDMETHODIMP_(ret) ret
+
+#define FALSE 0
+#define TRUE 1
+#define CP_ACP 0
+#define SW_HIDE 0
+#define SW_SHOW 5
+#define MAX_PATH 260
+#define _TRUNCATE size_t(-1)
+#define INVALID_HANDLE_VALUE HANDLE(-1)
+
+typedef void *HANDLE;
+typedef int BOOL, SOCKET;
+typedef uint8_t BYTE;
+typedef uint16_t WORD;
+typedef uint32_t DWORD, UINT, COLORREF;
+typedef intptr_t WPARAM, LPARAM, INT_PTR;
+typedef uintptr_t UINT_PTR;
+typedef char *LPSTR;
+typedef const char *LPCSTR;
+typedef wchar_t *LPWSTR, *LPTSTR;
+typedef const wchar_t *LPCWSTR, *LPCTSTR;
+typedef sockaddr_in SOCKADDR_IN;
+
+struct RECT { int left, top, right, bottom; };
+struct POINT { int x, y; };
+struct SIZE { int width, height; };
+
+#define MIR_EXPORT __attribute__((__visibility__("default")))
+#define MIR_IMPORT
+#define MIR_SYSCALL
+#define MIR_CDECL
+#define UNREFERENCED_PARAMETER(x)
+
+#define __try try
+#define __except catch
+#define EXCEPTION_EXECUTE_HANDLER ...
+
+#define _In_z_
+#define _Pre_notnull_
+#define _Always_(x)
+#define _Printf_format_string_
+
+#define InterlockedIncrement(x) __sync_fetch_and_add(x, 1)
+#define InterlockedDecrement(x) __sync_fetch_and_add(x, -1)
+
+#define SecureZeroMemory(x, y) memset(x, 0, y)
+#define interface struct
+#define memcpy_s(a,b,c,d) memcpy(a,c,(b)<(d)?(b):(d))
+#define memmove_s(a,b,c,d) memmove(a,c,(b)<(d)?(b):(d))
+
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+#define wcsicmp wcscasecmp
+#define wcsnicmp wcsncasecmp
+
+#define _vsnprintf vsnprintf
+#define _vsnwprintf vswprintf
+
+#define DECLARE_HANDLE(name) struct _##name { int unused; }; typedef struct _##name *name
+DECLARE_HANDLE(HWND);
+DECLARE_HANDLE(HFONT);
+DECLARE_HANDLE(HICON);
+DECLARE_HANDLE(HMENU);
+DECLARE_HANDLE(HBRUSH);
+DECLARE_HANDLE(HBITMAP);
+DECLARE_HANDLE(HCURSOR);
+DECLARE_HANDLE(HTREEITEM);
+DECLARE_HANDLE(HINSTANCE);
+
+struct EXCEPTION_POINTERS { int unused; };
+struct LOGFONT { int unused; };
+
+#else
+///////////////////////////////////////////////////////////////////////////////
+// Windows
+
+#define MIR_EXPORT __declspec(dllexport)
+#define MIR_IMPORT __declspec(dllimport)
+
+#define MIR_SYSCALL __stdcall
+#define MIR_CDECL __cdecl
+
+#endif
+
+#endif // M_TYPES_H__
diff --git a/include/m_xml.h b/include/m_xml.h
index 491c4a016c..d09b289cf3 100644
--- a/include/m_xml.h
+++ b/include/m_xml.h
@@ -1,195 +1,194 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-Copyright (c) 2000-08 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 M_XML_H__
-#define M_XML_H__
-
-#include <tchar.h>
-#include <m_core.h>
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// new API to replace the old one
-
-#ifdef MIR_CORE_EXPORTS
-#define TINYXML2_EXPORT 1
-#else
-#define TINYXML2_IMPORT 1
-#endif
-
-#include "../src/mir_core/src/tinyxml2.h"
-
-typedef tinyxml2::XMLNode TiXmlNode;
-typedef tinyxml2::XMLText TiXmlText;
-typedef tinyxml2::XMLElement TiXmlElement;
-typedef tinyxml2::XMLDocument TiXmlDocument;
-
-typedef tinyxml2::XMLHandle TiXmlHandle;
-typedef tinyxml2::XMLConstHandle TiXmlConst;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// safe wrappers
-
-EXTERN_C MIR_CORE_DLL(int) XmlGetChildCount(const TiXmlElement*);
-
-EXTERN_C MIR_CORE_DLL(TiXmlElement*) XmlAddChild(TiXmlElement*, const char *pszName);
-EXTERN_C MIR_CORE_DLL(TiXmlElement*) XmlAddChildA(TiXmlElement*, const char *pszName, const char *ptszValue);
-EXTERN_C MIR_CORE_DLL(TiXmlElement*) XmlAddChildI(TiXmlElement*, const char *pszName, int iValue);
-
-EXTERN_C MIR_CORE_DLL(int) XmlGetChildInt(const TiXmlElement *hXml, const char *key);
-EXTERN_C MIR_CORE_DLL(const char*) XmlGetChildText(const TiXmlElement *hXml, const char *key);
-EXTERN_C MIR_CORE_DLL(const TiXmlElement*) XmlGetChildByTag(const TiXmlElement *hXml, const char *key, const char *attrName, const char *attrValue);
-EXTERN_C MIR_CORE_DLL(const TiXmlElement*) XmlFirstChild(const TiXmlElement *hXml, const char *key = nullptr);
-
-EXTERN_C MIR_CORE_DLL(void) XmlAddAttr(TiXmlElement*, const char *pszName, const char *ptszValue);
-EXTERN_C MIR_CORE_DLL(const char*) XmlGetAttr(const TiXmlElement*, const char *pszName);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// simple element iterator
-//
-// allows traversing subnodes in a cycle like
-// for (auto *pNode : TiXmlEnum(pRoot)) {
-
-class TiXmlIterator
-{
- const TiXmlElement *m_pCurr;
-
-public:
- TiXmlIterator(const TiXmlElement *pNode) :
- m_pCurr(pNode)
- {
- }
-
- TiXmlIterator& operator=(const TiXmlElement *pNode)
- {
- m_pCurr = pNode;
- return *this;
- }
-
- // Prefix ++ overload
- TiXmlIterator& operator++()
- {
- if (m_pCurr)
- m_pCurr = m_pCurr->NextSiblingElement();
- return *this;
- }
-
- const TiXmlElement* operator*()
- {
- return m_pCurr;
- }
-
- bool operator!=(const TiXmlIterator &iterator)
- {
- return m_pCurr != iterator.m_pCurr;
- }
-};
-
-class TiXmlEnum
-{
- const TiXmlElement *m_pFirst;
-
-public:
- TiXmlEnum(const TiXmlNode *pNode)
- {
- m_pFirst = (pNode) ? pNode->FirstChildElement() : nullptr;
- }
-
- TiXmlIterator begin()
- {
- return TiXmlIterator(m_pFirst);
- }
-
- TiXmlIterator end()
- {
- return TiXmlIterator(nullptr);
- }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// filtered element iterator
-//
-// allows traversing subnodes of the specified name in a cycle like
-// for (auto *pNode : TiXmlFilter(pRoot, "element")) {
-
-class TiXmlFilterIterator
-{
- const TiXmlElement *m_pCurr;
- const char *m_pszFilter;
-
-public:
- TiXmlFilterIterator(const TiXmlElement *pNode, const char *pszNodeName) :
- m_pszFilter(pszNodeName),
- m_pCurr(pNode)
- {
- }
-
- TiXmlFilterIterator& operator=(const TiXmlElement *pNode)
- {
- m_pCurr = pNode;
- return *this;
- }
-
- // Prefix ++ overload
- TiXmlFilterIterator& operator++()
- {
- if (m_pCurr)
- m_pCurr = m_pCurr->NextSiblingElement(m_pszFilter);
- return *this;
- }
-
- const TiXmlElement* operator*()
- {
- return m_pCurr;
- }
-
- bool operator!=(const TiXmlFilterIterator &iterator)
- {
- return m_pCurr != iterator.m_pCurr;
- }
-};
-
-class TiXmlFilter
-{
- const TiXmlElement *m_pFirst;
- const char *m_pszFilter;
-
-public:
- TiXmlFilter(const TiXmlNode *pNode, const char *pszNodeName) :
- m_pszFilter(pszNodeName)
- {
- m_pFirst = (pNode) ? pNode->FirstChildElement(pszNodeName) : nullptr;
- }
-
- TiXmlFilterIterator begin()
- {
- return TiXmlFilterIterator(m_pFirst, m_pszFilter);
- }
-
- TiXmlFilterIterator end()
- {
- return TiXmlFilterIterator(nullptr, nullptr);
- }
-};
-
-#endif // M_XML_H__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+Copyright (c) 2000-08 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 M_XML_H__
+#define M_XML_H__
+
+#include <m_core.h>
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// new API to replace the old one
+
+#ifdef MIR_CORE_EXPORTS
+#define TINYXML2_EXPORT 1
+#else
+#define TINYXML2_IMPORT 1
+#endif
+
+#include "../src/mir_core/src/tinyxml2.h"
+
+typedef tinyxml2::XMLNode TiXmlNode;
+typedef tinyxml2::XMLText TiXmlText;
+typedef tinyxml2::XMLElement TiXmlElement;
+typedef tinyxml2::XMLDocument TiXmlDocument;
+
+typedef tinyxml2::XMLHandle TiXmlHandle;
+typedef tinyxml2::XMLConstHandle TiXmlConst;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// safe wrappers
+
+EXTERN_C MIR_CORE_DLL(int) XmlGetChildCount(const TiXmlElement*);
+
+EXTERN_C MIR_CORE_DLL(TiXmlElement*) XmlAddChild(TiXmlElement*, const char *pszName);
+EXTERN_C MIR_CORE_DLL(TiXmlElement*) XmlAddChildA(TiXmlElement*, const char *pszName, const char *ptszValue);
+EXTERN_C MIR_CORE_DLL(TiXmlElement*) XmlAddChildI(TiXmlElement*, const char *pszName, int iValue);
+
+EXTERN_C MIR_CORE_DLL(int) XmlGetChildInt(const TiXmlElement *hXml, const char *key);
+EXTERN_C MIR_CORE_DLL(const char*) XmlGetChildText(const TiXmlElement *hXml, const char *key);
+EXTERN_C MIR_CORE_DLL(const TiXmlElement*) XmlGetChildByTag(const TiXmlElement *hXml, const char *key, const char *attrName, const char *attrValue);
+EXTERN_C MIR_CORE_DLL(const TiXmlElement*) XmlFirstChild(const TiXmlElement *hXml, const char *key = nullptr);
+
+EXTERN_C MIR_CORE_DLL(void) XmlAddAttr(TiXmlElement*, const char *pszName, const char *ptszValue);
+EXTERN_C MIR_CORE_DLL(const char*) XmlGetAttr(const TiXmlElement*, const char *pszName);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// simple element iterator
+//
+// allows traversing subnodes in a cycle like
+// for (auto *pNode : TiXmlEnum(pRoot)) {
+
+class TiXmlIterator
+{
+ const TiXmlElement *m_pCurr;
+
+public:
+ TiXmlIterator(const TiXmlElement *pNode) :
+ m_pCurr(pNode)
+ {
+ }
+
+ TiXmlIterator& operator=(const TiXmlElement *pNode)
+ {
+ m_pCurr = pNode;
+ return *this;
+ }
+
+ // Prefix ++ overload
+ TiXmlIterator& operator++()
+ {
+ if (m_pCurr)
+ m_pCurr = m_pCurr->NextSiblingElement();
+ return *this;
+ }
+
+ const TiXmlElement* operator*()
+ {
+ return m_pCurr;
+ }
+
+ bool operator!=(const TiXmlIterator &iterator)
+ {
+ return m_pCurr != iterator.m_pCurr;
+ }
+};
+
+class TiXmlEnum
+{
+ const TiXmlElement *m_pFirst;
+
+public:
+ TiXmlEnum(const TiXmlNode *pNode)
+ {
+ m_pFirst = (pNode) ? pNode->FirstChildElement() : nullptr;
+ }
+
+ TiXmlIterator begin()
+ {
+ return TiXmlIterator(m_pFirst);
+ }
+
+ TiXmlIterator end()
+ {
+ return TiXmlIterator(nullptr);
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// filtered element iterator
+//
+// allows traversing subnodes of the specified name in a cycle like
+// for (auto *pNode : TiXmlFilter(pRoot, "element")) {
+
+class TiXmlFilterIterator
+{
+ const TiXmlElement *m_pCurr;
+ const char *m_pszFilter;
+
+public:
+ TiXmlFilterIterator(const TiXmlElement *pNode, const char *pszNodeName) :
+ m_pszFilter(pszNodeName),
+ m_pCurr(pNode)
+ {
+ }
+
+ TiXmlFilterIterator& operator=(const TiXmlElement *pNode)
+ {
+ m_pCurr = pNode;
+ return *this;
+ }
+
+ // Prefix ++ overload
+ TiXmlFilterIterator& operator++()
+ {
+ if (m_pCurr)
+ m_pCurr = m_pCurr->NextSiblingElement(m_pszFilter);
+ return *this;
+ }
+
+ const TiXmlElement* operator*()
+ {
+ return m_pCurr;
+ }
+
+ bool operator!=(const TiXmlFilterIterator &iterator)
+ {
+ return m_pCurr != iterator.m_pCurr;
+ }
+};
+
+class TiXmlFilter
+{
+ const TiXmlElement *m_pFirst;
+ const char *m_pszFilter;
+
+public:
+ TiXmlFilter(const TiXmlNode *pNode, const char *pszNodeName) :
+ m_pszFilter(pszNodeName)
+ {
+ m_pFirst = (pNode) ? pNode->FirstChildElement(pszNodeName) : nullptr;
+ }
+
+ TiXmlFilterIterator begin()
+ {
+ return TiXmlFilterIterator(m_pFirst, m_pszFilter);
+ }
+
+ TiXmlFilterIterator end()
+ {
+ return TiXmlFilterIterator(nullptr, nullptr);
+ }
+};
+
+#endif // M_XML_H__
diff --git a/include/newpluginapi.h b/include/newpluginapi.h
index 21ec09fd54..33394bbfa3 100644
--- a/include/newpluginapi.h
+++ b/include/newpluginapi.h
@@ -1,517 +1,498 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-Copyright (c) 2000-08 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 M_NEWPLUGINAPI_H__
-#define M_NEWPLUGINAPI_H__
-
-#if !defined(HIMAGELIST)
-typedef struct _IMAGELIST* HIMAGELIST;
-#endif
-
-#include <m_core.h>
-#include <m_database.h>
-
-#define PLUGIN_MAKE_VERSION(a, b, c, d) (((((DWORD)(a))&0xFF)<<24)|((((DWORD)(b))&0xFF)<<16)|((((DWORD)(c))&0xFF)<<8)|(((DWORD)(d))&0xFF))
-#define MAXMODULELABELLENGTH 64
-
-#define UNICODE_AWARE 0x0001
-#define STATIC_PLUGIN 0x0002
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// The UUID structure below is used to for plugin UUID's and module type definitions
-
-struct MUUID
-{
- unsigned long a;
- unsigned short b;
- unsigned short c;
- unsigned char d[8];
-};
-
-__forceinline bool operator==(const MUUID &p1, const MUUID &p2)
-{
- return memcmp(&p1, &p2, sizeof(MUUID)) == 0;
-}
-__forceinline bool operator!=(const MUUID &p1, const MUUID &p2)
-{
- return memcmp(&p1, &p2, sizeof(MUUID)) != 0;
-}
-
-MIR_APP_DLL(int) GetPluginLangId(const MUUID &uuid, int langId);
-MIR_APP_DLL(int) IsPluginLoaded(const MUUID &uuid);
-MIR_APP_DLL(int) SetServiceModePlugin(const char *szPluginName, WPARAM = 0, LPARAM = 0);
-
-// manually get/set flag specified at Options - Plugins - Enabled
-MIR_APP_DLL(bool) IsPluginOnWhiteList(const char *szPluginName);
-MIR_APP_DLL(void) SetPluginOnWhiteList(const char *szPluginName, bool bAllow);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Used to define the end of the MirandaPluginInterface list
-
-#define MIID_LAST {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Replaceable internal modules interface ids
-
-#define MIID_HISTORY {0x5ca0cbc1, 0x999a, 0x4ea2, {0x8b, 0x44, 0xf8, 0xf6, 0x7d, 0x7f, 0x8e, 0xbe}}
-#define MIID_UIUSERINFO {0x570b931c, 0x9af8, 0x48f1, {0xad, 0x9f, 0xc4, 0x49, 0x8c, 0x61, 0x8a, 0x77}}
-#define MIID_SRAWAY {0x5ab54c76, 0x1b4c, 0x4a00, {0xb4, 0x04, 0x48, 0xcb, 0xea, 0x5f, 0xef, 0xe7}}
-#define MIID_SREMAIL {0xd005b5a6, 0x1b66, 0x445a, {0xb6, 0x03, 0x74, 0xd4, 0xd4, 0x55, 0x2d, 0xe2}}
-#define MIID_SRFILE {0x989d104d, 0xacb7, 0x4ee0, {0xb9, 0x6d, 0x67, 0xce, 0x46, 0x53, 0xb6, 0x95}}
-#define MIID_UIHISTORY {0x7f7e3d98, 0xce1f, 0x4962, {0x82, 0x84, 0x96, 0x85, 0x50, 0xf1, 0xd3, 0xd9}}
-#define MIID_AUTOAWAY {0x9c87f7dc, 0x3bd7, 0x4983, {0xb7, 0xfb, 0xb8, 0x48, 0xfd, 0xbc, 0x91, 0xf0}}
-#define MIID_USERONLINE {0x130829e0, 0x2463, 0x4ff8, {0xbb, 0xc8, 0xce, 0x73, 0xc0, 0x18, 0x84, 0x42}}
-#define MIID_CRYPTO {0x415ca6e1, 0x895f, 0x40e6, {0x87, 0xbd, 0x9b, 0x39, 0x60, 0x16, 0xd0, 0xe5}}
-#define MIID_POPUP {0xb275f4a4, 0xe347, 0x4515, {0xaf, 0x71, 0x77, 0xd0, 0x1e, 0xef, 0x54, 0x41}}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Common plugin interfaces (core plugins)
-
-#define MIID_DATABASE {0xae77fd33, 0xe484, 0x4dc7, {0x8c, 0xbc, 0x09, 0x9f, 0xed, 0xcc, 0xcf, 0xdd}}
-#define MIID_CLIST {0x9d8da8bf, 0x665b, 0x4908, {0x9e, 0x61, 0x9f, 0x75, 0x98, 0xae, 0x33, 0x0e}}
-#define MIID_SRMM {0x58c7eea6, 0xf9db, 0x4dd9, {0x80, 0x36, 0xae, 0x80, 0x2b, 0xc0, 0x41, 0x4c}}
-#define MIID_TESTPLUGIN {0x53b974f4, 0x3c74, 0x4dba, {0x8f, 0xc2, 0x6f, 0x92, 0xfe, 0x01, 0x3b, 0x8c}}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Special exception interface for protocols.
-// This interface allows more than one plugin to implement it at the same time
-
-#define MIID_PROTOCOL {0x2a3c815e, 0xa7d9, 0x424b, {0xba, 0x30, 0x2, 0xd0, 0x83, 0x22, 0x90, 0x85}}
-
-#define MIID_SERVICEMODE {0x8a92c026, 0x953a, 0x4f5f, { 0x99, 0x21, 0xf2, 0xc2, 0xdc, 0x19, 0x5e, 0xc5}}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Each service mode plugin must implement MS_SERVICEMODE_LAUNCH
-// This service might return one of the following values:
-// SERVICE_CONTINUE - load Miranda normally, like there's no service plugins at all
-// SERVICE_ONLYDB - load database and then execute service plugin only
-// SERVICE_MONOPOLY - execute only service plugin, even without database
-// SERVICE_FAILED - terminate Miranda execution
-
-#define SERVICE_CONTINUE 0
-#define SERVICE_ONLYDB 1
-#define SERVICE_MONOPOLY 2
-#define SERVICE_FAILED (-1)
-
-#define MS_SERVICEMODE_LAUNCH "ServiceMode/Launch"
-
-struct PLUGININFOEX
-{
- int cbSize;
- char *shortName;
- DWORD version;
- char *description;
- char *author;
- char *copyright;
- char *homepage;
- BYTE flags; // right now the only flag, UNICODE_AWARE, is recognized here
- MUUID uuid; // plugin's unique identifier
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Miranda/System/LoadModule event
-// called when a plugin is being loaded dynamically
-// wParam = CMPluginBase*
-// lParam = HINSTANCE of the loaded plugin
-
-#define ME_SYSTEM_MODULELOAD "Miranda/System/LoadModule"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Miranda/System/UnloadModule event
-// called when a plugin is being unloaded dynamically
-// wParam = CMPluginBase*
-// lParam = HINSTANCE of the plugin to be unloaded
-
-#define ME_SYSTEM_MODULEUNLOAD "Miranda/System/UnloadModule"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// plugin's class
-
-// initializes an empty account
-typedef struct PROTO_INTERFACE* (*pfnInitProto)(const char* szModuleName, const wchar_t* szUserName);
-
-// deallocates an account instance
-typedef int(*pfnUninitProto)(PROTO_INTERFACE*);
-
-#pragma warning(push)
-#pragma warning(disable:4275)
-
-struct IcolibItem;
-
-class MIR_APP_EXPORT CMPluginBase : public MNonCopyable
-{
- void tryOpenLog();
-
-protected:
- HINSTANCE m_hInst;
- const char *m_szModuleName;
- const PLUGININFOEX &m_pInfo;
- HANDLE m_hLogger = nullptr;
- LIST<IcolibItem> m_arIcons;
-
- CMPluginBase(const char *moduleName, const PLUGININFOEX &pInfo);
- ~CMPluginBase();
-
- // pass one of PROTOTYPE_* constants as type
- void RegisterProtocol(int type, pfnInitProto = nullptr, pfnUninitProto = nullptr);
- void SetUniqueId(const char *pszUniqueId);
-
-public:
- void debugLogA(LPCSTR szFormat, ...);
- void debugLogW(LPCWSTR wszFormat, ...);
-
- __forceinline void addIcolib(HANDLE hIcolib) { m_arIcons.insert((IcolibItem*)hIcolib); }
- int addImgListIcon(HIMAGELIST himl, int iconId);
- HICON getIcon(int iconId, bool big = false);
- HANDLE getIconHandle(int iconId);
- void releaseIcon(int iconId, bool big = false);
-
- __forceinline const PLUGININFOEX& getInfo() const { return m_pInfo; }
- __forceinline const char* getModule() const { return m_szModuleName; }
-
- __forceinline HINSTANCE getInst() const { return m_hInst; }
- __forceinline void setInst(HINSTANCE hInst) { m_hInst = hInst; }
-
- virtual int Load();
- virtual int Unload();
-
- ////////////////////////////////////////////////////////////////////////////////////////
- // registering module's resources
-
- template <size_t _Size>
- __forceinline void registerIcon(const char *szSection, IconItem(&pIcons)[_Size], const char *prefix = nullptr)
- {
- Icon_Register(m_hInst, szSection, pIcons, _Size, prefix, this);
- }
-
- template <size_t _Size>
- __forceinline void registerIconW(const wchar_t *szSection, IconItemT(&pIcons)[_Size], const char *prefix = nullptr)
- {
- Icon_RegisterT(m_hInst, szSection, pIcons, _Size, prefix, this);
- }
-
- int addOptions(WPARAM wParam, struct OPTIONSDIALOGPAGE *odp);
- void openOptions(const wchar_t *pszGroup, const wchar_t *pszPage = 0, const wchar_t *pszTab = 0);
- void openOptionsPage(const wchar_t *pszGroup, const wchar_t *pszPage = 0, const wchar_t *pszTab = 0);
-
- HANDLE addIcon(const struct SKINICONDESC*);
- HANDLE addTTB(const struct TTBButton*);
-
- HGENMENU addRootMenu(int hMenuObject, LPCWSTR ptszName, int position, HANDLE hIcoLib = nullptr);
-
- int addFont(struct FontID *pFont);
- int addFont(struct FontIDW *pFont);
-
- int addColor(struct ColourID *pColor);
- int addColor(struct ColourIDW *pColor);
-
- int addEffect(struct EffectID *pEffect);
- int addEffect(struct EffectIDW *pEffect);
-
- int addFrame(const struct CLISTFrame*);
- int addHotkey(const struct HOTKEYDESC*);
- int addSound(const char *name, const wchar_t *section, const wchar_t *description, const wchar_t *defaultFile = nullptr);
- int addUserInfo(WPARAM wParam, struct OPTIONSDIALOGPAGE *odp);
-
- ////////////////////////////////////////////////////////////////////////////////////////
-
- __forceinline INT_PTR delSetting(const char *name)
- {
- return db_unset(0, m_szModuleName, name);
- }
- __forceinline INT_PTR delSetting(MCONTACT hContact, const char *name)
- {
- return db_unset(hContact, m_szModuleName, name);
- }
-
- __forceinline bool getBool(const char *name, bool defaultValue = false)
- {
- return db_get_b(0, m_szModuleName, name, defaultValue) != 0;
- }
- __forceinline bool getBool(MCONTACT hContact, const char *name, bool defaultValue = false)
- {
- return db_get_b(hContact, m_szModuleName, name, defaultValue) != 0;
- }
-
- __forceinline int getByte(const char *name, int defaultValue = 0)
- {
- return db_get_b(0, m_szModuleName, name, defaultValue);
- }
- __forceinline int getByte(MCONTACT hContact, const char *name, int defaultValue = 0)
- {
- return db_get_b(hContact, m_szModuleName, name, defaultValue);
- }
-
- __forceinline int getWord(const char *name, int defaultValue = 0)
- {
- return db_get_w(0, m_szModuleName, name, defaultValue);
- }
- __forceinline int getWord(MCONTACT hContact, const char *name, int defaultValue = 0)
- {
- return db_get_w(hContact, m_szModuleName, name, defaultValue);
- }
-
- __forceinline DWORD getDword(const char *name, int defaultValue = 0)
- {
- return db_get_dw(0, m_szModuleName, name, defaultValue);
- }
- __forceinline DWORD getDword(MCONTACT hContact, const char *name, int defaultValue = 0)
- {
- return db_get_dw(hContact, m_szModuleName, name, defaultValue);
- }
-
- __forceinline INT_PTR getString(const char *name, DBVARIANT *result)
- {
- return db_get_s(0, m_szModuleName, name, result);
- }
- __forceinline INT_PTR getString(MCONTACT hContact, const char *name, DBVARIANT *result)
- {
- return db_get_s(hContact, m_szModuleName, name, result);
- }
-
- __forceinline INT_PTR getUString(const char *name, DBVARIANT *result)
- {
- return db_get_utf(0, m_szModuleName, name, result);
- }
- __forceinline INT_PTR getUString(MCONTACT hContact, const char *name, DBVARIANT *result)
- {
- return db_get_utf(hContact, m_szModuleName, name, result);
- }
-
- __forceinline INT_PTR getWString(const char *name, DBVARIANT *result)
- {
- return db_get_ws(0, m_szModuleName, name, result);
- }
- __forceinline INT_PTR getWString(MCONTACT hContact, const char *name, DBVARIANT *result)
- {
- return db_get_ws(hContact, m_szModuleName, name, result);
- }
-
- __forceinline CMStringA getMStringA(const char *name, const char *szValue = nullptr)
- {
- return db_get_sm(0, m_szModuleName, name, szValue);
- }
- __forceinline CMStringA getMStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr)
- {
- return db_get_sm(hContact, m_szModuleName, name, szValue);
- }
-
- __forceinline char* getStringA(const char *name, const char *szValue = nullptr)
- {
- return db_get_sa(0, m_szModuleName, name, szValue);
- }
- __forceinline char* getStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr)
- {
- return db_get_sa(hContact, m_szModuleName, name, szValue);
- }
-
- __forceinline char* getUStringA(const char *name, const char *szValue = nullptr)
- {
- return db_get_utfa(0, m_szModuleName, name, szValue);
- }
- __forceinline char* getUStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr)
- {
- return db_get_utfa(hContact, m_szModuleName, name, szValue);
- }
-
- __forceinline wchar_t* getWStringA(const char *name, const wchar_t *szValue = nullptr)
- {
- return db_get_wsa(0, m_szModuleName, name, szValue);
- }
- __forceinline wchar_t* getWStringA(MCONTACT hContact, const char *name, const wchar_t *szValue = nullptr)
- {
- return db_get_wsa(hContact, m_szModuleName, name, szValue);
- }
-
- __forceinline CMStringW getMStringW(const char *name, const wchar_t *szValue = nullptr)
- {
- return db_get_wsm(0, m_szModuleName, name, szValue);
- }
- __forceinline CMStringW getMStringW(MCONTACT hContact, const char *name, const wchar_t *szValue = nullptr)
- {
- return db_get_wsm(hContact, m_szModuleName, name, szValue);
- }
-
- __forceinline void setByte(const char *name, BYTE value)
- {
- db_set_b(0, m_szModuleName, name, value);
- }
- __forceinline void setByte(MCONTACT hContact, const char *name, BYTE value)
- {
- db_set_b(hContact, m_szModuleName, name, value);
- }
-
- __forceinline void setWord(const char *name, WORD value)
- {
- db_set_w(0, m_szModuleName, name, value);
- }
- __forceinline void setWord(MCONTACT hContact, const char *name, WORD value)
- {
- db_set_w(hContact, m_szModuleName, name, value);
- }
-
- __forceinline void setDword(const char *name, DWORD value)
- {
- db_set_dw(0, m_szModuleName, name, value);
- }
- __forceinline void setDword(MCONTACT hContact, const char *name, DWORD value)
- {
- db_set_dw(hContact, m_szModuleName, name, value);
- }
-
- __forceinline void setString(const char *name, const char* value)
- {
- db_set_s(0, m_szModuleName, name, value);
- }
- __forceinline void setString(MCONTACT hContact, const char *name, const char* value)
- {
- db_set_s(hContact, m_szModuleName, name, value);
- }
-
- __forceinline void setUString(const char *name, const char* value)
- {
- db_set_utf(0, m_szModuleName, name, value);
- }
- __forceinline void setUString(MCONTACT hContact, const char *name, const char* value)
- {
- db_set_utf(hContact, m_szModuleName, name, value);
- }
-
- __forceinline void setWString(const char *name, const wchar_t* value)
- {
- db_set_ws(0, m_szModuleName, name, value);
- }
- __forceinline void setWString(MCONTACT hContact, const char *name, const wchar_t* value)
- {
- db_set_ws(hContact, m_szModuleName, name, value);
- }
-};
-
-#pragma warning(pop)
-
-extern struct CMPlugin g_plugin;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Basic class for plugins (not protocols) written in C++
-
-typedef BOOL(WINAPI * const _pfnCrtInit)(HINSTANCE, DWORD, LPVOID);
-
-template<class T> class PLUGIN : public CMPluginBase
-{
- typedef CMPluginBase CSuper;
-
-protected:
- __forceinline PLUGIN(const char *moduleName, const PLUGININFOEX &pInfo)
- : CSuper(moduleName, pInfo)
- {}
-
- __forceinline HANDLE CreatePluginEvent(const char *name)
- {
- CMStringA str(FORMAT, "%s\\%s", m_szModuleName, name);
- return CreateHookableEvent(str);
- }
-
- typedef int(__cdecl T::*MyEventFunc)(WPARAM, LPARAM);
- __forceinline void HookPluginEvent(const char *name, MyEventFunc pFunc)
- {
- HookEventObj(name, (MIRANDAHOOKOBJ)*(void**)&pFunc, this);
- }
-
- typedef INT_PTR(__cdecl T::*MyServiceFunc)(WPARAM, LPARAM);
- __forceinline void CreatePluginService(const char *name, MyServiceFunc pFunc)
- {
- CMStringA str(FORMAT, "%s\\%s", m_szModuleName, name);
- CreateServiceFunctionObj(str, (MIRANDASERVICEOBJ)*(void**)&pFunc, this);
- }
-
- typedef INT_PTR(__cdecl T::*MyServiceFuncParam)(WPARAM, LPARAM, LPARAM);
- __forceinline void CreatePluginServiceParam(const char *name, MyServiceFuncParam pFunc, LPARAM param)
- {
- CMStringA str(FORMAT, "%s\\%s", m_szModuleName, name);
- CreateServiceFunctionObjParam(str, (MIRANDASERVICEOBJPARAM)*(void**)&pFunc, this, param);
- }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Basic class for protocols with accounts
-
-struct CMPlugin;
-
-template<class P> class ACCPROTOPLUGIN : public PLUGIN<CMPlugin>
-{
- typedef PLUGIN<CMPlugin> CSuper;
-
-protected:
- ACCPROTOPLUGIN(const char *moduleName, const PLUGININFOEX &pInfo) :
- CSuper(moduleName, pInfo)
- {
- CMPluginBase::RegisterProtocol(1002, &fnInit, &fnUninit);
- }
-
- static PROTO_INTERFACE* fnInit(const char *szModuleName, const wchar_t *wszAccountName)
- {
- P *ppro = new P(szModuleName, wszAccountName);
- g_arInstances.insert(ppro);
- return ppro;
- }
-
- static int fnUninit(PROTO_INTERFACE *ppro)
- {
- g_arInstances.remove((P*)ppro);
- return 0;
- }
-
-public:
- static OBJLIST<P> g_arInstances;
-
- static P* getInstance(const char *szProto)
- {
- for (auto &it : g_arInstances)
- if (mir_strcmp(szProto, it->m_szModuleName) == 0)
- return it;
-
- return nullptr;
- }
-
- static P* getInstance(MCONTACT hContact)
- {
- return getInstance(::Proto_GetBaseAccountName(hContact));
- }
-};
-
-template<class P>
-OBJLIST<P> ACCPROTOPLUGIN<P>::g_arInstances(1, PtrKeySortT);
-
-#ifndef __NO_CMPLUGIN_NEEDED
-#ifdef _DEBUG
-#pragma comment(lib, "cmstubd.lib")
-#else
-#pragma comment(lib, "cmstub.lib")
-#endif
-#endif
-
-EXTERN_C MIR_APP_DLL(HINSTANCE) GetInstByAddress(void* codePtr);
-EXTERN_C MIR_APP_DLL(CMPluginBase&) GetPluginByInstance(HINSTANCE hInst);
-
-#endif // M_NEWPLUGINAPI_H__
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+Copyright (c) 2000-08 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 M_NEWPLUGINAPI_H__
+#define M_NEWPLUGINAPI_H__
+
+#if !defined(HIMAGELIST)
+typedef struct _IMAGELIST* HIMAGELIST;
+#endif
+
+#include <m_core.h>
+#include <m_database.h>
+#include <m_protocols.h>
+
+#define PLUGIN_MAKE_VERSION(a, b, c, d) (((((DWORD)(a))&0xFF)<<24)|((((DWORD)(b))&0xFF)<<16)|((((DWORD)(c))&0xFF)<<8)|(((DWORD)(d))&0xFF))
+#define MAXMODULELABELLENGTH 64
+
+#define UNICODE_AWARE 0x0001
+#define STATIC_PLUGIN 0x0002
+
+MIR_APP_DLL(int) GetPluginLangId(const MUUID &uuid, int langId);
+MIR_APP_DLL(int) IsPluginLoaded(const MUUID &uuid);
+MIR_APP_DLL(int) SetServiceModePlugin(const char *szPluginName, WPARAM = 0, LPARAM = 0);
+
+// manually get/set flag specified at Options - Plugins - Enabled
+MIR_APP_DLL(bool) IsPluginOnWhiteList(const char *szPluginName);
+MIR_APP_DLL(void) SetPluginOnWhiteList(const char *szPluginName, bool bAllow);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Used to define the end of the MirandaPluginInterface list
+
+#define MIID_LAST {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Replaceable internal modules interface ids
+
+#define MIID_HISTORY {0x5ca0cbc1, 0x999a, 0x4ea2, {0x8b, 0x44, 0xf8, 0xf6, 0x7d, 0x7f, 0x8e, 0xbe}}
+#define MIID_UIUSERINFO {0x570b931c, 0x9af8, 0x48f1, {0xad, 0x9f, 0xc4, 0x49, 0x8c, 0x61, 0x8a, 0x77}}
+#define MIID_SRAWAY {0x5ab54c76, 0x1b4c, 0x4a00, {0xb4, 0x04, 0x48, 0xcb, 0xea, 0x5f, 0xef, 0xe7}}
+#define MIID_SREMAIL {0xd005b5a6, 0x1b66, 0x445a, {0xb6, 0x03, 0x74, 0xd4, 0xd4, 0x55, 0x2d, 0xe2}}
+#define MIID_SRFILE {0x989d104d, 0xacb7, 0x4ee0, {0xb9, 0x6d, 0x67, 0xce, 0x46, 0x53, 0xb6, 0x95}}
+#define MIID_UIHISTORY {0x7f7e3d98, 0xce1f, 0x4962, {0x82, 0x84, 0x96, 0x85, 0x50, 0xf1, 0xd3, 0xd9}}
+#define MIID_AUTOAWAY {0x9c87f7dc, 0x3bd7, 0x4983, {0xb7, 0xfb, 0xb8, 0x48, 0xfd, 0xbc, 0x91, 0xf0}}
+#define MIID_USERONLINE {0x130829e0, 0x2463, 0x4ff8, {0xbb, 0xc8, 0xce, 0x73, 0xc0, 0x18, 0x84, 0x42}}
+#define MIID_CRYPTO {0x415ca6e1, 0x895f, 0x40e6, {0x87, 0xbd, 0x9b, 0x39, 0x60, 0x16, 0xd0, 0xe5}}
+#define MIID_POPUP {0xb275f4a4, 0xe347, 0x4515, {0xaf, 0x71, 0x77, 0xd0, 0x1e, 0xef, 0x54, 0x41}}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Common plugin interfaces (core plugins)
+
+#define MIID_DATABASE {0xae77fd33, 0xe484, 0x4dc7, {0x8c, 0xbc, 0x09, 0x9f, 0xed, 0xcc, 0xcf, 0xdd}}
+#define MIID_CLIST {0x9d8da8bf, 0x665b, 0x4908, {0x9e, 0x61, 0x9f, 0x75, 0x98, 0xae, 0x33, 0x0e}}
+#define MIID_SRMM {0x58c7eea6, 0xf9db, 0x4dd9, {0x80, 0x36, 0xae, 0x80, 0x2b, 0xc0, 0x41, 0x4c}}
+#define MIID_TESTPLUGIN {0x53b974f4, 0x3c74, 0x4dba, {0x8f, 0xc2, 0x6f, 0x92, 0xfe, 0x01, 0x3b, 0x8c}}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Special exception interface for protocols.
+// This interface allows more than one plugin to implement it at the same time
+
+#define MIID_PROTOCOL {0x2a3c815e, 0xa7d9, 0x424b, {0xba, 0x30, 0x2, 0xd0, 0x83, 0x22, 0x90, 0x85}}
+
+#define MIID_SERVICEMODE {0x8a92c026, 0x953a, 0x4f5f, { 0x99, 0x21, 0xf2, 0xc2, 0xdc, 0x19, 0x5e, 0xc5}}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Each service mode plugin must implement MS_SERVICEMODE_LAUNCH
+// This service might return one of the following values:
+// SERVICE_CONTINUE - load Miranda normally, like there's no service plugins at all
+// SERVICE_ONLYDB - load database and then execute service plugin only
+// SERVICE_MONOPOLY - execute only service plugin, even without database
+// SERVICE_FAILED - terminate Miranda execution
+
+#define SERVICE_CONTINUE 0
+#define SERVICE_ONLYDB 1
+#define SERVICE_MONOPOLY 2
+#define SERVICE_FAILED (-1)
+
+#define MS_SERVICEMODE_LAUNCH "ServiceMode/Launch"
+
+struct PLUGININFOEX
+{
+ int cbSize;
+ char *shortName;
+ DWORD version;
+ char *description;
+ char *author;
+ char *copyright;
+ char *homepage;
+ BYTE flags; // right now the only flag, UNICODE_AWARE, is recognized here
+ MUUID uuid; // plugin's unique identifier
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Miranda/System/LoadModule event
+// called when a plugin is being loaded dynamically
+// wParam = CMPluginBase*
+// lParam = HINSTANCE of the loaded plugin
+
+#define ME_SYSTEM_MODULELOAD "Miranda/System/LoadModule"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Miranda/System/UnloadModule event
+// called when a plugin is being unloaded dynamically
+// wParam = CMPluginBase*
+// lParam = HINSTANCE of the plugin to be unloaded
+
+#define ME_SYSTEM_MODULEUNLOAD "Miranda/System/UnloadModule"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// plugin's class
+
+// initializes an empty account
+typedef struct PROTO_INTERFACE* (*pfnInitProto)(const char* szModuleName, const wchar_t* szUserName);
+
+// deallocates an account instance
+typedef int(*pfnUninitProto)(PROTO_INTERFACE*);
+
+#pragma warning(push)
+#pragma warning(disable:4275)
+
+struct IcolibItem;
+
+class MIR_APP_EXPORT CMPluginBase : public MNonCopyable
+{
+ void tryOpenLog();
+
+protected:
+ HINSTANCE m_hInst;
+ const char *m_szModuleName;
+ const PLUGININFOEX &m_pInfo;
+ HANDLE m_hLogger = nullptr;
+ LIST<IcolibItem> m_arIcons;
+
+ CMPluginBase(const char *moduleName, const PLUGININFOEX &pInfo);
+ ~CMPluginBase();
+
+ // pass one of PROTOTYPE_* constants as type
+ void RegisterProtocol(int type, pfnInitProto = nullptr, pfnUninitProto = nullptr);
+ void SetUniqueId(const char *pszUniqueId);
+
+public:
+ void debugLogA(LPCSTR szFormat, ...);
+ void debugLogW(LPCWSTR wszFormat, ...);
+
+ __forceinline void addIcolib(HANDLE hIcolib) { m_arIcons.insert((IcolibItem*)hIcolib); }
+ int addImgListIcon(HIMAGELIST himl, int iconId);
+ HICON getIcon(int iconId, bool big = false);
+ HANDLE getIconHandle(int iconId);
+ void releaseIcon(int iconId, bool big = false);
+
+ __forceinline const PLUGININFOEX& getInfo() const { return m_pInfo; }
+ __forceinline const char* getModule() const { return m_szModuleName; }
+
+ __forceinline HINSTANCE getInst() const { return m_hInst; }
+ __forceinline void setInst(HINSTANCE hInst) { m_hInst = hInst; }
+
+ virtual int Load();
+ virtual int Unload();
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // registering module's resources
+
+ template <size_t _Size>
+ __forceinline void registerIcon(const char *szSection, IconItem(&pIcons)[_Size], const char *prefix = nullptr)
+ {
+ Icon_Register(m_hInst, szSection, pIcons, _Size, prefix, this);
+ }
+
+ template <size_t _Size>
+ __forceinline void registerIconW(const wchar_t *szSection, IconItemT(&pIcons)[_Size], const char *prefix = nullptr)
+ {
+ Icon_RegisterT(m_hInst, szSection, pIcons, _Size, prefix, this);
+ }
+
+ int addOptions(WPARAM wParam, struct OPTIONSDIALOGPAGE *odp);
+ void openOptions(const wchar_t *pszGroup, const wchar_t *pszPage = 0, const wchar_t *pszTab = 0);
+ void openOptionsPage(const wchar_t *pszGroup, const wchar_t *pszPage = 0, const wchar_t *pszTab = 0);
+
+ HANDLE addIcon(const struct SKINICONDESC*);
+ HANDLE addTTB(const struct TTBButton*);
+
+ HGENMENU addRootMenu(int hMenuObject, LPCWSTR ptszName, int position, HANDLE hIcoLib = nullptr);
+
+ int addFont(struct FontID *pFont);
+ int addFont(struct FontIDW *pFont);
+
+ int addColor(struct ColourID *pColor);
+ int addColor(struct ColourIDW *pColor);
+
+ int addEffect(struct EffectID *pEffect);
+ int addEffect(struct EffectIDW *pEffect);
+
+ int addFrame(const struct CLISTFrame*);
+ int addHotkey(const struct HOTKEYDESC*);
+ int addSound(const char *name, const wchar_t *section, const wchar_t *description, const wchar_t *defaultFile = nullptr);
+ int addUserInfo(WPARAM wParam, struct OPTIONSDIALOGPAGE *odp);
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline INT_PTR delSetting(const char *name)
+ {
+ return db_unset(0, m_szModuleName, name);
+ }
+ __forceinline INT_PTR delSetting(MCONTACT hContact, const char *name)
+ {
+ return db_unset(hContact, m_szModuleName, name);
+ }
+
+ __forceinline bool getBool(const char *name, bool defaultValue = false)
+ {
+ return db_get_b(0, m_szModuleName, name, defaultValue) != 0;
+ }
+ __forceinline bool getBool(MCONTACT hContact, const char *name, bool defaultValue = false)
+ {
+ return db_get_b(hContact, m_szModuleName, name, defaultValue) != 0;
+ }
+
+ __forceinline int getByte(const char *name, int defaultValue = 0)
+ {
+ return db_get_b(0, m_szModuleName, name, defaultValue);
+ }
+ __forceinline int getByte(MCONTACT hContact, const char *name, int defaultValue = 0)
+ {
+ return db_get_b(hContact, m_szModuleName, name, defaultValue);
+ }
+
+ __forceinline int getWord(const char *name, int defaultValue = 0)
+ {
+ return db_get_w(0, m_szModuleName, name, defaultValue);
+ }
+ __forceinline int getWord(MCONTACT hContact, const char *name, int defaultValue = 0)
+ {
+ return db_get_w(hContact, m_szModuleName, name, defaultValue);
+ }
+
+ __forceinline DWORD getDword(const char *name, int defaultValue = 0)
+ {
+ return db_get_dw(0, m_szModuleName, name, defaultValue);
+ }
+ __forceinline DWORD getDword(MCONTACT hContact, const char *name, int defaultValue = 0)
+ {
+ return db_get_dw(hContact, m_szModuleName, name, defaultValue);
+ }
+
+ __forceinline INT_PTR getString(const char *name, DBVARIANT *result)
+ {
+ return db_get_s(0, m_szModuleName, name, result);
+ }
+ __forceinline INT_PTR getString(MCONTACT hContact, const char *name, DBVARIANT *result)
+ {
+ return db_get_s(hContact, m_szModuleName, name, result);
+ }
+
+ __forceinline INT_PTR getUString(const char *name, DBVARIANT *result)
+ {
+ return db_get_utf(0, m_szModuleName, name, result);
+ }
+ __forceinline INT_PTR getUString(MCONTACT hContact, const char *name, DBVARIANT *result)
+ {
+ return db_get_utf(hContact, m_szModuleName, name, result);
+ }
+
+ __forceinline INT_PTR getWString(const char *name, DBVARIANT *result)
+ {
+ return db_get_ws(0, m_szModuleName, name, result);
+ }
+ __forceinline INT_PTR getWString(MCONTACT hContact, const char *name, DBVARIANT *result)
+ {
+ return db_get_ws(hContact, m_szModuleName, name, result);
+ }
+
+ __forceinline CMStringA getMStringA(const char *name, const char *szValue = nullptr)
+ {
+ return db_get_sm(0, m_szModuleName, name, szValue);
+ }
+ __forceinline CMStringA getMStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr)
+ {
+ return db_get_sm(hContact, m_szModuleName, name, szValue);
+ }
+
+ __forceinline char* getStringA(const char *name, const char *szValue = nullptr)
+ {
+ return db_get_sa(0, m_szModuleName, name, szValue);
+ }
+ __forceinline char* getStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr)
+ {
+ return db_get_sa(hContact, m_szModuleName, name, szValue);
+ }
+
+ __forceinline char* getUStringA(const char *name, const char *szValue = nullptr)
+ {
+ return db_get_utfa(0, m_szModuleName, name, szValue);
+ }
+ __forceinline char* getUStringA(MCONTACT hContact, const char *name, const char *szValue = nullptr)
+ {
+ return db_get_utfa(hContact, m_szModuleName, name, szValue);
+ }
+
+ __forceinline wchar_t* getWStringA(const char *name, const wchar_t *szValue = nullptr)
+ {
+ return db_get_wsa(0, m_szModuleName, name, szValue);
+ }
+ __forceinline wchar_t* getWStringA(MCONTACT hContact, const char *name, const wchar_t *szValue = nullptr)
+ {
+ return db_get_wsa(hContact, m_szModuleName, name, szValue);
+ }
+
+ __forceinline CMStringW getMStringW(const char *name, const wchar_t *szValue = nullptr)
+ {
+ return db_get_wsm(0, m_szModuleName, name, szValue);
+ }
+ __forceinline CMStringW getMStringW(MCONTACT hContact, const char *name, const wchar_t *szValue = nullptr)
+ {
+ return db_get_wsm(hContact, m_szModuleName, name, szValue);
+ }
+
+ __forceinline void setByte(const char *name, BYTE value)
+ {
+ db_set_b(0, m_szModuleName, name, value);
+ }
+ __forceinline void setByte(MCONTACT hContact, const char *name, BYTE value)
+ {
+ db_set_b(hContact, m_szModuleName, name, value);
+ }
+
+ __forceinline void setWord(const char *name, WORD value)
+ {
+ db_set_w(0, m_szModuleName, name, value);
+ }
+ __forceinline void setWord(MCONTACT hContact, const char *name, WORD value)
+ {
+ db_set_w(hContact, m_szModuleName, name, value);
+ }
+
+ __forceinline void setDword(const char *name, DWORD value)
+ {
+ db_set_dw(0, m_szModuleName, name, value);
+ }
+ __forceinline void setDword(MCONTACT hContact, const char *name, DWORD value)
+ {
+ db_set_dw(hContact, m_szModuleName, name, value);
+ }
+
+ __forceinline void setString(const char *name, const char* value)
+ {
+ db_set_s(0, m_szModuleName, name, value);
+ }
+ __forceinline void setString(MCONTACT hContact, const char *name, const char* value)
+ {
+ db_set_s(hContact, m_szModuleName, name, value);
+ }
+
+ __forceinline void setUString(const char *name, const char* value)
+ {
+ db_set_utf(0, m_szModuleName, name, value);
+ }
+ __forceinline void setUString(MCONTACT hContact, const char *name, const char* value)
+ {
+ db_set_utf(hContact, m_szModuleName, name, value);
+ }
+
+ __forceinline void setWString(const char *name, const wchar_t* value)
+ {
+ db_set_ws(0, m_szModuleName, name, value);
+ }
+ __forceinline void setWString(MCONTACT hContact, const char *name, const wchar_t* value)
+ {
+ db_set_ws(hContact, m_szModuleName, name, value);
+ }
+};
+
+#pragma warning(pop)
+
+extern struct CMPlugin g_plugin;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Basic class for plugins (not protocols) written in C++
+
+typedef BOOL(MIR_SYSCALL* const _pfnCrtInit)(HINSTANCE, DWORD, void*);
+
+template<class T> class PLUGIN : public CMPluginBase
+{
+ typedef CMPluginBase CSuper;
+
+protected:
+ __forceinline PLUGIN(const char *moduleName, const PLUGININFOEX &pInfo)
+ : CSuper(moduleName, pInfo)
+ {}
+
+ __forceinline HANDLE CreatePluginEvent(const char *name)
+ {
+ CMStringA str(FORMAT, "%s\\%s", m_szModuleName, name);
+ return CreateHookableEvent(str);
+ }
+
+ typedef int(MIR_CDECL T::*MyEventFunc)(WPARAM, LPARAM);
+ __forceinline void HookPluginEvent(const char *name, MyEventFunc pFunc)
+ {
+ HookEventObj(name, (MIRANDAHOOKOBJ)*(void**)&pFunc, this);
+ }
+
+ typedef INT_PTR(MIR_CDECL T::*MyServiceFunc)(WPARAM, LPARAM);
+ __forceinline void CreatePluginService(const char *name, MyServiceFunc pFunc)
+ {
+ CMStringA str(FORMAT, "%s\\%s", m_szModuleName, name);
+ CreateServiceFunctionObj(str, (MIRANDASERVICEOBJ)*(void**)&pFunc, this);
+ }
+
+ typedef INT_PTR(MIR_CDECL T::*MyServiceFuncParam)(WPARAM, LPARAM, LPARAM);
+ __forceinline void CreatePluginServiceParam(const char *name, MyServiceFuncParam pFunc, LPARAM param)
+ {
+ CMStringA str(FORMAT, "%s\\%s", m_szModuleName, name);
+ CreateServiceFunctionObjParam(str, (MIRANDASERVICEOBJPARAM)*(void**)&pFunc, this, param);
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Basic class for protocols with accounts
+
+struct CMPlugin;
+
+template<class P> class ACCPROTOPLUGIN : public PLUGIN<CMPlugin>
+{
+ typedef PLUGIN<CMPlugin> CSuper;
+
+protected:
+ ACCPROTOPLUGIN(const char *moduleName, const PLUGININFOEX &pInfo) :
+ CSuper(moduleName, pInfo)
+ {
+ CMPluginBase::RegisterProtocol(1002, &fnInit, &fnUninit);
+ }
+
+ static PROTO_INTERFACE* fnInit(const char *szModuleName, const wchar_t *wszAccountName)
+ {
+ P *ppro = new P(szModuleName, wszAccountName);
+ g_arInstances.insert(ppro);
+ return ppro;
+ }
+
+ static int fnUninit(PROTO_INTERFACE *ppro)
+ {
+ g_arInstances.remove((P*)ppro);
+ return 0;
+ }
+
+public:
+ static OBJLIST<P> g_arInstances;
+
+ static P* getInstance(const char *szProto)
+ {
+ for (auto &it : g_arInstances)
+ if (mir_strcmp(szProto, it->m_szModuleName) == 0)
+ return it;
+
+ return nullptr;
+ }
+
+ static P* getInstance(MCONTACT hContact)
+ {
+ return getInstance(::Proto_GetBaseAccountName(hContact));
+ }
+};
+
+template<class P>
+OBJLIST<P> ACCPROTOPLUGIN<P>::g_arInstances(1, PtrKeySortT);
+
+#ifndef __NO_CMPLUGIN_NEEDED
+#ifdef _DEBUG
+#pragma comment(lib, "cmstubd.lib")
+#else
+#pragma comment(lib, "cmstub.lib")
+#endif
+#endif
+
+EXTERN_C MIR_APP_DLL(HINSTANCE) GetInstByAddress(void* codePtr);
+EXTERN_C MIR_APP_DLL(CMPluginBase&) GetPluginByInstance(HINSTANCE hInst);
+
+#endif // M_NEWPLUGINAPI_H__
diff --git a/libs/Pcre16/pcre16.cbp b/libs/Pcre16/pcre16.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/libs/Pcre16/pcre16.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/libs/Pcre16/pcre16.layout b/libs/Pcre16/pcre16.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/libs/Pcre16/pcre16.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/libs/freeimage/freeimage.cbp b/libs/freeimage/freeimage.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/libs/freeimage/freeimage.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/libs/freeimage/freeimage.layout b/libs/freeimage/freeimage.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/libs/freeimage/freeimage.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/libs/libjson/libjson.cbp b/libs/libjson/libjson.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/libs/libjson/libjson.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/libs/libjson/libjson.layout b/libs/libjson/libjson.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/libs/libjson/libjson.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/libs/libsignal/libsignal.cbp b/libs/libsignal/libsignal.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/libs/libsignal/libsignal.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/libs/libsignal/libsignal.layout b/libs/libsignal/libsignal.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/libs/libsignal/libsignal.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/libs/sqlite3/sqlite3.cbp b/libs/sqlite3/sqlite3.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/libs/sqlite3/sqlite3.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/libs/sqlite3/sqlite3.layout b/libs/sqlite3/sqlite3.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/libs/sqlite3/sqlite3.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/libs/zlib/zlib.cbp b/libs/zlib/zlib.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/libs/zlib/zlib.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/libs/zlib/zlib.layout b/libs/zlib/zlib.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/libs/zlib/zlib.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/AVS/avs.cbp b/plugins/AVS/avs.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/AVS/avs.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/AVS/avs.layout b/plugins/AVS/avs.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/AVS/avs.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/Clist_modern/clist_modern.cbp b/plugins/Clist_modern/clist_modern.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/Clist_modern/clist_modern.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/Clist_modern/clist_modern.layout b/plugins/Clist_modern/clist_modern.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/Clist_modern/clist_modern.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/Clist_modern/icons_pack/Toolbar_icons.cbp b/plugins/Clist_modern/icons_pack/Toolbar_icons.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/Clist_modern/icons_pack/Toolbar_icons.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/Clist_modern/icons_pack/Toolbar_icons.layout b/plugins/Clist_modern/icons_pack/Toolbar_icons.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/Clist_modern/icons_pack/Toolbar_icons.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/Cln_skinedit/skinedit.cbp b/plugins/Cln_skinedit/skinedit.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/Cln_skinedit/skinedit.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/Cln_skinedit/skinedit.layout b/plugins/Cln_skinedit/skinedit.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/Cln_skinedit/skinedit.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/DbChecker/dbchecker.cbp b/plugins/DbChecker/dbchecker.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/DbChecker/dbchecker.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/DbChecker/dbchecker.layout b/plugins/DbChecker/dbchecker.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/DbChecker/dbchecker.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/Dbx_sqlite/dbx_sqlite.cbp b/plugins/Dbx_sqlite/dbx_sqlite.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/Dbx_sqlite/dbx_sqlite.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/Dbx_sqlite/dbx_sqlite.layout b/plugins/Dbx_sqlite/dbx_sqlite.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/Dbx_sqlite/dbx_sqlite.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/Import/import.cbp b/plugins/Import/import.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/Import/import.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/Import/import.layout b/plugins/Import/import.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/Import/import.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/PluginUpdater/PluginUpdater.cbp b/plugins/PluginUpdater/PluginUpdater.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/PluginUpdater/PluginUpdater.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/PluginUpdater/PluginUpdater.layout b/plugins/PluginUpdater/PluginUpdater.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/PluginUpdater/PluginUpdater.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/TabSRMM/TabSRMM_icons/NOVA/ICONS_NOVA_16.cbp b/plugins/TabSRMM/TabSRMM_icons/NOVA/ICONS_NOVA_16.cbp
new file mode 100644
index 0000000000..daed7cf466
--- /dev/null
+++ b/plugins/TabSRMM/TabSRMM_icons/NOVA/ICONS_NOVA_16.cbp
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="TabSRMM_icons" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build>
+ <Target title="Debug x64">
+ <Option output="../../../../../../../home/ghazan/miranda-ng/bin16/Debug64/Icons/TabSRMM_icons" prefix_auto="1" extension_auto="1" />
+ <Option object_output="../../../../../../../home/ghazan/miranda-ng/bin16/Debug64/Obj/TabSRMM_icons/" />
+ <Option deps_output="../../../../../../../home/ghazan/miranda-ng/bin16/Debug64/Icons/" />
+ <Option type="3" />
+ <Option compiler="gcc" />
+ <Compiler>
+ <Add option="-g" />
+ <Add option="-D_DEBUG" />
+ </Compiler>
+ <ResourceCompiler>
+ <Add directory="../../../../include/msapi/" />
+ </ResourceCompiler>
+ <Linker>
+ <Add library="winmm.lib" />
+ <Add library="comctl32.lib" />
+ <Add library="kernel32.lib" />
+ <Add library="user32.lib" />
+ <Add library="gdi32.lib" />
+ <Add library="winspool.lib" />
+ <Add library="comdlg32.lib" />
+ <Add library="advapi32.lib" />
+ <Add library="shell32.lib" />
+ <Add library="ole32.lib" />
+ <Add library="oleaut32.lib" />
+ <Add library="uuid.lib" />
+ <Add library="odbc32.lib" />
+ <Add library="odbccp32.lib" />
+ <Add directory="../../../../../../../home/ghazan/miranda-ng/bin16/lib/" />
+ </Linker>
+ </Target>
+ <Target title="Release x64">
+ <Option output="../../../../../../../home/ghazan/miranda-ng/bin16/Release64/Icons/TabSRMM_icons" prefix_auto="1" extension_auto="1" />
+ <Option object_output="../../../../../../../home/ghazan/miranda-ng/bin16/Release64/Obj/TabSRMM_icons/" />
+ <Option deps_output="../../../../../../../home/ghazan/miranda-ng/bin16/Release64/Icons/" />
+ <Option type="3" />
+ <Option compiler="gcc" />
+ <Compiler>
+ <Add option="-DNDEBUG" />
+ </Compiler>
+ <ResourceCompiler>
+ <Add directory="../../../../include/msapi/" />
+ </ResourceCompiler>
+ <Linker>
+ <Add library="winmm.lib" />
+ <Add library="comctl32.lib" />
+ <Add library="kernel32.lib" />
+ <Add library="user32.lib" />
+ <Add library="gdi32.lib" />
+ <Add library="winspool.lib" />
+ <Add library="comdlg32.lib" />
+ <Add library="advapi32.lib" />
+ <Add library="shell32.lib" />
+ <Add library="ole32.lib" />
+ <Add library="oleaut32.lib" />
+ <Add library="uuid.lib" />
+ <Add library="odbc32.lib" />
+ <Add library="odbccp32.lib" />
+ <Add directory="../../../../../../../home/ghazan/miranda-ng/bin16/lib/" />
+ </Linker>
+ </Target>
+ <Target title="Release Win32">
+ <Option output="../../../../../../../home/ghazan/miranda-ng/bin16/Release/Icons/TabSRMM_icons" prefix_auto="1" extension_auto="1" />
+ <Option object_output="../../../../../../../home/ghazan/miranda-ng/bin16/Release/Obj/TabSRMM_icons/" />
+ <Option deps_output="../../../../../../../home/ghazan/miranda-ng/bin16/Release/Icons/" />
+ <Option type="3" />
+ <Option compiler="gcc" />
+ <Compiler>
+ <Add option="-DNDEBUG" />
+ </Compiler>
+ <ResourceCompiler>
+ <Add directory="../../../../include/msapi/" />
+ </ResourceCompiler>
+ <Linker>
+ <Add library="winmm.lib" />
+ <Add library="comctl32.lib" />
+ <Add library="kernel32.lib" />
+ <Add library="user32.lib" />
+ <Add library="gdi32.lib" />
+ <Add library="winspool.lib" />
+ <Add library="comdlg32.lib" />
+ <Add library="advapi32.lib" />
+ <Add library="shell32.lib" />
+ <Add library="ole32.lib" />
+ <Add library="oleaut32.lib" />
+ <Add library="uuid.lib" />
+ <Add library="odbc32.lib" />
+ <Add library="odbccp32.lib" />
+ <Add directory="../../../../../../../home/ghazan/miranda-ng/bin16/lib/" />
+ </Linker>
+ </Target>
+ <Target title="Debug Win32">
+ <Option output="../../../../../../../home/ghazan/miranda-ng/bin16/Debug/Icons/TabSRMM_icons" prefix_auto="1" extension_auto="1" />
+ <Option object_output="../../../../../../../home/ghazan/miranda-ng/bin16/Debug/Obj/TabSRMM_icons/" />
+ <Option deps_output="../../../../../../../home/ghazan/miranda-ng/bin16/Debug/Icons/" />
+ <Option type="3" />
+ <Option compiler="gcc" />
+ <Compiler>
+ <Add option="-g" />
+ <Add option="-D_DEBUG" />
+ </Compiler>
+ <ResourceCompiler>
+ <Add directory="../../../../include/msapi/" />
+ </ResourceCompiler>
+ <Linker>
+ <Add library="winmm.lib" />
+ <Add library="comctl32.lib" />
+ <Add library="kernel32.lib" />
+ <Add library="user32.lib" />
+ <Add library="gdi32.lib" />
+ <Add library="winspool.lib" />
+ <Add library="comdlg32.lib" />
+ <Add library="advapi32.lib" />
+ <Add library="shell32.lib" />
+ <Add library="ole32.lib" />
+ <Add library="oleaut32.lib" />
+ <Add library="uuid.lib" />
+ <Add library="odbc32.lib" />
+ <Add library="odbccp32.lib" />
+ <Add directory="../../../../../../../home/ghazan/miranda-ng/bin16/lib/" />
+ </Linker>
+ </Target>
+ </Build>
+ <Unit filename="../Version.h" />
+ <Unit filename="../resource.h" />
+ <Unit filename="res/ICONS_NOVA.rc" />
+ <Unit filename="res/Version.rc" />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/TabSRMM/TabSRMM_icons/NOVA/ICONS_NOVA_16.layout b/plugins/TabSRMM/TabSRMM_icons/NOVA/ICONS_NOVA_16.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/TabSRMM/TabSRMM_icons/NOVA/ICONS_NOVA_16.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/TabSRMM/tabsrmm.cbp b/plugins/TabSRMM/tabsrmm.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/TabSRMM/tabsrmm.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/TabSRMM/tabsrmm.layout b/plugins/TabSRMM/tabsrmm.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/TabSRMM/tabsrmm.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/plugins/TopToolBar/TopToolBar.cbp b/plugins/TopToolBar/TopToolBar.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/plugins/TopToolBar/TopToolBar.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/plugins/TopToolBar/TopToolBar.layout b/plugins/TopToolBar/TopToolBar.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/plugins/TopToolBar/TopToolBar.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/Facebook/facebook.cbp b/protocols/Facebook/facebook.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/Facebook/facebook.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/Facebook/facebook.layout b/protocols/Facebook/facebook.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/Facebook/facebook.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/Facebook/proto_facebook/Proto_Facebook.cbp b/protocols/Facebook/proto_facebook/Proto_Facebook.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/Facebook/proto_facebook/Proto_Facebook.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/Facebook/proto_facebook/Proto_Facebook.layout b/protocols/Facebook/proto_facebook/Proto_Facebook.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/Facebook/proto_facebook/Proto_Facebook.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/Gadu-Gadu/gadugadu.cbp b/protocols/Gadu-Gadu/gadugadu.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/Gadu-Gadu/gadugadu.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/Gadu-Gadu/gadugadu.layout b/protocols/Gadu-Gadu/gadugadu.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/Gadu-Gadu/gadugadu.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/Gadu-Gadu/proto_gg/Proto_GG.cbp b/protocols/Gadu-Gadu/proto_gg/Proto_GG.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/Gadu-Gadu/proto_gg/Proto_GG.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/Gadu-Gadu/proto_gg/Proto_GG.layout b/protocols/Gadu-Gadu/proto_gg/Proto_GG.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/Gadu-Gadu/proto_gg/Proto_GG.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/ICQ-WIM/ICQ-WIM.cbp b/protocols/ICQ-WIM/ICQ-WIM.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/ICQ-WIM/ICQ-WIM.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/ICQ-WIM/ICQ-WIM.layout b/protocols/ICQ-WIM/ICQ-WIM.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/ICQ-WIM/ICQ-WIM.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/ICQ-WIM/proto_icq/Proto_ICQ.cbp b/protocols/ICQ-WIM/proto_icq/Proto_ICQ.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/ICQ-WIM/proto_icq/Proto_ICQ.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/ICQ-WIM/proto_icq/Proto_ICQ.layout b/protocols/ICQ-WIM/proto_icq/Proto_ICQ.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/ICQ-WIM/proto_icq/Proto_ICQ.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/IRCG/IRC.cbp b/protocols/IRCG/IRC.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/IRCG/IRC.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/IRCG/IRC.layout b/protocols/IRCG/IRC.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/IRCG/IRC.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/IRCG/proto_irc/Proto_IRC.cbp b/protocols/IRCG/proto_irc/Proto_IRC.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/IRCG/proto_irc/Proto_IRC.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/IRCG/proto_irc/Proto_IRC.layout b/protocols/IRCG/proto_irc/Proto_IRC.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/IRCG/proto_irc/Proto_IRC.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/JabberG/jabber.cbp b/protocols/JabberG/jabber.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/JabberG/jabber.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/JabberG/jabber.layout b/protocols/JabberG/jabber.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/JabberG/jabber.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/JabberG/jabber_xstatus/xStatus_Jabber.cbp b/protocols/JabberG/jabber_xstatus/xStatus_Jabber.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/JabberG/jabber_xstatus/xStatus_Jabber.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/JabberG/jabber_xstatus/xStatus_Jabber.layout b/protocols/JabberG/jabber_xstatus/xStatus_Jabber.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/JabberG/jabber_xstatus/xStatus_Jabber.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/protocols/JabberG/proto_jabber/Proto_Jabber.cbp b/protocols/JabberG/proto_jabber/Proto_Jabber.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/protocols/JabberG/proto_jabber/Proto_Jabber.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/protocols/JabberG/proto_jabber/Proto_Jabber.layout b/protocols/JabberG/proto_jabber/Proto_Jabber.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/protocols/JabberG/proto_jabber/Proto_Jabber.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stdautoaway/stdautoaway.cbp b/src/core/stdautoaway/stdautoaway.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stdautoaway/stdautoaway.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stdautoaway/stdautoaway.layout b/src/core/stdautoaway/stdautoaway.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stdautoaway/stdautoaway.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stdaway/stdaway.cbp b/src/core/stdaway/stdaway.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stdaway/stdaway.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stdaway/stdaway.layout b/src/core/stdaway/stdaway.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stdaway/stdaway.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stdclist/stdclist.cbp b/src/core/stdclist/stdclist.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stdclist/stdclist.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stdclist/stdclist.layout b/src/core/stdclist/stdclist.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stdclist/stdclist.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stdcrypt/stdcrypt.cbp b/src/core/stdcrypt/stdcrypt.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stdcrypt/stdcrypt.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stdcrypt/stdcrypt.layout b/src/core/stdcrypt/stdcrypt.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stdcrypt/stdcrypt.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stdemail/stdemail.cbp b/src/core/stdemail/stdemail.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stdemail/stdemail.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stdemail/stdemail.layout b/src/core/stdemail/stdemail.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stdemail/stdemail.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stdfile/stdfile.cbp b/src/core/stdfile/stdfile.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stdfile/stdfile.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stdfile/stdfile.layout b/src/core/stdfile/stdfile.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stdfile/stdfile.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stdmsg/stdmsg.cbp b/src/core/stdmsg/stdmsg.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stdmsg/stdmsg.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stdmsg/stdmsg.layout b/src/core/stdmsg/stdmsg.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stdmsg/stdmsg.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stdpopup/stdpopup.cbp b/src/core/stdpopup/stdpopup.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stdpopup/stdpopup.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stdpopup/stdpopup.layout b/src/core/stdpopup/stdpopup.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stdpopup/stdpopup.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stduihist/stduihist.cbp b/src/core/stduihist/stduihist.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stduihist/stduihist.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stduihist/stduihist.layout b/src/core/stduihist/stduihist.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stduihist/stduihist.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stduserinfo/stduserinfo.cbp b/src/core/stduserinfo/stduserinfo.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stduserinfo/stduserinfo.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stduserinfo/stduserinfo.layout b/src/core/stduserinfo/stduserinfo.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stduserinfo/stduserinfo.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/core/stduseronline/stduseronline.cbp b/src/core/stduseronline/stduseronline.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/core/stduseronline/stduseronline.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/core/stduseronline/stduseronline.layout b/src/core/stduseronline/stduseronline.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/core/stduseronline/stduseronline.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/icons/proto_metacontacts/Proto_MetaContacts.cbp b/src/icons/proto_metacontacts/Proto_MetaContacts.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/icons/proto_metacontacts/Proto_MetaContacts.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/icons/proto_metacontacts/Proto_MetaContacts.layout b/src/icons/proto_metacontacts/Proto_MetaContacts.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/icons/proto_metacontacts/Proto_MetaContacts.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/mir_app/mir_app.cbp b/src/mir_app/mir_app.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/mir_app/mir_app.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/mir_app/mir_app.layout b/src/mir_app/mir_app.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/mir_app/mir_app.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>
diff --git a/src/mir_core/main.cpp b/src/mir_core/main.cpp
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/src/mir_core/main.cpp
@@ -0,0 +1 @@
+
diff --git a/src/mir_core/mir_core.cbp b/src/mir_core/mir_core.cbp
new file mode 100644
index 0000000000..b24f650bb3
--- /dev/null
+++ b/src/mir_core/mir_core.cbp
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="Miranda core" />
+ <Option platforms="Unix;" />
+ <Option compiler="gcc" />
+ <Option virtualFolders="Sources/" />
+ <Build>
+ <Target title="Debug">
+ <Option output="../../codeblocks/bin/Debug/mir_core" prefix_auto="1" extension_auto="1" />
+ <Option object_output="../../codeblocks/obj/Debug/" />
+ <Option type="3" />
+ <Option compiler="gcc" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-m64" />
+ <Add option="-g" />
+ </Compiler>
+ <Linker>
+ <Add option="-m64" />
+ </Linker>
+ </Target>
+ <Target title="Release">
+ <Option output="../../codeblocks/bin/Release/mir_core" prefix_auto="1" extension_auto="1" />
+ <Option object_output="../../codeblocks/obj/Release/" />
+ <Option type="3" />
+ <Option compiler="gcc" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-fomit-frame-pointer" />
+ <Add option="-flto" />
+ <Add option="-Os" />
+ <Add option="-std=c++11" />
+ <Add option="-m64" />
+ </Compiler>
+ <Linker>
+ <Add option="-flto" />
+ <Add option="-s" />
+ <Add option="-m64" />
+ </Linker>
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-Wfatal-errors" />
+ <Add option="-Wall" />
+ <Add option="-fexceptions" />
+ <Add option="-DMIR_CORE_EXPORTS" />
+ <Add directory="../../include" />
+ </Compiler>
+ <Unit filename="src/binbuffer.cpp" />
+ <Unit filename="src/bitmaps.cpp" />
+ <Unit filename="src/db.cpp" />
+ <Unit filename="src/http.cpp" />
+ <Unit filename="src/lists.cpp" />
+ <Unit filename="src/logger.cpp" />
+ <Unit filename="src/md5.cpp" />
+ <Unit filename="src/memory.cpp" />
+ <Unit filename="src/miranda.h" />
+ <Unit filename="src/modules.cpp" />
+ <Unit filename="src/mstring.cpp" />
+ <Unit filename="src/sha1.cpp" />
+ <Unit filename="src/sha256.cpp" />
+ <Unit filename="src/stdafx.cxx" />
+ <Unit filename="src/stdafx.h" />
+ <Unit filename="src/tinyxml2.cpp" />
+ <Unit filename="src/tinyxml2.h" />
+ <Unit filename="src/tinyxml2_utils.cpp" />
+ <Unit filename="src/utf.cpp" />
+ <Unit filename="src/utils.cpp" />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/mir_core/mir_core.depend b/src/mir_core/mir_core.depend
new file mode 100644
index 0000000000..bd3a5c7130
--- /dev/null
+++ b/src/mir_core/mir_core.depend
@@ -0,0 +1,231 @@
+# depslib dependency file v1.0
+1634479263 source:/var/www/miranda-ng/src/mir_core/src/binbuffer.cpp
+ "stdafx.h"
+
+1636290589 /var/www/miranda-ng/src/mir_core/src/stdafx.h
+ <winsock2.h>
+ <ws2tcpip.h>
+ <windows.h>
+ <windowsx.h>
+ <shlobj.h>
+ <commctrl.h>
+ <ShellAPI.h>
+ <vssym32.h>
+ <Uxtheme.h>
+ <Richedit.h>
+ <Wtsapi32.h>
+ <process.h>
+ <io.h>
+ <direct.h>
+ <malloc.h>
+ <stdio.h>
+ <time.h>
+ <stdarg.h>
+ <stddef.h>
+ <limits.h>
+ <string.h>
+ <locale.h>
+ <m_system.h>
+ <m_database.h>
+ <m_db_int.h>
+ <newpluginapi.h>
+ <m_langpack.h>
+ <m_metacontacts.h>
+ <m_skin.h>
+ <m_icolib.h>
+ <m_netlib.h>
+ <m_timezones.h>
+ <m_protocols.h>
+ <m_button.h>
+ <m_gui.h>
+ <m_chat_int.h>
+ "miranda.h"
+ <m_xml.h>
+ <m_string.inl>
+
+1636282921 /var/www/miranda-ng/include/m_system.h
+ <m_core.h>
+ <m_string.h>
+
+1636291943 /var/www/miranda-ng/include/m_core.h
+ <sal.h>
+ <stdint.h>
+ <stdlib.h>
+ <m_types.h>
+
+1636292217 /var/www/miranda-ng/include/m_types.h
+ <wchar.h>
+ <netinet/in.h>
+
+1636282895 /var/www/miranda-ng/include/m_string.h
+ <stdio.h>
+ <string.h>
+ <mbstring.h>
+ <wchar.h>
+ <m_core.h>
+ <limits.h>
+
+1636283401 /var/www/miranda-ng/include/m_database.h
+ "m_system.h"
+ "m_utils.h"
+
+1634479262 /var/www/miranda-ng/include/m_utils.h
+ <stdio.h>
+ <m_system.h>
+ <m_string.h>
+ "m_system.h"
+
+1636283723 /var/www/miranda-ng/include/m_db_int.h
+ <m_core.h>
+
+1636284034 /var/www/miranda-ng/include/newpluginapi.h
+ <m_core.h>
+ <m_database.h>
+ <m_protocols.h>
+
+1634479262 /var/www/miranda-ng/include/m_protocols.h
+ "statusmodes.h"
+ <m_core.h>
+ <m_system.h>
+ <m_genmenu.h>
+
+1634479262 /var/www/miranda-ng/include/statusmodes.h
+
+1634479262 /var/www/miranda-ng/include/m_genmenu.h
+ <m_core.h>
+ <newpluginapi.h>
+
+1634479262 /var/www/miranda-ng/include/m_langpack.h
+ <m_core.h>
+
+1634479262 /var/www/miranda-ng/include/m_metacontacts.h
+ <m_core.h>
+
+1634479262 /var/www/miranda-ng/include/m_skin.h
+ <m_core.h>
+
+1634479262 /var/www/miranda-ng/include/m_icolib.h
+ <m_core.h>
+
+1636284288 /var/www/miranda-ng/include/m_netlib.h
+ "m_utils.h"
+
+1636284672 /var/www/miranda-ng/include/m_timezones.h
+ <m_core.h>
+
+1634479262 /var/www/miranda-ng/include/m_button.h
+
+1636286799 /var/www/miranda-ng/include/m_gui.h
+ <CommCtrl.h>
+ <m_system.h>
+ <m_protoint.h>
+ <m_clc.h>
+
+1636284756 /var/www/miranda-ng/include/m_protoint.h
+ <m_system.h>
+ <m_protosvc.h>
+ <m_database.h>
+ <m_genmenu.h>
+ <m_utils.h>
+
+1634479262 /var/www/miranda-ng/include/m_protosvc.h
+ "m_protocols.h"
+
+1636284822 /var/www/miranda-ng/include/m_clc.h
+
+1634479262 /var/www/miranda-ng/include/m_chat_int.h
+ <time.h>
+ <m_core.h>
+ <m_string.h>
+ <m_chat.h>
+ <m_gui.h>
+ <m_utils.h>
+
+1634479262 /var/www/miranda-ng/include/m_chat.h
+
+1636286911 /var/www/miranda-ng/src/mir_core/src/miranda.h
+
+1636278170 /var/www/miranda-ng/include/m_xml.h
+ <m_core.h>
+ "../src/mir_core/src/tinyxml2.h"
+
+1634479263 /var/www/miranda-ng/src/mir_core/src/tinyxml2.h
+ <ctype.h>
+ <limits.h>
+ <stdio.h>
+ <stdlib.h>
+ <string.h>
+ <stddef.h>
+ <cctype>
+ <climits>
+ <cstdio>
+ <cstdlib>
+ <cstring>
+ <stdint.h>
+ <android/log.h>
+ <assert.h>
+
+1636290281 /var/www/miranda-ng/include/m_string.inl
+
+1634479263 source:/var/www/miranda-ng/src/mir_core/src/lists.cpp
+ "stdafx.h"
+
+1634479263 source:/var/www/miranda-ng/src/mir_core/src/sha1.cpp
+ "stdafx.h"
+
+1634479263 source:/var/www/miranda-ng/src/mir_core/src/stdafx.cxx
+ "stdafx.h"
+
+1634479263 source:/var/www/miranda-ng/src/mir_core/src/tinyxml2.cpp
+ "stdafx.h"
+ <new>
+ <stddef.h>
+ <stdarg.h>
+ <cstddef>
+ <cstdarg>
+
+1636289969 source:/var/www/miranda-ng/src/mir_core/src/Linux/fileutil.cpp
+ "../stdafx.h"
+
+1634479263 source:/var/www/miranda-ng/src/mir_core/src/http.cpp
+ "stdafx.h"
+
+1636289767 source:/var/www/miranda-ng/src/mir_core/src/logger.cpp
+ "stdafx.h"
+
+1636290658 source:/var/www/miranda-ng/src/mir_core/src/md5.cpp
+ "stdafx.h"
+
+1636290256 source:/var/www/miranda-ng/src/mir_core/src/db.cpp
+ "stdafx.h"
+
+1636290951 source:/var/www/miranda-ng/src/mir_core/src/mstring.cpp
+ "stdafx.h"
+
+1636290966 source:/var/www/miranda-ng/src/mir_core/src/sha256.cpp
+ "stdafx.h"
+
+1636290782 source:/var/www/miranda-ng/src/mir_core/src/bitmaps.cpp
+ "stdafx.h"
+ <m_imgsrvc.h>
+
+1634479262 /var/www/miranda-ng/include/m_imgsrvc.h
+ "../libs/freeimage/src/FreeImage.h"
+ <m_core.h>
+
+1634479262 /var/www/miranda-ng/libs/freeimage/src/FreeImage.h
+ <wchar.h>
+ <inttypes.h>
+
+1636291741 source:/var/www/miranda-ng/src/mir_core/src/memory.cpp
+ "stdafx.h"
+
+1634479263 source:/var/www/miranda-ng/src/mir_core/src/tinyxml2_utils.cpp
+ "stdafx.h"
+
+1636291998 source:/var/www/miranda-ng/src/mir_core/src/utf.cpp
+ "stdafx.h"
+
+1636292418 source:/var/www/miranda-ng/src/mir_core/src/utils.cpp
+ "stdafx.h"
+
diff --git a/src/mir_core/mir_core.layout b/src/mir_core/mir_core.layout
new file mode 100644
index 0000000000..5ca32c1036
--- /dev/null
+++ b/src/mir_core/mir_core.layout
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug" />
+ <File name="src/stdafx.h" open="1" top="1" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+ <Cursor>
+ <Cursor1 position="1016" topLine="0" />
+ </Cursor>
+ </File>
+</CodeBlocks_layout_file>
diff --git a/src/mir_core/src/Linux/fileutil.cpp b/src/mir_core/src/Linux/fileutil.cpp
new file mode 100644
index 0000000000..e246219f46
--- /dev/null
+++ b/src/mir_core/src/Linux/fileutil.cpp
@@ -0,0 +1,23 @@
+/*
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+
+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 version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+
+MIR_CORE_DLL(FILE*) _wfopen(const wchar_t *pwszFileName, const wchar_t *pwszMode)
+{
+ return fopen(T2Utf(pwszFileName), T2Utf(pwszMode));
+}
diff --git a/src/mir_core/src/db.cpp b/src/mir_core/src/db.cpp
index 9f00db4387..11d28cf84a 100644
--- a/src/mir_core/src/db.cpp
+++ b/src/mir_core/src/db.cpp
@@ -1,533 +1,538 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-
-MIR_CORE_EXPORT MDatabaseCommon* g_pCurrDb = nullptr;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// database functions
-
-MIR_CORE_DLL(void) db_set_safety_mode(BOOL bNewMode)
-{
- if (g_pCurrDb)
- g_pCurrDb->SetCacheSafetyMode(bNewMode != 0);
-}
-
-MIR_CORE_DLL(int) db_get_contact_count(void)
-{
- return (g_pCurrDb) ? g_pCurrDb->GetContactCount() : 0;
-}
-
-MIR_CORE_DLL(MDatabaseCommon*) db_get_current()
-{
- return g_pCurrDb;
-}
-
-MIR_CORE_DLL(int) db_delete_module(MCONTACT hContact, const char *szModuleName)
-{
- return (g_pCurrDb) ? g_pCurrDb->DeleteModule(hContact, szModuleName) : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// contact functions
-
-MIR_CORE_DLL(MCONTACT) db_add_contact(void)
-{
- MCONTACT hNew = (g_pCurrDb) ? g_pCurrDb->AddContact() : 0;
- Netlib_Logf(nullptr, "New contact created: %d", hNew);
- return hNew;
-}
-
-MIR_CORE_DLL(int) db_delete_contact(MCONTACT hContact)
-{
- ptrW wszPhoto(db_get_wsa(hContact, "ContactPhoto", "File"));
- if (wszPhoto != NULL)
- DeleteFile(wszPhoto);
-
- Netlib_Logf(nullptr, "Contact deleted: %d", hContact);
- return (g_pCurrDb) ? g_pCurrDb->DeleteContact(hContact) : 0;
-}
-
-MIR_CORE_DLL(int) db_is_contact(MCONTACT hContact)
-{
- return (g_pCurrDb) ? g_pCurrDb->IsDbContact(hContact) : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// enumerators
-
-MIR_CORE_DLL(int) db_enum_modules(DBMODULEENUMPROC pFunc, void *param)
-{
- return (g_pCurrDb) ? g_pCurrDb->EnumModuleNames(pFunc, param) : 0;
-}
-
-MIR_CORE_DLL(int) db_enum_residents(DBMODULEENUMPROC pFunc, void *param)
-{
- return (g_pCurrDb) ? g_pCurrDb->EnumResidentSettings(pFunc, param) : 0;
-}
-
-EXTERN_C MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC pFunc, const char *szModule, void *param)
-{
- return (g_pCurrDb) ? g_pCurrDb->EnumContactSettings(hContact, pFunc, szModule, param) : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// getting data
-
-MIR_CORE_DLL(int) db_get_b(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue)
-{
- if (g_pCurrDb != nullptr) {
- DBVARIANT dbv;
- if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv))
- {
- switch(dbv.type) {
- case DBVT_BYTE: return dbv.bVal;
- case DBVT_WORD: return BYTE(dbv.wVal);
- case DBVT_DWORD: return BYTE(dbv.dVal);
- }
- g_pCurrDb->FreeVariant(&dbv);
- }
- }
- return errorValue;
-}
-
-MIR_CORE_DLL(int) db_get_w(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue)
-{
- if (g_pCurrDb != nullptr) {
- DBVARIANT dbv;
- if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) {
- switch(dbv.type) {
- case DBVT_BYTE: return dbv.bVal;
- case DBVT_WORD: return dbv.wVal;
- case DBVT_DWORD: return WORD(dbv.dVal);
- }
- g_pCurrDb->FreeVariant(&dbv);
- }
- }
- return errorValue;
-}
-
-MIR_CORE_DLL(DWORD) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD errorValue)
-{
- if (g_pCurrDb != nullptr) {
- DBVARIANT dbv;
- if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) {
- switch(dbv.type) {
- case DBVT_BYTE: return dbv.bVal;
- case DBVT_WORD: return dbv.wVal;
- case DBVT_DWORD: return dbv.dVal;
- }
- g_pCurrDb->FreeVariant(&dbv);
- }
- }
-
- return errorValue;
-}
-
-MIR_CORE_DLL(INT_PTR) db_get(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- return g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_get_s(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv, const int nType)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- dbv->type = (BYTE)nType;
- return g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, dbv);
-}
-
-MIR_CORE_DLL(char*) db_get_sa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue)
-{
- if (g_pCurrDb) {
- DBVARIANT dbv = { DBVT_ASCIIZ };
- if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return dbv.pszVal;
- }
-
- return (szValue == nullptr) ? nullptr : mir_strdup(szValue);
-}
-
-MIR_CORE_DLL(char*) db_get_utfa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue)
-{
- if (g_pCurrDb) {
- DBVARIANT dbv = { DBVT_UTF8 };
- if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return dbv.pszVal;
- }
-
- return (szValue == nullptr) ? nullptr : mir_strdup(szValue);
-}
-
-MIR_CORE_DLL(wchar_t*) db_get_wsa(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue)
-{
- if (g_pCurrDb) {
- DBVARIANT dbv = { DBVT_WCHAR };
- if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return dbv.pwszVal;
- }
-
- return (szValue == nullptr) ? nullptr : mir_wstrdup(szValue);
-}
-
-MIR_CORE_DLL(CMStringA) db_get_sm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const char *szValue)
-{
- if (g_pCurrDb == nullptr)
- return (szValue == nullptr) ? CMStringA() : CMStringA(szValue);
-
- DBVARIANT dbv = { DBVT_ASCIIZ };
- if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return (szValue == nullptr) ? CMStringA() : CMStringA(szValue);
-
- return CMStringA(ptrA(dbv.pszVal));
-}
-
-MIR_CORE_DLL(CMStringW) db_get_wsm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const wchar_t *szValue)
-{
- if (g_pCurrDb == nullptr)
- return (szValue == nullptr) ? CMStringW() : CMStringW(szValue);
-
- DBVARIANT dbv = { DBVT_WCHAR };
- if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
- return (szValue == nullptr) ? CMStringW() : CMStringW(szValue);
-
- return CMStringW(ptrW(dbv.pwszVal));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// getting static data
-
-MIR_CORE_DLL(int) db_get_static(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_ASCIIZ;
- dbv.pszVal = pDest;
- dbv.cchVal = cbDest;
- return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(int) db_get_static_utf(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_UTF8;
- dbv.pszVal = pDest;
- dbv.cchVal = cbDest;
- return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
-}
-
-MIR_CORE_DLL(int) db_get_wstatic(MCONTACT hContact, const char *szModule, const char *szSetting, wchar_t *pDest, int cbDest)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- DBVARIANT dbv;
- dbv.type = DBVT_WCHAR;
- dbv.pwszVal = pDest;
- dbv.cchVal = cbDest;
- return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// setting data
-
-MIR_CORE_DLL(INT_PTR) db_set(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBCONTACTWRITESETTING cws;
- cws.szModule = szModule;
- cws.szSetting = szSetting;
- cws.value = *dbv;
- return g_pCurrDb->WriteContactSetting(hContact, &cws);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_b(MCONTACT hContact, const char *szModule, const char *szSetting, BYTE val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBCONTACTWRITESETTING cws;
- cws.szModule = szModule;
- cws.szSetting = szSetting;
- cws.value.type = DBVT_BYTE;
- cws.value.bVal = val;
- return g_pCurrDb->WriteContactSetting(hContact, &cws);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, WORD val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBCONTACTWRITESETTING cws;
- cws.szModule = szModule;
- cws.szSetting = szSetting;
- cws.value.type = DBVT_WORD;
- cws.value.wVal = val;
- return g_pCurrDb->WriteContactSetting(hContact, &cws);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBCONTACTWRITESETTING cws;
- cws.szModule = szModule;
- cws.szSetting = szSetting;
- cws.value.type = DBVT_DWORD;
- cws.value.dVal = val;
- return g_pCurrDb->WriteContactSetting(hContact, &cws);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_s(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBCONTACTWRITESETTING cws;
- cws.szModule = szModule;
- cws.szSetting = szSetting;
- cws.value.type = DBVT_ASCIIZ;
- cws.value.pszVal = (char*)(val == nullptr ? "" : val);
- return g_pCurrDb->WriteContactSetting(hContact, &cws);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_ws(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBCONTACTWRITESETTING cws;
- cws.szModule = szModule;
- cws.szSetting = szSetting;
- cws.value.type = DBVT_WCHAR;
- cws.value.pwszVal = (wchar_t*)(val == nullptr ? L"" : val);
- return g_pCurrDb->WriteContactSetting(hContact, &cws);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_utf(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBCONTACTWRITESETTING cws;
- cws.szModule = szModule;
- cws.szSetting = szSetting;
- cws.value.type = DBVT_UTF8;
- cws.value.pszVal = (char*)(val == nullptr ? "" : val);
- return g_pCurrDb->WriteContactSetting(hContact, &cws);
-}
-
-MIR_CORE_DLL(INT_PTR) db_set_blob(MCONTACT hContact, const char *szModule, const char *szSetting, void *val, unsigned len)
-{
- if (g_pCurrDb == nullptr) return 1;
-
- DBCONTACTWRITESETTING cws;
- cws.szModule = szModule;
- cws.szSetting = szSetting;
- cws.value.type = DBVT_BLOB;
- cws.value.cpbVal = (WORD)len;
- cws.value.pbVal = (unsigned char*)val;
- return g_pCurrDb->WriteContactSetting(hContact, &cws);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// events
-
-MIR_CORE_DLL(MEVENT) db_event_add(MCONTACT hContact, const DBEVENTINFO *dbei)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->AddEvent(hContact, dbei);
-}
-
-MIR_CORE_DLL(int) db_event_count(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventCount(hContact);
-}
-
-MIR_CORE_DLL(int) db_event_delete(MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->DeleteEvent(hDbEvent);
-}
-
-MIR_CORE_DLL(int) db_event_edit(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO *dbei)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EditEvent(hContact, hDbEvent, dbei);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_first(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstEvent(hContact);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_firstUnread(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstUnreadEvent(hContact);
-}
-
-MIR_CORE_DLL(int) db_event_get(MEVENT hDbEvent, DBEVENTINFO *dbei)
-{
- return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->GetEvent(hDbEvent, dbei);
-}
-
-MIR_CORE_DLL(int) db_event_getBlobSize(MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetBlobSize(hDbEvent);
-}
-
-MIR_CORE_DLL(MCONTACT) db_event_getContact(MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventContact(hDbEvent);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_last(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindLastEvent(hContact);
-}
-
-MIR_CORE_DLL(int) db_event_markRead(MCONTACT hContact, MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->MarkEventRead(hContact, hDbEvent);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_next(MCONTACT hContact, MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindNextEvent(hContact, hDbEvent);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_prev(MCONTACT hContact, MEVENT hDbEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindPrevEvent(hContact, hDbEvent);
-}
-
-MIR_CORE_DLL(MEVENT) db_event_getById(const char *szModule, const char *szId)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventById(szModule, szId);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// event cursors
-
-DB::EventCursor::~EventCursor()
-{
-}
-
-MIR_CORE_DLL(DB::EventCursor*) DB::Events(MCONTACT hContact, MEVENT iStartEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursor(hContact, iStartEvent);
-}
-
-MIR_CORE_DLL(DB::EventCursor*) DB::EventsRev(MCONTACT hContact, MEVENT iStartEvent)
-{
- return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursorRev(hContact, iStartEvent);
-}
-
-DB::ECPTR::ECPTR(EventCursor *_pCursor) :
- m_cursor(_pCursor),
- m_prevFetched(-1),
- m_currEvent(0)
-{
-}
-
-DB::ECPTR::~ECPTR()
-{
- delete m_cursor;
-}
-
-void DB::ECPTR::DeleteEvent()
-{
- m_prevFetched = m_cursor->FetchNext();
- db_event_delete(m_currEvent);
-}
-
-MEVENT DB::ECPTR::FetchNext()
-{
- if (m_prevFetched != -1) {
- m_currEvent = m_prevFetched;
- m_prevFetched = -1;
- }
- else m_currEvent = m_cursor->FetchNext();
-
- return m_currEvent;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// misc functions
-
-MIR_CORE_DLL(INT_PTR) db_free(DBVARIANT *dbv)
-{
- return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->FreeVariant(dbv);
-}
-
-MIR_CORE_DLL(INT_PTR) db_unset(MCONTACT hContact, const char *szModule, const char *szSetting)
-{
- if (g_pCurrDb == nullptr)
- return 1;
-
- return g_pCurrDb->DeleteContactSetting(hContact, szModule, szSetting);
-}
-
-MIR_CORE_DLL(DBCachedContact*) db_get_contact(MCONTACT hContact)
-{
- return (g_pCurrDb == nullptr) ? nullptr : g_pCurrDb->getCache()->GetCachedContact(hContact);
-}
-
-MIR_CORE_DLL(MCONTACT) db_find_first(const char *szProto)
-{
- return (g_pCurrDb == nullptr) ? NULL : g_pCurrDb->FindFirstContact(szProto);
-}
-
-MIR_CORE_DLL(MCONTACT) db_find_next(MCONTACT hContact, const char *szProto)
-{
- return (g_pCurrDb == nullptr) ? NULL : g_pCurrDb->FindNextContact(hContact, szProto);
-}
-
-MIR_CORE_DLL(void) db_setCurrent(MDatabaseCommon *_db)
-{
- g_pCurrDb = _db;
- if (g_pCurrDb == nullptr)
- return;
-
- // try to get the langpack's name from a profile
- ptrW langpack(db_get_wsa(0, "Langpack", "Current"));
- if (langpack && langpack[0] != '\0')
- LoadLangPack(langpack);
- else
- GetDefaultLang();
-}
-
-MIR_CORE_DLL(BOOL) db_set_resident(const char *szModule, const char *szService, BOOL bEnable)
-{
- if (g_pCurrDb == nullptr || szModule == nullptr || szService == nullptr)
- return FALSE;
-
- char str[MAXMODULELABELLENGTH * 2];
- mir_snprintf(str, "%s/%s", szModule, szService);
- return g_pCurrDb->SetSettingResident(bEnable, str);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+
+MIR_CORE_EXPORT MDatabaseCommon* g_pCurrDb = nullptr;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// database functions
+
+MIR_CORE_DLL(void) db_set_safety_mode(BOOL bNewMode)
+{
+ if (g_pCurrDb)
+ g_pCurrDb->SetCacheSafetyMode(bNewMode != 0);
+}
+
+MIR_CORE_DLL(int) db_get_contact_count(void)
+{
+ return (g_pCurrDb) ? g_pCurrDb->GetContactCount() : 0;
+}
+
+MIR_CORE_DLL(MDatabaseCommon*) db_get_current()
+{
+ return g_pCurrDb;
+}
+
+MIR_CORE_DLL(int) db_delete_module(MCONTACT hContact, const char *szModuleName)
+{
+ return (g_pCurrDb) ? g_pCurrDb->DeleteModule(hContact, szModuleName) : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// contact functions
+
+MIR_CORE_DLL(MCONTACT) db_add_contact(void)
+{
+ MCONTACT hNew = (g_pCurrDb) ? g_pCurrDb->AddContact() : 0;
+ Netlib_Logf(nullptr, "New contact created: %d", hNew);
+ return hNew;
+}
+
+MIR_CORE_DLL(int) db_delete_contact(MCONTACT hContact)
+{
+ ptrW wszPhoto(db_get_wsa(hContact, "ContactPhoto", "File"));
+ if (wszPhoto != NULL) {
+ #ifdef _MSC_VER
+ DeleteFileW(wszPhoto);
+ #else
+ remove(T2Utf(wszPhoto));
+ #endif
+ }
+
+ Netlib_Logf(nullptr, "Contact deleted: %d", hContact);
+ return (g_pCurrDb) ? g_pCurrDb->DeleteContact(hContact) : 0;
+}
+
+MIR_CORE_DLL(int) db_is_contact(MCONTACT hContact)
+{
+ return (g_pCurrDb) ? g_pCurrDb->IsDbContact(hContact) : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// enumerators
+
+MIR_CORE_DLL(int) db_enum_modules(DBMODULEENUMPROC pFunc, void *param)
+{
+ return (g_pCurrDb) ? g_pCurrDb->EnumModuleNames(pFunc, param) : 0;
+}
+
+MIR_CORE_DLL(int) db_enum_residents(DBMODULEENUMPROC pFunc, void *param)
+{
+ return (g_pCurrDb) ? g_pCurrDb->EnumResidentSettings(pFunc, param) : 0;
+}
+
+EXTERN_C MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC pFunc, const char *szModule, void *param)
+{
+ return (g_pCurrDb) ? g_pCurrDb->EnumContactSettings(hContact, pFunc, szModule, param) : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// getting data
+
+MIR_CORE_DLL(int) db_get_b(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue)
+{
+ if (g_pCurrDb != nullptr) {
+ DBVARIANT dbv;
+ if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv))
+ {
+ switch(dbv.type) {
+ case DBVT_BYTE: return dbv.bVal;
+ case DBVT_WORD: return BYTE(dbv.wVal);
+ case DBVT_DWORD: return BYTE(dbv.dVal);
+ }
+ g_pCurrDb->FreeVariant(&dbv);
+ }
+ }
+ return errorValue;
+}
+
+MIR_CORE_DLL(int) db_get_w(MCONTACT hContact, const char *szModule, const char *szSetting, int errorValue)
+{
+ if (g_pCurrDb != nullptr) {
+ DBVARIANT dbv;
+ if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) {
+ switch(dbv.type) {
+ case DBVT_BYTE: return dbv.bVal;
+ case DBVT_WORD: return dbv.wVal;
+ case DBVT_DWORD: return WORD(dbv.dVal);
+ }
+ g_pCurrDb->FreeVariant(&dbv);
+ }
+ }
+ return errorValue;
+}
+
+MIR_CORE_DLL(DWORD) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD errorValue)
+{
+ if (g_pCurrDb != nullptr) {
+ DBVARIANT dbv;
+ if (!g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, &dbv)) {
+ switch(dbv.type) {
+ case DBVT_BYTE: return dbv.bVal;
+ case DBVT_WORD: return dbv.wVal;
+ case DBVT_DWORD: return dbv.dVal;
+ }
+ g_pCurrDb->FreeVariant(&dbv);
+ }
+ }
+
+ return errorValue;
+}
+
+MIR_CORE_DLL(INT_PTR) db_get(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ return g_pCurrDb->GetContactSetting(hContact, szModule, szSetting, dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_get_s(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv, const int nType)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ dbv->type = (BYTE)nType;
+ return g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, dbv);
+}
+
+MIR_CORE_DLL(char*) db_get_sa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue)
+{
+ if (g_pCurrDb) {
+ DBVARIANT dbv = { DBVT_ASCIIZ };
+ if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return dbv.pszVal;
+ }
+
+ return (szValue == nullptr) ? nullptr : mir_strdup(szValue);
+}
+
+MIR_CORE_DLL(char*) db_get_utfa(MCONTACT hContact, const char *szModule, const char *szSetting, const char *szValue)
+{
+ if (g_pCurrDb) {
+ DBVARIANT dbv = { DBVT_UTF8 };
+ if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return dbv.pszVal;
+ }
+
+ return (szValue == nullptr) ? nullptr : mir_strdup(szValue);
+}
+
+MIR_CORE_DLL(wchar_t*) db_get_wsa(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *szValue)
+{
+ if (g_pCurrDb) {
+ DBVARIANT dbv = { DBVT_WCHAR };
+ if (!g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return dbv.pwszVal;
+ }
+
+ return (szValue == nullptr) ? nullptr : mir_wstrdup(szValue);
+}
+
+MIR_CORE_DLL(CMStringA) db_get_sm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const char *szValue)
+{
+ if (g_pCurrDb == nullptr)
+ return (szValue == nullptr) ? CMStringA() : CMStringA(szValue);
+
+ DBVARIANT dbv = { DBVT_ASCIIZ };
+ if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return (szValue == nullptr) ? CMStringA() : CMStringA(szValue);
+
+ return CMStringA(ptrA(dbv.pszVal).get());
+}
+
+MIR_CORE_DLL(CMStringW) db_get_wsm(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, const wchar_t *szValue)
+{
+ if (g_pCurrDb == nullptr)
+ return (szValue == nullptr) ? CMStringW() : CMStringW(szValue);
+
+ DBVARIANT dbv = { DBVT_WCHAR };
+ if (g_pCurrDb->GetContactSettingStr(hContact, szModule, szSetting, &dbv))
+ return (szValue == nullptr) ? CMStringW() : CMStringW(szValue);
+
+ return CMStringW(ptrW(dbv.pwszVal).get());
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// getting static data
+
+MIR_CORE_DLL(int) db_get_static(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = pDest;
+ dbv.cchVal = cbDest;
+ return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(int) db_get_static_utf(MCONTACT hContact, const char *szModule, const char *szSetting, char *pDest, int cbDest)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_UTF8;
+ dbv.pszVal = pDest;
+ dbv.cchVal = cbDest;
+ return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
+}
+
+MIR_CORE_DLL(int) db_get_wstatic(MCONTACT hContact, const char *szModule, const char *szSetting, wchar_t *pDest, int cbDest)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ DBVARIANT dbv;
+ dbv.type = DBVT_WCHAR;
+ dbv.pwszVal = pDest;
+ dbv.cchVal = cbDest;
+ return g_pCurrDb->GetContactSettingStatic(hContact, szModule, szSetting, &dbv);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// setting data
+
+MIR_CORE_DLL(INT_PTR) db_set(MCONTACT hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBCONTACTWRITESETTING cws;
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value = *dbv;
+ return g_pCurrDb->WriteContactSetting(hContact, &cws);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_b(MCONTACT hContact, const char *szModule, const char *szSetting, BYTE val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBCONTACTWRITESETTING cws;
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value.type = DBVT_BYTE;
+ cws.value.bVal = val;
+ return g_pCurrDb->WriteContactSetting(hContact, &cws);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, WORD val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBCONTACTWRITESETTING cws;
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value.type = DBVT_WORD;
+ cws.value.wVal = val;
+ return g_pCurrDb->WriteContactSetting(hContact, &cws);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, DWORD val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBCONTACTWRITESETTING cws;
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value.type = DBVT_DWORD;
+ cws.value.dVal = val;
+ return g_pCurrDb->WriteContactSetting(hContact, &cws);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_s(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBCONTACTWRITESETTING cws;
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value.type = DBVT_ASCIIZ;
+ cws.value.pszVal = (char*)(val == nullptr ? "" : val);
+ return g_pCurrDb->WriteContactSetting(hContact, &cws);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_ws(MCONTACT hContact, const char *szModule, const char *szSetting, const wchar_t *val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBCONTACTWRITESETTING cws;
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value.type = DBVT_WCHAR;
+ cws.value.pwszVal = (wchar_t*)(val == nullptr ? L"" : val);
+ return g_pCurrDb->WriteContactSetting(hContact, &cws);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_utf(MCONTACT hContact, const char *szModule, const char *szSetting, const char *val)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBCONTACTWRITESETTING cws;
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value.type = DBVT_UTF8;
+ cws.value.pszVal = (char*)(val == nullptr ? "" : val);
+ return g_pCurrDb->WriteContactSetting(hContact, &cws);
+}
+
+MIR_CORE_DLL(INT_PTR) db_set_blob(MCONTACT hContact, const char *szModule, const char *szSetting, void *val, unsigned len)
+{
+ if (g_pCurrDb == nullptr) return 1;
+
+ DBCONTACTWRITESETTING cws;
+ cws.szModule = szModule;
+ cws.szSetting = szSetting;
+ cws.value.type = DBVT_BLOB;
+ cws.value.cpbVal = (WORD)len;
+ cws.value.pbVal = (unsigned char*)val;
+ return g_pCurrDb->WriteContactSetting(hContact, &cws);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// events
+
+MIR_CORE_DLL(MEVENT) db_event_add(MCONTACT hContact, const DBEVENTINFO *dbei)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->AddEvent(hContact, dbei);
+}
+
+MIR_CORE_DLL(int) db_event_count(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventCount(hContact);
+}
+
+MIR_CORE_DLL(int) db_event_delete(MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->DeleteEvent(hDbEvent);
+}
+
+MIR_CORE_DLL(int) db_event_edit(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO *dbei)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EditEvent(hContact, hDbEvent, dbei);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_first(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstEvent(hContact);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_firstUnread(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindFirstUnreadEvent(hContact);
+}
+
+MIR_CORE_DLL(int) db_event_get(MEVENT hDbEvent, DBEVENTINFO *dbei)
+{
+ return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->GetEvent(hDbEvent, dbei);
+}
+
+MIR_CORE_DLL(int) db_event_getBlobSize(MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetBlobSize(hDbEvent);
+}
+
+MIR_CORE_DLL(MCONTACT) db_event_getContact(MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventContact(hDbEvent);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_last(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindLastEvent(hContact);
+}
+
+MIR_CORE_DLL(int) db_event_markRead(MCONTACT hContact, MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->MarkEventRead(hContact, hDbEvent);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_next(MCONTACT hContact, MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindNextEvent(hContact, hDbEvent);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_prev(MCONTACT hContact, MEVENT hDbEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->FindPrevEvent(hContact, hDbEvent);
+}
+
+MIR_CORE_DLL(MEVENT) db_event_getById(const char *szModule, const char *szId)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->GetEventById(szModule, szId);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// event cursors
+
+DB::EventCursor::~EventCursor()
+{
+}
+
+MIR_CORE_DLL(DB::EventCursor*) DB::Events(MCONTACT hContact, MEVENT iStartEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursor(hContact, iStartEvent);
+}
+
+MIR_CORE_DLL(DB::EventCursor*) DB::EventsRev(MCONTACT hContact, MEVENT iStartEvent)
+{
+ return (g_pCurrDb == nullptr) ? 0 : g_pCurrDb->EventCursorRev(hContact, iStartEvent);
+}
+
+DB::ECPTR::ECPTR(EventCursor *_pCursor) :
+ m_cursor(_pCursor),
+ m_prevFetched(-1),
+ m_currEvent(0)
+{
+}
+
+DB::ECPTR::~ECPTR()
+{
+ delete m_cursor;
+}
+
+void DB::ECPTR::DeleteEvent()
+{
+ m_prevFetched = m_cursor->FetchNext();
+ db_event_delete(m_currEvent);
+}
+
+MEVENT DB::ECPTR::FetchNext()
+{
+ if (m_prevFetched != -1) {
+ m_currEvent = m_prevFetched;
+ m_prevFetched = -1;
+ }
+ else m_currEvent = m_cursor->FetchNext();
+
+ return m_currEvent;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// misc functions
+
+MIR_CORE_DLL(INT_PTR) db_free(DBVARIANT *dbv)
+{
+ return (g_pCurrDb == nullptr) ? 1 : g_pCurrDb->FreeVariant(dbv);
+}
+
+MIR_CORE_DLL(INT_PTR) db_unset(MCONTACT hContact, const char *szModule, const char *szSetting)
+{
+ if (g_pCurrDb == nullptr)
+ return 1;
+
+ return g_pCurrDb->DeleteContactSetting(hContact, szModule, szSetting);
+}
+
+MIR_CORE_DLL(DBCachedContact*) db_get_contact(MCONTACT hContact)
+{
+ return (g_pCurrDb == nullptr) ? nullptr : g_pCurrDb->getCache()->GetCachedContact(hContact);
+}
+
+MIR_CORE_DLL(MCONTACT) db_find_first(const char *szProto)
+{
+ return (g_pCurrDb == nullptr) ? NULL : g_pCurrDb->FindFirstContact(szProto);
+}
+
+MIR_CORE_DLL(MCONTACT) db_find_next(MCONTACT hContact, const char *szProto)
+{
+ return (g_pCurrDb == nullptr) ? NULL : g_pCurrDb->FindNextContact(hContact, szProto);
+}
+
+MIR_CORE_DLL(void) db_setCurrent(MDatabaseCommon *_db)
+{
+ g_pCurrDb = _db;
+ if (g_pCurrDb == nullptr)
+ return;
+
+ // try to get the langpack's name from a profile
+ ptrW langpack(db_get_wsa(0, "Langpack", "Current"));
+ if (langpack && langpack[0] != '\0')
+ LoadLangPack(langpack);
+ else
+ GetDefaultLang();
+}
+
+MIR_CORE_DLL(BOOL) db_set_resident(const char *szModule, const char *szService, BOOL bEnable)
+{
+ if (g_pCurrDb == nullptr || szModule == nullptr || szService == nullptr)
+ return FALSE;
+
+ char str[MAXMODULELABELLENGTH * 2];
+ mir_snprintf(str, "%s/%s", szModule, szService);
+ return g_pCurrDb->SetSettingResident(bEnable, str);
+}
diff --git a/src/mir_core/src/logger.cpp b/src/mir_core/src/logger.cpp
index c6a1681139..30244e45e4 100644
--- a/src/mir_core/src/logger.cpp
+++ b/src/mir_core/src/logger.cpp
@@ -1,222 +1,202 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-
-#define SECRET_SIGNATURE 0x87654321
-
-struct Logger
-{
- Logger(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFilename, unsigned options) :
- m_name(mir_strdup(pszName)),
- m_descr(mir_wstrdup(ptszDescr)),
- m_fileName(mir_wstrdup(ptszFilename)),
- m_options(options),
- m_signature(SECRET_SIGNATURE),
- m_out(nullptr),
- m_lastwrite(0)
- {
- }
-
- ~Logger()
- {
- if (m_out)
- fclose(m_out);
- }
-
- int m_signature;
- ptrA m_name;
- ptrW m_fileName, m_descr;
- FILE *m_out;
- __int64 m_lastwrite;
- unsigned m_options;
- mir_cs m_cs;
-};
-
-static int CompareLoggers(const Logger *p1, const Logger *p2)
-{ return strcmp(p1->m_name, p2->m_name);
-}
-
-static OBJLIST<Logger> arLoggers(1, CompareLoggers);
-
-static __int64 llIdlePeriod;
-
-void InitLogs()
-{
- LARGE_INTEGER li;
- QueryPerformanceFrequency(&li);
- llIdlePeriod = li.QuadPart;
-}
-
-void UninitLogs()
-{
- arLoggers.destroy();
-}
-
-void CheckLogs()
-{
- LARGE_INTEGER li;
- QueryPerformanceCounter(&li);
-
- for (auto &p : arLoggers) {
- mir_cslock lck(p->m_cs);
- if (p->m_out && li.QuadPart - p->m_lastwrite > llIdlePeriod) {
- fclose(p->m_out);
- p->m_out = nullptr;
- }
- else fflush(p->m_out);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(HANDLE) mir_createLog(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFile, unsigned options)
-{
- if (ptszFile == nullptr)
- return nullptr;
-
- Logger *result = new Logger(pszName, ptszDescr, ptszFile, options);
- if (result == nullptr)
- return nullptr;
-
- int idx = arLoggers.getIndex(result);
- if (idx != -1) {
- delete result;
- return &arLoggers[idx];
- }
-
- FILE *fp = _wfopen(ptszFile, L"ab");
- if (fp == nullptr)
- CreatePathToFileW(ptszFile);
- else
- fclose(fp);
-
- DeleteFile(ptszFile);
- arLoggers.insert(result);
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-static Logger* prepareLogger(HANDLE hLogger)
-{
- if (hLogger == nullptr)
- return nullptr;
-
- Logger *p = (Logger*)hLogger;
- return (p->m_signature == SECRET_SIGNATURE) ? p : nullptr;
-}
-
-MIR_CORE_DLL(void) mir_closeLog(HANDLE hLogger)
-{
- Logger *p = prepareLogger(hLogger);
- if (p != nullptr)
- arLoggers.remove(p);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_C_CORE_DLL(int) mir_writeLogA(HANDLE hLogger, const char *format, ...)
-{
- Logger *p = prepareLogger(hLogger);
- if (p == nullptr)
- return 1;
-
- mir_cslock lck(p->m_cs);
- if (p->m_out == nullptr)
- if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
- return 2;
-
- va_list args;
- va_start(args, format);
- vfprintf(p->m_out, format, args);
- va_end(args);
-
- LARGE_INTEGER li;
- QueryPerformanceCounter(&li);
- p->m_lastwrite = li.QuadPart;
- return 0;
-}
-
-MIR_C_CORE_DLL(int) mir_writeLogW(HANDLE hLogger, const wchar_t *format, ...)
-{
- Logger *p = prepareLogger(hLogger);
- if (p == nullptr)
- return 1;
-
- mir_cslock lck(p->m_cs);
- if (p->m_out == nullptr)
- if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
- return 2;
-
- va_list args;
- va_start(args, format);
- vfwprintf(p->m_out, format, args);
- va_end(args);
-
- LARGE_INTEGER li;
- QueryPerformanceCounter(&li);
- p->m_lastwrite = li.QuadPart;
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) mir_writeLogVA(HANDLE hLogger, const char *format, va_list args)
-{
- Logger *p = prepareLogger(hLogger);
- if (p == nullptr)
- return 1;
-
- mir_cslock lck(p->m_cs);
- if (p->m_out == nullptr)
- if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
- return 2;
-
- vfprintf(p->m_out, format, args);
-
- LARGE_INTEGER li;
- QueryPerformanceCounter(&li);
- p->m_lastwrite = li.QuadPart;
- return 0;
-}
-
-MIR_CORE_DLL(int) mir_writeLogVW(HANDLE hLogger, const wchar_t *format, va_list args)
-{
- Logger *p = prepareLogger(hLogger);
- if (p == nullptr)
- return 1;
-
- mir_cslock lck(p->m_cs);
- if (p->m_out == nullptr)
- if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
- return 2;
-
- vfwprintf(p->m_out, format, args);
-
- LARGE_INTEGER li;
- QueryPerformanceCounter(&li);
- p->m_lastwrite = li.QuadPart;
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+
+#define SECRET_SIGNATURE 0x87654321
+
+struct Logger
+{
+ Logger(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFilename, unsigned options) :
+ m_name(mir_strdup(pszName)),
+ m_descr(mir_wstrdup(ptszDescr)),
+ m_fileName(mir_wstrdup(ptszFilename)),
+ m_options(options),
+ m_signature(SECRET_SIGNATURE),
+ m_out(nullptr),
+ m_lastwrite(0)
+ {
+ }
+
+ ~Logger()
+ {
+ if (m_out)
+ fclose(m_out);
+ }
+
+ int m_signature;
+ ptrA m_name;
+ ptrW m_fileName, m_descr;
+ FILE *m_out;
+ __int64_t m_lastwrite;
+ unsigned m_options;
+ mir_cs m_cs;
+};
+
+static int CompareLoggers(const Logger *p1, const Logger *p2)
+{ return strcmp(p1->m_name, p2->m_name);
+}
+
+static OBJLIST<Logger> arLoggers(1, CompareLoggers);
+
+void InitLogs()
+{
+}
+
+void UninitLogs()
+{
+ arLoggers.destroy();
+}
+
+void CheckLogs()
+{
+ time_t tm = time(0);
+
+ for (auto &p : arLoggers) {
+ mir_cslock lck(p->m_cs);
+ if (p->m_out && tm - p->m_lastwrite > 5) {
+ fclose(p->m_out);
+ p->m_out = nullptr;
+ }
+ else fflush(p->m_out);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(HANDLE) mir_createLog(const char* pszName, const wchar_t *ptszDescr, const wchar_t *ptszFile, unsigned options)
+{
+ if (ptszFile == nullptr)
+ return nullptr;
+
+ Logger *result = new Logger(pszName, ptszDescr, ptszFile, options);
+ if (result == nullptr)
+ return nullptr;
+
+ int idx = arLoggers.getIndex(result);
+ if (idx != -1) {
+ delete result;
+ return &arLoggers[idx];
+ }
+
+ CreatePathToFileW(ptszFile);
+ arLoggers.insert(result);
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+static Logger* prepareLogger(HANDLE hLogger)
+{
+ if (hLogger == nullptr)
+ return nullptr;
+
+ Logger *p = (Logger*)hLogger;
+ return (p->m_signature == SECRET_SIGNATURE) ? p : nullptr;
+}
+
+MIR_CORE_DLL(void) mir_closeLog(HANDLE hLogger)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p != nullptr)
+ arLoggers.remove(p);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_C_CORE_DLL(int) mir_writeLogA(HANDLE hLogger, const char *format, ...)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p == nullptr)
+ return 1;
+
+ mir_cslock lck(p->m_cs);
+ if (p->m_out == nullptr)
+ if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
+ return 2;
+
+ va_list args;
+ va_start(args, format);
+ vfprintf(p->m_out, format, args);
+ va_end(args);
+
+ p->m_lastwrite = time(0);
+ return 0;
+}
+
+MIR_C_CORE_DLL(int) mir_writeLogW(HANDLE hLogger, const wchar_t *format, ...)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p == nullptr)
+ return 1;
+
+ mir_cslock lck(p->m_cs);
+ if (p->m_out == nullptr)
+ if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
+ return 2;
+
+ va_list args;
+ va_start(args, format);
+ vfwprintf(p->m_out, format, args);
+ va_end(args);
+
+ p->m_lastwrite = time(0);
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) mir_writeLogVA(HANDLE hLogger, const char *format, va_list args)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p == nullptr)
+ return 1;
+
+ mir_cslock lck(p->m_cs);
+ if (p->m_out == nullptr)
+ if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
+ return 2;
+
+ vfprintf(p->m_out, format, args);
+
+ p->m_lastwrite = time(0);
+ return 0;
+}
+
+MIR_CORE_DLL(int) mir_writeLogVW(HANDLE hLogger, const wchar_t *format, va_list args)
+{
+ Logger *p = prepareLogger(hLogger);
+ if (p == nullptr)
+ return 1;
+
+ mir_cslock lck(p->m_cs);
+ if (p->m_out == nullptr)
+ if ((p->m_out = _wfopen(p->m_fileName, L"ab")) == nullptr)
+ return 2;
+
+ vfwprintf(p->m_out, format, args);
+
+ p->m_lastwrite = time(0);
+ return 0;
+}
diff --git a/src/mir_core/src/md5.cpp b/src/mir_core/src/md5.cpp
index 6cb8419249..8b7b37020f 100644
--- a/src/mir_core/src/md5.cpp
+++ b/src/mir_core/src/md5.cpp
@@ -1,358 +1,358 @@
-/*
- Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5.c 2874 2006-05-16 21:38:00Z ghazan $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.c is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
- either statically or dynamically; added missing #include <string.h>
- in library.
- 2002-03-11 lpd Corrected argument list for main(), and added int return
- type, in test program and T value program.
- 2002-02-21 lpd Added missing #include <stdio.h> in test program.
- 2000-07-03 lpd Patched to eliminate warnings about "constant is
- unsigned in ANSI C, signed in traditional"; made test program
- self-checking.
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
- 1999-05-03 lpd Original version.
- */
-
-// (C) 2005 Joe @ Whale - changed to compile with Miranda
-
-#include "stdafx.h"
-
-#define T_MASK ((UINT32)~0)
-#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
-#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3 0x242070db
-#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
-#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6 0x4787c62a
-#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
-#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9 0x698098d8
-#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
-#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
-#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13 0x6b901122
-#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
-#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16 0x49b40821
-#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
-#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19 0x265e5a51
-#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
-#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22 0x02441453
-#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
-#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25 0x21e1cde6
-#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
-#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28 0x455a14ed
-#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
-#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31 0x676f02d9
-#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
-#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
-#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35 0x6d9d6122
-#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
-#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38 0x4bdecfa9
-#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
-#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41 0x289b7ec6
-#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
-#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44 0x04881d05
-#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
-#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47 0x1fa27cf8
-#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
-#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50 0x432aff97
-#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
-#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53 0x655b59c3
-#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
-#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
-#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57 0x6fa87e4f
-#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
-#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60 0x4e0811a1
-#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
-#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63 0x2ad7d2bb
-#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-//gfd*
-static void md5_process(mir_md5_state_t *pms, const BYTE *data /*[64]*/)
-{
- UINT32
- a = pms->abcd[0], b = pms->abcd[1],
- c = pms->abcd[2], d = pms->abcd[3];
- UINT32 t;
- /* Define storage for little-endian or both types of CPUs. */
- UINT32 xbuf[16];
- const UINT32 *X;
-
- {
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if (*((const BYTE *)&w)) /* dynamic little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if ( !((data - (const BYTE *)nullptr) & 3)) {
- /* data are properly aligned */
- X = (const UINT32 *)data;
- } else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
- else /* dynamic big-endian */
- {
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const BYTE *xp = data;
- int i;
-
- X = xbuf; /* (dynamic only) */
- for (i = 0; i < 16; ++i, xp += 4)
- xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
- }
- }
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b, c, d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET1(a, b, c, d, k, s, Ti)\
- t = a + F(b, c, d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET1(a, b, c, d, 0, 7, T1);
- SET1(d, a, b, c, 1, 12, T2);
- SET1(c, d, a, b, 2, 17, T3);
- SET1(b, c, d, a, 3, 22, T4);
- SET1(a, b, c, d, 4, 7, T5);
- SET1(d, a, b, c, 5, 12, T6);
- SET1(c, d, a, b, 6, 17, T7);
- SET1(b, c, d, a, 7, 22, T8);
- SET1(a, b, c, d, 8, 7, T9);
- SET1(d, a, b, c, 9, 12, T10);
- SET1(c, d, a, b, 10, 17, T11);
- SET1(b, c, d, a, 11, 22, T12);
- SET1(a, b, c, d, 12, 7, T13);
- SET1(d, a, b, c, 13, 12, T14);
- SET1(c, d, a, b, 14, 17, T15);
- SET1(b, c, d, a, 15, 22, T16);
-
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b, c, d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET2(a, b, c, d, k, s, Ti)\
- t = a + G(b, c, d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET2(a, b, c, d, 1, 5, T17);
- SET2(d, a, b, c, 6, 9, T18);
- SET2(c, d, a, b, 11, 14, T19);
- SET2(b, c, d, a, 0, 20, T20);
- SET2(a, b, c, d, 5, 5, T21);
- SET2(d, a, b, c, 10, 9, T22);
- SET2(c, d, a, b, 15, 14, T23);
- SET2(b, c, d, a, 4, 20, T24);
- SET2(a, b, c, d, 9, 5, T25);
- SET2(d, a, b, c, 14, 9, T26);
- SET2(c, d, a, b, 3, 14, T27);
- SET2(b, c, d, a, 8, 20, T28);
- SET2(a, b, c, d, 13, 5, T29);
- SET2(d, a, b, c, 2, 9, T30);
- SET2(c, d, a, b, 7, 14, T31);
- SET2(b, c, d, a, 12, 20, T32);
-
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b, c, d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET3(a, b, c, d, k, s, Ti)\
- t = a + H(b, c, d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET3(a, b, c, d, 5, 4, T33);
- SET3(d, a, b, c, 8, 11, T34);
- SET3(c, d, a, b, 11, 16, T35);
- SET3(b, c, d, a, 14, 23, T36);
- SET3(a, b, c, d, 1, 4, T37);
- SET3(d, a, b, c, 4, 11, T38);
- SET3(c, d, a, b, 7, 16, T39);
- SET3(b, c, d, a, 10, 23, T40);
- SET3(a, b, c, d, 13, 4, T41);
- SET3(d, a, b, c, 0, 11, T42);
- SET3(c, d, a, b, 3, 16, T43);
- SET3(b, c, d, a, 6, 23, T44);
- SET3(a, b, c, d, 9, 4, T45);
- SET3(d, a, b, c, 12, 11, T46);
- SET3(c, d, a, b, 15, 16, T47);
- SET3(b, c, d, a, 2, 23, T48);
-
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b, c, d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET4(a, b, c, d, k, s, Ti)\
- t = a + I(b, c, d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET4(a, b, c, d, 0, 6, T49);
- SET4(d, a, b, c, 7, 10, T50);
- SET4(c, d, a, b, 14, 15, T51);
- SET4(b, c, d, a, 5, 21, T52);
- SET4(a, b, c, d, 12, 6, T53);
- SET4(d, a, b, c, 3, 10, T54);
- SET4(c, d, a, b, 10, 15, T55);
- SET4(b, c, d, a, 1, 21, T56);
- SET4(a, b, c, d, 8, 6, T57);
- SET4(d, a, b, c, 15, 10, T58);
- SET4(c, d, a, b, 6, 15, T59);
- SET4(b, c, d, a, 13, 21, T60);
- SET4(a, b, c, d, 4, 6, T61);
- SET4(d, a, b, c, 11, 10, T62);
- SET4(c, d, a, b, 2, 15, T63);
- SET4(b, c, d, a, 9, 21, T64);
-
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- pms->abcd[0] += a;
- pms->abcd[1] += b;
- pms->abcd[2] += c;
- pms->abcd[3] += d;
-}
-
-MIR_CORE_DLL(void) mir_md5_init(mir_md5_state_t *pms)
-{
- pms->count[0] = pms->count[1] = 0;
- pms->abcd[0] = 0x67452301;
- pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
- pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
- pms->abcd[3] = 0x10325476;
-}
-
-MIR_CORE_DLL(void) mir_md5_append(mir_md5_state_t *pms, const BYTE *data, size_t nBytes)
-{
- const BYTE *p = data;
- size_t left = nBytes;
- size_t offset = (pms->count[0] >> 3) & 63;
- UINT32 nbits = (UINT32)(nBytes << 3);
-
- if (nBytes == 0)
- return;
-
- /* Update the message length. */
- pms->count[1] += (UINT32)nBytes >> 29;
- pms->count[0] += nbits;
- if (pms->count[0] < nbits)
- pms->count[1]++;
-
- /* Process an initial partial block. */
- if (offset) {
- size_t copy = (offset + nBytes > 64 ? 64 - offset : nBytes);
- memcpy(pms->buf + offset, p, copy);
- if (offset + copy < 64)
- return;
-
- p += copy;
- left -= copy;
- md5_process(pms, pms->buf);
- }
-
- /* Process full blocks. */
- for (; left >= 64; p += 64, left -= 64)
- md5_process(pms, p);
-
- /* Process a final partial block. */
- if (left)
- memcpy(pms->buf, p, left);
-}
-
-MIR_CORE_DLL(void) mir_md5_finish(mir_md5_state_t *pms, BYTE digest[16])
-{
- static const BYTE pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- BYTE data[8];
- int i;
-
- /* Save the length before padding. */
- for (i = 0; i < 8; ++i)
- data[i] = (BYTE)(pms->count[i >> 2] >> ((i & 3) << 3));
- /* Pad to 56 bytes mod 64. */
- mir_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
- /* Append the length. */
- mir_md5_append(pms, data, 8);
- for (i = 0; i < 16; ++i)
- digest[i] = (BYTE)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
-
-MIR_CORE_DLL(void) mir_md5_hash(const BYTE *data, size_t len, BYTE digest[16])
-{
- mir_md5_state_t state;
- mir_md5_init(&state);
- mir_md5_append(&state, data, len);
- mir_md5_finish(&state, digest);
-}
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c 2874 2006-05-16 21:38:00Z ghazan $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+// (C) 2005 Joe @ Whale - changed to compile with Miranda
+
+#include "stdafx.h"
+
+#define T_MASK ((uint32_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+//gfd*
+static void md5_process(mir_md5_state_t *pms, const BYTE *data /*[64]*/)
+{
+ uint32_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ uint32_t t;
+ /* Define storage for little-endian or both types of CPUs. */
+ uint32_t xbuf[16];
+ const uint32_t *X;
+
+ {
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const BYTE *)&w)) /* dynamic little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if ( !((data - (const BYTE *)nullptr) & 3)) {
+ /* data are properly aligned */
+ X = (const uint32_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+ else /* dynamic big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const BYTE *xp = data;
+ int i;
+
+ X = xbuf; /* (dynamic only) */
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b, c, d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET1(a, b, c, d, k, s, Ti)\
+ t = a + F(b, c, d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET1(a, b, c, d, 0, 7, T1);
+ SET1(d, a, b, c, 1, 12, T2);
+ SET1(c, d, a, b, 2, 17, T3);
+ SET1(b, c, d, a, 3, 22, T4);
+ SET1(a, b, c, d, 4, 7, T5);
+ SET1(d, a, b, c, 5, 12, T6);
+ SET1(c, d, a, b, 6, 17, T7);
+ SET1(b, c, d, a, 7, 22, T8);
+ SET1(a, b, c, d, 8, 7, T9);
+ SET1(d, a, b, c, 9, 12, T10);
+ SET1(c, d, a, b, 10, 17, T11);
+ SET1(b, c, d, a, 11, 22, T12);
+ SET1(a, b, c, d, 12, 7, T13);
+ SET1(d, a, b, c, 13, 12, T14);
+ SET1(c, d, a, b, 14, 17, T15);
+ SET1(b, c, d, a, 15, 22, T16);
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b, c, d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET2(a, b, c, d, k, s, Ti)\
+ t = a + G(b, c, d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET2(a, b, c, d, 1, 5, T17);
+ SET2(d, a, b, c, 6, 9, T18);
+ SET2(c, d, a, b, 11, 14, T19);
+ SET2(b, c, d, a, 0, 20, T20);
+ SET2(a, b, c, d, 5, 5, T21);
+ SET2(d, a, b, c, 10, 9, T22);
+ SET2(c, d, a, b, 15, 14, T23);
+ SET2(b, c, d, a, 4, 20, T24);
+ SET2(a, b, c, d, 9, 5, T25);
+ SET2(d, a, b, c, 14, 9, T26);
+ SET2(c, d, a, b, 3, 14, T27);
+ SET2(b, c, d, a, 8, 20, T28);
+ SET2(a, b, c, d, 13, 5, T29);
+ SET2(d, a, b, c, 2, 9, T30);
+ SET2(c, d, a, b, 7, 14, T31);
+ SET2(b, c, d, a, 12, 20, T32);
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b, c, d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET3(a, b, c, d, k, s, Ti)\
+ t = a + H(b, c, d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET3(a, b, c, d, 5, 4, T33);
+ SET3(d, a, b, c, 8, 11, T34);
+ SET3(c, d, a, b, 11, 16, T35);
+ SET3(b, c, d, a, 14, 23, T36);
+ SET3(a, b, c, d, 1, 4, T37);
+ SET3(d, a, b, c, 4, 11, T38);
+ SET3(c, d, a, b, 7, 16, T39);
+ SET3(b, c, d, a, 10, 23, T40);
+ SET3(a, b, c, d, 13, 4, T41);
+ SET3(d, a, b, c, 0, 11, T42);
+ SET3(c, d, a, b, 3, 16, T43);
+ SET3(b, c, d, a, 6, 23, T44);
+ SET3(a, b, c, d, 9, 4, T45);
+ SET3(d, a, b, c, 12, 11, T46);
+ SET3(c, d, a, b, 15, 16, T47);
+ SET3(b, c, d, a, 2, 23, T48);
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b, c, d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET4(a, b, c, d, k, s, Ti)\
+ t = a + I(b, c, d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET4(a, b, c, d, 0, 6, T49);
+ SET4(d, a, b, c, 7, 10, T50);
+ SET4(c, d, a, b, 14, 15, T51);
+ SET4(b, c, d, a, 5, 21, T52);
+ SET4(a, b, c, d, 12, 6, T53);
+ SET4(d, a, b, c, 3, 10, T54);
+ SET4(c, d, a, b, 10, 15, T55);
+ SET4(b, c, d, a, 1, 21, T56);
+ SET4(a, b, c, d, 8, 6, T57);
+ SET4(d, a, b, c, 15, 10, T58);
+ SET4(c, d, a, b, 6, 15, T59);
+ SET4(b, c, d, a, 13, 21, T60);
+ SET4(a, b, c, d, 4, 6, T61);
+ SET4(d, a, b, c, 11, 10, T62);
+ SET4(c, d, a, b, 2, 15, T63);
+ SET4(b, c, d, a, 9, 21, T64);
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+MIR_CORE_DLL(void) mir_md5_init(mir_md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+MIR_CORE_DLL(void) mir_md5_append(mir_md5_state_t *pms, const BYTE *data, size_t nBytes)
+{
+ const BYTE *p = data;
+ size_t left = nBytes;
+ size_t offset = (pms->count[0] >> 3) & 63;
+ uint32_t nbits = (uint32_t)(nBytes << 3);
+
+ if (nBytes == 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += (uint32_t)nBytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ size_t copy = (offset + nBytes > 64 ? 64 - offset : nBytes);
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+MIR_CORE_DLL(void) mir_md5_finish(mir_md5_state_t *pms, BYTE digest[16])
+{
+ static const BYTE pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ BYTE data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (BYTE)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ mir_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ mir_md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (BYTE)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
+
+MIR_CORE_DLL(void) mir_md5_hash(const BYTE *data, size_t len, BYTE digest[16])
+{
+ mir_md5_state_t state;
+ mir_md5_init(&state);
+ mir_md5_append(&state, data, len);
+ mir_md5_finish(&state, digest);
+}
diff --git a/src/mir_core/src/memory.cpp b/src/mir_core/src/memory.cpp
index 849e42564a..3e3d7be69d 100644
--- a/src/mir_core/src/memory.cpp
+++ b/src/mir_core/src/memory.cpp
@@ -1,285 +1,295 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-
-#define BLOCK_ALLOCED 0xABBABABA
-#define BLOCK_FREED 0xDEADBEEF
-
-static int CheckBlock(void* blk)
-{
- int result = FALSE;
- char* p = (char*)blk - sizeof(DWORD)*2;
- DWORD size, *b, *e;
-
- __try
- {
- size = *(DWORD*)p;
- b = (DWORD*)&p[ sizeof(DWORD) ];
- e = (DWORD*)&p[ sizeof(DWORD)*2 + size ];
-
- if (*b != BLOCK_ALLOCED || *e != BLOCK_ALLOCED)
- {
- if (*b == BLOCK_FREED && *e == BLOCK_FREED)
- OutputDebugStringA("memory block is already deleted\n");
- else
- OutputDebugStringA("memory block is corrupted\n");
- #if defined(_DEBUG)
- DebugBreak();
- #endif
- }
- else result = TRUE;
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- OutputDebugStringA("access violation during checking memory block\n");
- #if defined(_DEBUG)
- DebugBreak();
- #endif
- }
-
- return result;
-}
-
-/******************************************************************************/
-
-MIR_C_CORE_DLL(void*) mir_alloc(size_t size)
-{
- if (size == 0)
- return nullptr;
-
- char *p = (char*)malloc(size + sizeof(DWORD)* 3);
- if (p == nullptr) {
- OutputDebugStringA("memory overflow\n");
- #if defined(_DEBUG)
- DebugBreak();
- #endif
- return nullptr;
- }
-
- *(DWORD*)p = (DWORD)size;
- *(DWORD*)&p[sizeof(DWORD)] = BLOCK_ALLOCED;
- *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_ALLOCED;
- return p + sizeof(DWORD)* 2;
-}
-
-/******************************************************************************/
-
-MIR_C_CORE_DLL(void*) mir_calloc(size_t size)
-{
- void* p = mir_alloc(size);
- if (p != nullptr)
- memset(p, 0, size);
- return p;
-}
-
-/******************************************************************************/
-
-MIR_C_CORE_DLL(void*) mir_realloc(void* ptr, size_t size)
-{
- char *p;
-
- if (ptr != nullptr) {
- if (!CheckBlock(ptr))
- return nullptr;
- p = (char*)ptr - sizeof(DWORD)*2;
- }
- else p = nullptr;
-
- p = (char*)realloc(p, size + sizeof(DWORD)*3);
- if (p == nullptr) {
- OutputDebugStringA("memory overflow\n");
- #if defined(_DEBUG)
- DebugBreak();
- #endif
- return nullptr;
- }
-
- *(DWORD*)p = (DWORD)size;
- *(DWORD*)&p[sizeof(DWORD)] = BLOCK_ALLOCED;
- *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_ALLOCED;
- return p + sizeof(DWORD)*2;
-}
-
-/******************************************************************************/
-
-MIR_C_CORE_DLL(void) mir_free(void* ptr)
-{
- char* p;
- DWORD size;
-
- if (ptr == nullptr)
- return;
- if (!CheckBlock(ptr))
- return;
-
- p = (char*)ptr - sizeof(DWORD)*2;
- size = *(DWORD*)p;
-
- *(DWORD*)&p[sizeof(DWORD)] = BLOCK_FREED;
- *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_FREED;
- free(p);
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(char*) mir_strdup(const char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- char *p = (char*)mir_alloc(strlen(str)+1);
- if (p)
- strcpy(p, str);
- return p;
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrdup(const wchar_t *str)
-{
- if (str == nullptr)
- return nullptr;
-
- wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(wcslen(str)+1));
- if (p)
- wcscpy(p, str);
- return p;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(char*) mir_strndup(const char *str, size_t len)
-{
- if (str == nullptr || len == 0)
- return nullptr;
-
- char *p = (char*)mir_alloc(len+1);
- if (p) {
- memcpy(p, str, len);
- p[len] = 0;
- }
- return p;
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrndup(const wchar_t *str, size_t len)
-{
- if (str == nullptr || len == 0)
- return nullptr;
-
- wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(len+1));
- if (p) {
- memcpy(p, str, sizeof(wchar_t)*len);
- p[len] = 0;
- }
- return p;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(int) mir_snprintf(char *buffer, size_t count, const char* fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- int len = _vsnprintf(buffer, count-1, fmt, va);
- va_end(va);
- buffer[count-1] = 0;
- return len;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(int) mir_snwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- int len = _vsnwprintf(buffer, count-1, fmt, va);
- va_end(va);
- buffer[count-1] = 0;
- return len;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(int) mir_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va)
-{
- int len = _vsnprintf(buffer, count-1, fmt, va);
- buffer[count-1] = 0;
- return len;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(int) mir_vsnwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, va_list va)
-{
- int len = _vsnwprintf(buffer, count-1, fmt, va);
- buffer[count-1] = 0;
- return len;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage)
-{
- if (src == nullptr)
- return nullptr;
-
- int cbLen = MultiByteToWideChar(codepage, 0, src, -1, nullptr, 0);
- wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen+1));
- if (result == nullptr)
- return nullptr;
-
- MultiByteToWideChar(codepage, 0, src, -1, result, cbLen);
- result[cbLen] = 0;
- return result;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src)
-{
- return mir_a2u_cp(src, Langpack_GetDefaultCodePage());
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage)
-{
- if (src == nullptr)
- return nullptr;
-
- int cbLen = WideCharToMultiByte(codepage, 0, src, -1, nullptr, 0, nullptr, nullptr);
- char* result = (char*)mir_alloc(cbLen+1);
- if (result == nullptr)
- return nullptr;
-
- WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, nullptr, nullptr);
- result[cbLen] = 0;
- return result;
-}
-
-/******************************************************************************/
-
-MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src)
-{
- return mir_u2a_cp(src, Langpack_GetDefaultCodePage());
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+
+#define BLOCK_ALLOCED 0xABBABABA
+#define BLOCK_FREED 0xDEADBEEF
+
+static int CheckBlock(void* blk)
+{
+ int result = FALSE;
+ char* p = (char*)blk - sizeof(DWORD)*2;
+ DWORD size, *b, *e;
+
+ __try
+ {
+ size = *(DWORD*)p;
+ b = (DWORD*)&p[ sizeof(DWORD) ];
+ e = (DWORD*)&p[ sizeof(DWORD)*2 + size ];
+
+ if (*b != BLOCK_ALLOCED || *e != BLOCK_ALLOCED)
+ {
+ #ifdef _MSC_VER
+ if (*b == BLOCK_FREED && *e == BLOCK_FREED)
+ OutputDebugStringA("memory block is already deleted\n");
+ else
+ OutputDebugStringA("memory block is corrupted\n");
+ #if defined(_DEBUG)
+ DebugBreak();
+ #endif
+ #endif
+ }
+ else result = TRUE;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ #ifdef _MSC_VER
+ OutputDebugStringA("access violation during checking memory block\n");
+ #if defined(_DEBUG)
+ DebugBreak();
+ #endif
+ #endif
+ }
+
+ return result;
+}
+
+/******************************************************************************/
+
+MIR_C_CORE_DLL(void*) mir_alloc(size_t size)
+{
+ if (size == 0)
+ return nullptr;
+
+ char *p = (char*)malloc(size + sizeof(DWORD)* 3);
+ if (p == nullptr) {
+ #ifdef _MSC_VER
+ OutputDebugStringA("memory overflow\n");
+ #if defined(_DEBUG)
+ DebugBreak();
+ #endif
+ #endif
+ return nullptr;
+ }
+
+ *(DWORD*)p = (DWORD)size;
+ *(DWORD*)&p[sizeof(DWORD)] = BLOCK_ALLOCED;
+ *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_ALLOCED;
+ return p + sizeof(DWORD)* 2;
+}
+
+/******************************************************************************/
+
+MIR_C_CORE_DLL(void*) mir_calloc(size_t size)
+{
+ void* p = mir_alloc(size);
+ if (p != nullptr)
+ memset(p, 0, size);
+ return p;
+}
+
+/******************************************************************************/
+
+MIR_C_CORE_DLL(void*) mir_realloc(void* ptr, size_t size)
+{
+ char *p;
+
+ if (ptr != nullptr) {
+ if (!CheckBlock(ptr))
+ return nullptr;
+ p = (char*)ptr - sizeof(DWORD)*2;
+ }
+ else p = nullptr;
+
+ p = (char*)realloc(p, size + sizeof(DWORD)*3);
+ if (p == nullptr) {
+ #ifdef _MSC_VER
+ OutputDebugStringA("memory overflow\n");
+ #if defined(_DEBUG)
+ DebugBreak();
+ #endif
+ #endif
+ return nullptr;
+ }
+
+ *(DWORD*)p = (DWORD)size;
+ *(DWORD*)&p[sizeof(DWORD)] = BLOCK_ALLOCED;
+ *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_ALLOCED;
+ return p + sizeof(DWORD)*2;
+}
+
+/******************************************************************************/
+
+MIR_C_CORE_DLL(void) mir_free(void* ptr)
+{
+ char* p;
+ DWORD size;
+
+ if (ptr == nullptr)
+ return;
+ if (!CheckBlock(ptr))
+ return;
+
+ p = (char*)ptr - sizeof(DWORD)*2;
+ size = *(DWORD*)p;
+
+ *(DWORD*)&p[sizeof(DWORD)] = BLOCK_FREED;
+ *(DWORD*)&p[size + sizeof(DWORD)*2] = BLOCK_FREED;
+ free(p);
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(char*) mir_strdup(const char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ char *p = (char*)mir_alloc(strlen(str)+1);
+ if (p)
+ strcpy(p, str);
+ return p;
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrdup(const wchar_t *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(wcslen(str)+1));
+ if (p)
+ wcscpy(p, str);
+ return p;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(char*) mir_strndup(const char *str, size_t len)
+{
+ if (str == nullptr || len == 0)
+ return nullptr;
+
+ char *p = (char*)mir_alloc(len+1);
+ if (p) {
+ memcpy(p, str, len);
+ p[len] = 0;
+ }
+ return p;
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrndup(const wchar_t *str, size_t len)
+{
+ if (str == nullptr || len == 0)
+ return nullptr;
+
+ wchar_t *p = (wchar_t*)mir_alloc(sizeof(wchar_t)*(len+1));
+ if (p) {
+ memcpy(p, str, sizeof(wchar_t)*len);
+ p[len] = 0;
+ }
+ return p;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(int) mir_snprintf(char *buffer, size_t count, const char* fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ int len = _vsnprintf(buffer, count-1, fmt, va);
+ va_end(va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(int) mir_snwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ int len = _vsnwprintf(buffer, count-1, fmt, va);
+ va_end(va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(int) mir_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va)
+{
+ int len = _vsnprintf(buffer, count-1, fmt, va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(int) mir_vsnwprintf(wchar_t *buffer, size_t count, const wchar_t* fmt, va_list va)
+{
+ int len = _vsnwprintf(buffer, count-1, fmt, va);
+ buffer[count-1] = 0;
+ return len;
+}
+
+/******************************************************************************/
+
+#ifdef _MSC_VER
+MIR_CORE_DLL(wchar_t*) mir_a2u_cp(const char* src, int codepage)
+{
+ if (src == nullptr)
+ return nullptr;
+
+ int cbLen = MultiByteToWideChar(codepage, 0, src, -1, nullptr, 0);
+ wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen+1));
+ if (result == nullptr)
+ return nullptr;
+
+ MultiByteToWideChar(codepage, 0, src, -1, result, cbLen);
+ result[cbLen] = 0;
+ return result;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(wchar_t*) mir_a2u(const char* src)
+{
+ return mir_a2u_cp(src, Langpack_GetDefaultCodePage());
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(char*) mir_u2a_cp(const wchar_t* src, int codepage)
+{
+ if (src == nullptr)
+ return nullptr;
+
+ int cbLen = WideCharToMultiByte(codepage, 0, src, -1, nullptr, 0, nullptr, nullptr);
+ char* result = (char*)mir_alloc(cbLen+1);
+ if (result == nullptr)
+ return nullptr;
+
+ WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, nullptr, nullptr);
+ result[cbLen] = 0;
+ return result;
+}
+
+/******************************************************************************/
+
+MIR_CORE_DLL(char*) mir_u2a(const wchar_t* src)
+{
+ return mir_u2a_cp(src, Langpack_GetDefaultCodePage());
+}
+#endif
diff --git a/src/mir_core/src/miranda.h b/src/mir_core/src/miranda.h
index 4805798fdd..32ea470e58 100644
--- a/src/mir_core/src/miranda.h
+++ b/src/mir_core/src/miranda.h
@@ -1,93 +1,93 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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.
-*/
-
-#pragma once
-
-void UnloadLangPackModule(void);
-
-int InitialiseModularEngine(void);
-void DestroyModularEngine(void);
-
-int InitPathUtils(void);
-
-extern HINSTANCE g_hInst;
-extern HWND hAPCWindow;
-extern HANDLE hThreadQueueEmpty;
-extern HCURSOR g_hCursorNS, g_hCursorWE;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// modules.cpp
-
-struct THookSubscriber
-{
- HINSTANCE hOwner;
- int type;
- union {
- struct {
- union {
- MIRANDAHOOK pfnHook;
- MIRANDAHOOKPARAM pfnHookParam;
- MIRANDAHOOKOBJ pfnHookObj;
- MIRANDAHOOKOBJPARAM pfnHookObjParam;
- };
- void* object;
- LPARAM lParam;
- };
- struct {
- HWND hwnd;
- UINT message;
- };
- };
-};
-
-#define HOOK_SECRET_SIGNATURE 0xDEADBABA
-
-struct THook : public MZeroedObject
-{
- char name[ MAXMODULELABELLENGTH ];
- int id;
- int subscriberCount;
- THookSubscriber* subscriber;
- MIRANDAHOOK pfnHook;
- DWORD secretSignature = HOOK_SECRET_SIGNATURE;
- mir_cs csHook;
-};
-
-extern LIST<CMPluginBase> pluginListAddr;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// langpack.cpp
-
-char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// threads.cpp
-
-extern DWORD mir_tls;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// utils.cpp
-
-typedef BOOL(APIENTRY *PGENRANDOM)(PVOID, ULONG);
-extern PGENRANDOM pfnRtlGenRandom;
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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.
+*/
+
+#pragma once
+
+void UnloadLangPackModule(void);
+
+int InitialiseModularEngine(void);
+void DestroyModularEngine(void);
+
+int InitPathUtils(void);
+
+extern HINSTANCE g_hInst;
+extern HWND hAPCWindow;
+extern HANDLE hThreadQueueEmpty;
+extern HCURSOR g_hCursorNS, g_hCursorWE;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// modules.cpp
+
+struct THookSubscriber
+{
+ HINSTANCE hOwner;
+ int type;
+ union {
+ struct {
+ union {
+ MIRANDAHOOK pfnHook;
+ MIRANDAHOOKPARAM pfnHookParam;
+ MIRANDAHOOKOBJ pfnHookObj;
+ MIRANDAHOOKOBJPARAM pfnHookObjParam;
+ };
+ void* object;
+ LPARAM lParam;
+ };
+ struct {
+ HWND hwnd;
+ UINT message;
+ };
+ };
+};
+
+#define HOOK_SECRET_SIGNATURE 0xDEADBABA
+
+struct THook : public MZeroedObject
+{
+ char name[ MAXMODULELABELLENGTH ];
+ int id;
+ int subscriberCount;
+ THookSubscriber* subscriber;
+ MIRANDAHOOK pfnHook;
+ DWORD secretSignature = HOOK_SECRET_SIGNATURE;
+ mir_cs csHook;
+};
+
+extern LIST<CMPluginBase> pluginListAddr;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// langpack.cpp
+
+char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// threads.cpp
+
+extern DWORD mir_tls;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// utils.cpp
+
+typedef BOOL(MIR_SYSCALL *PGENRANDOM)(void*, DWORD);
+extern PGENRANDOM pfnRtlGenRandom;
diff --git a/src/mir_core/src/mstring.cpp b/src/mir_core/src/mstring.cpp
index 2779c93978..3982fc8d61 100644
--- a/src/mir_core/src/mstring.cpp
+++ b/src/mir_core/src/mstring.cpp
@@ -1,142 +1,140 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CMBaseString
-
-class CNilMStringData : public CMStringData
-{
-public:
- CNilMStringData();
-
-public:
- wchar_t achNil[2];
-};
-
-CNilMStringData::CNilMStringData()
-{
- nRefs = 2; // Never gets freed
- nDataLength = 0;
- nAllocLength = 0;
- achNil[0] = 0;
- achNil[1] = 0;
-}
-
-static CNilMStringData *m_nil = nullptr;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CMBaseString
-
-MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize)
-{
- nChars++; // nil char
- size_t nDataBytes = nCharSize * nChars;
- size_t nTotalSize = nDataBytes + sizeof(CMStringData);
-
- CMStringData *pData = static_cast<CMStringData*>(malloc(nTotalSize));
- if (pData == nullptr)
- return nullptr;
-
- pData->nRefs = 1;
- pData->nAllocLength = nChars - 1;
- pData->nDataLength = 0;
- return pData;
-}
-
-MIR_CORE_DLL(void) mirstr_free(CMStringData *pData)
-{
- free(pData);
-}
-
-MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize)
-{
- nChars++; // nil char
- ULONG nDataBytes = nCharSize * nChars;
- ULONG nTotalSize = nDataBytes + sizeof(CMStringData);
-
- CMStringData *pNewData = static_cast<CMStringData*>(realloc(pData, nTotalSize));
- if (pNewData == nullptr)
- return nullptr;
-
- pNewData->nAllocLength = nChars - 1;
- return pNewData;
-}
-
-MIR_CORE_DLL(CMStringData*) mirstr_getNil()
-{
- if (m_nil == nullptr)
- m_nil = new CNilMStringData();
- m_nil->AddRef();
- return m_nil;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CMStringData
-
-MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis)
-{
- pThis->nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary
- if (pThis->nRefs == 0)
- pThis->nRefs = -1;
-}
-
-MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis)
-{
- if (InterlockedDecrement(&pThis->nRefs) <= 0)
- mirstr_free(pThis);
-}
-
-MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis)
-{
- if (pThis->IsLocked())
- {
- pThis->nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary
- if (pThis->nRefs == 0)
- pThis->nRefs = 1;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// don't remove it
-// this code just instantiates templates for CMStringW[A/W]
-
-template CMStringW;
-template MIR_CORE_EXPORT CMStringW CALLBACK operator + (const CMStringW& str1, const CMStringW& str2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const wchar_t *psz2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const wchar_t *psz1, const CMStringW& str2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, wchar_t ch2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, char ch2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(wchar_t ch1, const CMStringW& str2);
-template MIR_CORE_EXPORT CMStringW CALLBACK operator+(char ch1, const CMStringW& str2);
-
-template CMStringA;
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const CMStringA& str2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const char *psz2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const char *psz1, const CMStringA& str2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, wchar_t ch2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, char ch2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(wchar_t ch1, const CMStringA& str2);
-template MIR_CORE_EXPORT CMStringA CALLBACK operator+(char ch1, const CMStringA& str2);
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMBaseString
+
+class CNilMStringData : public CMStringData
+{
+public:
+ CNilMStringData();
+
+public:
+ wchar_t achNil[2];
+};
+
+CNilMStringData::CNilMStringData()
+{
+ nRefs = 2; // Never gets freed
+ nDataLength = 0;
+ nAllocLength = 0;
+ achNil[0] = 0;
+ achNil[1] = 0;
+}
+
+static CNilMStringData *m_nil = nullptr;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMBaseString
+
+MIR_CORE_DLL(CMStringData*) mirstr_allocate(int nChars, int nCharSize)
+{
+ nChars++; // nil char
+ size_t nDataBytes = nCharSize * nChars;
+ size_t nTotalSize = nDataBytes + sizeof(CMStringData);
+
+ CMStringData *pData = static_cast<CMStringData*>(malloc(nTotalSize));
+ if (pData == nullptr)
+ return nullptr;
+
+ pData->nRefs = 1;
+ pData->nAllocLength = nChars - 1;
+ pData->nDataLength = 0;
+ return pData;
+}
+
+MIR_CORE_DLL(void) mirstr_free(CMStringData *pData)
+{
+ free(pData);
+}
+
+MIR_CORE_DLL(CMStringData*) mirstr_realloc(CMStringData* pData, int nChars, int nCharSize)
+{
+ nChars++; // nil char
+ uint32_t nDataBytes = nCharSize * nChars;
+ uint32_t nTotalSize = nDataBytes + sizeof(CMStringData);
+
+ CMStringData *pNewData = static_cast<CMStringData*>(realloc(pData, nTotalSize));
+ if (pNewData == nullptr)
+ return nullptr;
+
+ pNewData->nAllocLength = nChars - 1;
+ return pNewData;
+}
+
+MIR_CORE_DLL(CMStringData*) mirstr_getNil()
+{
+ if (m_nil == nullptr)
+ m_nil = new CNilMStringData();
+ m_nil->AddRef();
+ return m_nil;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMStringData
+
+MIR_CORE_DLL(void) mirstr_lock(CMStringData* pThis)
+{
+ pThis->nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary
+ if (pThis->nRefs == 0)
+ pThis->nRefs = -1;
+}
+
+MIR_CORE_DLL(void) mirstr_release(CMStringData* pThis)
+{
+ if (InterlockedDecrement(&pThis->nRefs) <= 0)
+ mirstr_free(pThis);
+}
+
+MIR_CORE_DLL(void) mirstr_unlock(CMStringData* pThis)
+{
+ if (pThis->IsLocked())
+ {
+ pThis->nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary
+ if (pThis->nRefs == 0)
+ pThis->nRefs = 1;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// don't remove it
+// this code just instantiates templates for CMStringW[A/W]
+
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, const wchar_t *psz2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const wchar_t *psz1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, wchar_t ch2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(const CMStringW& str1, char ch2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(wchar_t ch1, const CMStringW& str2);
+template MIR_CORE_EXPORT CMStringW CALLBACK operator+(char ch1, const CMStringW& str2);
+
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, const char *psz2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const char *psz1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, wchar_t ch2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(const CMStringA& str1, char ch2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(wchar_t ch1, const CMStringA& str2);
+template MIR_CORE_EXPORT CMStringA CALLBACK operator+(char ch1, const CMStringA& str2);
diff --git a/src/mir_core/src/sha256.cpp b/src/mir_core/src/sha256.cpp
index e3e5991f5f..63fd940a62 100644
--- a/src/mir_core/src/sha256.cpp
+++ b/src/mir_core/src/sha256.cpp
@@ -1,289 +1,289 @@
-
-#include "stdafx.h"
-
-MIR_CORE_DLL(void) mir_sha256_init(SHA256_CONTEXT *hd)
-{
- hd->h0 = 0x6a09e667;
- hd->h1 = 0xbb67ae85;
- hd->h2 = 0x3c6ef372;
- hd->h3 = 0xa54ff53a;
- hd->h4 = 0x510e527f;
- hd->h5 = 0x9b05688c;
- hd->h6 = 0x1f83d9ab;
- hd->h7 = 0x5be0cd19;
-
- hd->nblocks = 0;
- hd->count = 0;
-}
-
-/*
-Transform the message X which consists of 16 32-bit-words. See FIPS
-180-2 for details. */
-#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
-#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */
-#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */
-#define R(a,b,c,d,e,f,g,h,k,w) do \
-{ \
- t1 = (h)+Sum1((e)) + Cho((e), (f), (g)) + (k)+(w); \
- t2 = Sum0((a)) + Maj((a), (b), (c)); \
- h = g; \
- g = f; \
- f = e; \
- e = d + t1; \
- d = c; \
- c = b; \
- b = a; \
- a = t1 + t2; \
-} while (0)
-
-/* (4.2) same as SHA-1's F1. */
-static inline UINT32
-Cho(UINT32 x, UINT32 y, UINT32 z)
-{
- return (z ^ (x & (y ^ z)));
-}
-
-/* (4.3) same as SHA-1's F3 */
-static inline UINT32
-Maj(UINT32 x, UINT32 y, UINT32 z)
-{
- return ((x & y) | (z & (x | y)));
-}
-
-/* (4.4) */
-static inline UINT32 Sum0(UINT32 x)
-{
- return (ror(x, 2) ^ ror(x, 13) ^ ror(x, 22));
-}
-
-/* (4.5) */
-static inline UINT32
-Sum1(UINT32 x)
-{
- return (ror(x, 6) ^ ror(x, 11) ^ ror(x, 25));
-}
-
-
-static void transform(SHA256_CONTEXT *hd, const unsigned char *data)
-{
- static const UINT32 K[64] = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
- };
-
- UINT32 a, b, c, d, e, f, g, h, t1, t2;
- UINT32 x[16];
- UINT32 w[64];
- int i;
-
- a = hd->h0;
- b = hd->h1;
- c = hd->h2;
- d = hd->h3;
- e = hd->h4;
- f = hd->h5;
- g = hd->h6;
- h = hd->h7;
-
-#ifdef WORDS_BIGENDIAN
- memcpy(x, data, 64);
-#else
- {
- BYTE *p2;
-
- for (i = 0, p2 = (BYTE*)x; i < 16; i++, p2 += 4) {
- p2[3] = *data++;
- p2[2] = *data++;
- p2[1] = *data++;
- p2[0] = *data++;
- }
- }
-#endif
-
- for (i = 0; i < 16; i++)
- w[i] = x[i];
- for (; i < 64; i++)
- w[i] = S1(w[i - 2]) + w[i - 7] + S0(w[i - 15]) + w[i - 16];
-
- for (i = 0; i < 64;) {
-#if 0
- R(a, b, c, d, e, f, g, h, K[i], w[i]);
- i++;
-#else
- t1 = h + Sum1(e) + Cho(e, f, g) + K[i] + w[i];
- t2 = Sum0(a) + Maj(a, b, c);
- d += t1;
- h = t1 + t2;
-
- t1 = g + Sum1(d) + Cho(d, e, f) + K[i + 1] + w[i + 1];
- t2 = Sum0(h) + Maj(h, a, b);
- c += t1;
- g = t1 + t2;
-
- t1 = f + Sum1(c) + Cho(c, d, e) + K[i + 2] + w[i + 2];
- t2 = Sum0(g) + Maj(g, h, a);
- b += t1;
- f = t1 + t2;
-
- t1 = e + Sum1(b) + Cho(b, c, d) + K[i + 3] + w[i + 3];
- t2 = Sum0(f) + Maj(f, g, h);
- a += t1;
- e = t1 + t2;
-
- t1 = d + Sum1(a) + Cho(a, b, c) + K[i + 4] + w[i + 4];
- t2 = Sum0(e) + Maj(e, f, g);
- h += t1;
- d = t1 + t2;
-
- t1 = c + Sum1(h) + Cho(h, a, b) + K[i + 5] + w[i + 5];
- t2 = Sum0(d) + Maj(d, e, f);
- g += t1;
- c = t1 + t2;
-
- t1 = b + Sum1(g) + Cho(g, h, a) + K[i + 6] + w[i + 6];
- t2 = Sum0(c) + Maj(c, d, e);
- f += t1;
- b = t1 + t2;
-
- t1 = a + Sum1(f) + Cho(f, g, h) + K[i + 7] + w[i + 7];
- t2 = Sum0(b) + Maj(b, c, d);
- e += t1;
- a = t1 + t2;
-
- i += 8;
-#endif
- }
-
- hd->h0 += a;
- hd->h1 += b;
- hd->h2 += c;
- hd->h3 += d;
- hd->h4 += e;
- hd->h5 += f;
- hd->h6 += g;
- hd->h7 += h;
-}
-#undef S0
-#undef S1
-#undef R
-
-
-/* Update the message digest with the contents of INBUF with length INLEN. */
-MIR_CORE_DLL(void) mir_sha256_write(SHA256_CONTEXT *hd, const void *inbuf_arg, size_t inlen)
-{
- const unsigned char *inbuf = (const unsigned char *)inbuf_arg;
-
- if (hd->count == 64) { /* flush the buffer */
- transform(hd, hd->buf);
- hd->count = 0;
- hd->nblocks++;
- }
- if (!inbuf)
- return;
- if (hd->count) {
- for (; inlen && hd->count < 64; inlen--)
- hd->buf[hd->count++] = *inbuf++;
- mir_sha256_write(hd, nullptr, 0);
- if (!inlen)
- return;
- }
-
- while (inlen >= 64) {
- transform(hd, inbuf);
- hd->count = 0;
- hd->nblocks++;
- inlen -= 64;
- inbuf += 64;
- }
- for (; inlen && hd->count < 64; inlen--)
- hd->buf[hd->count++] = *inbuf++;
-}
-
-/*
-The routine finally terminates the computation and returns the
-digest. The handle is prepared for a new cycle, but adding bytes
-to the handle will the destroy the returned buffer. Returns: 32
-bytes with the message the digest. */
-
-MIR_CORE_DLL(void) mir_sha256_final(SHA256_CONTEXT *hd, BYTE hashout[MIR_SHA256_HASH_SIZE])
-{
- UINT32 t, msb, lsb;
-
- mir_sha256_write(hd, nullptr, 0); /* flush */;
-
- t = hd->nblocks;
- /* multiply by 64 to make a BYTE count */
- lsb = t << 6;
- msb = t >> 26;
- /* add the count */
- t = lsb;
- if ((lsb += hd->count) < t)
- msb++;
- /* multiply by 8 to make a bit count */
- t = lsb;
- lsb <<= 3;
- msb <<= 3;
- msb |= t >> 29;
-
- if (hd->count < 56) { /* enough room */
- hd->buf[hd->count++] = 0x80; /* pad */
- while (hd->count < 56)
- hd->buf[hd->count++] = 0; /* pad */
- }
- else { /* need one extra block */
- hd->buf[hd->count++] = 0x80; /* pad character */
- while (hd->count < 64)
- hd->buf[hd->count++] = 0;
- mir_sha256_write(hd, nullptr, 0); /* flush */;
- memset(hd->buf, 0, 56); /* fill next block with zeroes */
- }
- /* append the 64 bit count */
- hd->buf[56] = msb >> 24;
- hd->buf[57] = msb >> 16;
- hd->buf[58] = msb >> 8;
- hd->buf[59] = msb;
- hd->buf[60] = lsb >> 24;
- hd->buf[61] = lsb >> 16;
- hd->buf[62] = lsb >> 8;
- hd->buf[63] = lsb;
- transform(hd, hd->buf);
-
- BYTE *p = hashout;
-#ifdef WORDS_BIGENDIAN
-#define X(a) do { *(UINT32*)p = hd->h##a ; p += 4; } while(0)
-#else /* little endian */
-#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
- *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0)
-#endif
- X(0);
- X(1);
- X(2);
- X(3);
- X(4);
- X(5);
- X(6);
- X(7);
-#undef X
-}
-
-MIR_CORE_DLL(void) mir_sha256_hash(const void *dataIn, size_t len, BYTE hashout[MIR_SHA256_HASH_SIZE])
-{
- SHA256_CONTEXT tmp;
- mir_sha256_init(&tmp);
- mir_sha256_write(&tmp, dataIn, len);
- mir_sha256_final(&tmp, hashout);
-}
+
+#include "stdafx.h"
+
+MIR_CORE_DLL(void) mir_sha256_init(SHA256_CONTEXT *hd)
+{
+ hd->h0 = 0x6a09e667;
+ hd->h1 = 0xbb67ae85;
+ hd->h2 = 0x3c6ef372;
+ hd->h3 = 0xa54ff53a;
+ hd->h4 = 0x510e527f;
+ hd->h5 = 0x9b05688c;
+ hd->h6 = 0x1f83d9ab;
+ hd->h7 = 0x5be0cd19;
+
+ hd->nblocks = 0;
+ hd->count = 0;
+}
+
+/*
+Transform the message X which consists of 16 32-bit-words. See FIPS
+180-2 for details. */
+#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
+#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */
+#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */
+#define R(a,b,c,d,e,f,g,h,k,w) do \
+{ \
+ t1 = (h)+Sum1((e)) + Cho((e), (f), (g)) + (k)+(w); \
+ t2 = Sum0((a)) + Maj((a), (b), (c)); \
+ h = g; \
+ g = f; \
+ f = e; \
+ e = d + t1; \
+ d = c; \
+ c = b; \
+ b = a; \
+ a = t1 + t2; \
+} while (0)
+
+/* (4.2) same as SHA-1's F1. */
+static inline uint32_t
+Cho(uint32_t x, uint32_t y, uint32_t z)
+{
+ return (z ^ (x & (y ^ z)));
+}
+
+/* (4.3) same as SHA-1's F3 */
+static inline uint32_t
+Maj(uint32_t x, uint32_t y, uint32_t z)
+{
+ return ((x & y) | (z & (x | y)));
+}
+
+/* (4.4) */
+static inline uint32_t Sum0(uint32_t x)
+{
+ return (ror(x, 2) ^ ror(x, 13) ^ ror(x, 22));
+}
+
+/* (4.5) */
+static inline uint32_t
+Sum1(uint32_t x)
+{
+ return (ror(x, 6) ^ ror(x, 11) ^ ror(x, 25));
+}
+
+
+static void transform(SHA256_CONTEXT *hd, const unsigned char *data)
+{
+ static const uint32_t K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+
+ uint32_t a, b, c, d, e, f, g, h, t1, t2;
+ uint32_t x[16];
+ uint32_t w[64];
+ int i;
+
+ a = hd->h0;
+ b = hd->h1;
+ c = hd->h2;
+ d = hd->h3;
+ e = hd->h4;
+ f = hd->h5;
+ g = hd->h6;
+ h = hd->h7;
+
+#ifdef WORDS_BIGENDIAN
+ memcpy(x, data, 64);
+#else
+ {
+ BYTE *p2;
+
+ for (i = 0, p2 = (BYTE*)x; i < 16; i++, p2 += 4) {
+ p2[3] = *data++;
+ p2[2] = *data++;
+ p2[1] = *data++;
+ p2[0] = *data++;
+ }
+ }
+#endif
+
+ for (i = 0; i < 16; i++)
+ w[i] = x[i];
+ for (; i < 64; i++)
+ w[i] = S1(w[i - 2]) + w[i - 7] + S0(w[i - 15]) + w[i - 16];
+
+ for (i = 0; i < 64;) {
+#if 0
+ R(a, b, c, d, e, f, g, h, K[i], w[i]);
+ i++;
+#else
+ t1 = h + Sum1(e) + Cho(e, f, g) + K[i] + w[i];
+ t2 = Sum0(a) + Maj(a, b, c);
+ d += t1;
+ h = t1 + t2;
+
+ t1 = g + Sum1(d) + Cho(d, e, f) + K[i + 1] + w[i + 1];
+ t2 = Sum0(h) + Maj(h, a, b);
+ c += t1;
+ g = t1 + t2;
+
+ t1 = f + Sum1(c) + Cho(c, d, e) + K[i + 2] + w[i + 2];
+ t2 = Sum0(g) + Maj(g, h, a);
+ b += t1;
+ f = t1 + t2;
+
+ t1 = e + Sum1(b) + Cho(b, c, d) + K[i + 3] + w[i + 3];
+ t2 = Sum0(f) + Maj(f, g, h);
+ a += t1;
+ e = t1 + t2;
+
+ t1 = d + Sum1(a) + Cho(a, b, c) + K[i + 4] + w[i + 4];
+ t2 = Sum0(e) + Maj(e, f, g);
+ h += t1;
+ d = t1 + t2;
+
+ t1 = c + Sum1(h) + Cho(h, a, b) + K[i + 5] + w[i + 5];
+ t2 = Sum0(d) + Maj(d, e, f);
+ g += t1;
+ c = t1 + t2;
+
+ t1 = b + Sum1(g) + Cho(g, h, a) + K[i + 6] + w[i + 6];
+ t2 = Sum0(c) + Maj(c, d, e);
+ f += t1;
+ b = t1 + t2;
+
+ t1 = a + Sum1(f) + Cho(f, g, h) + K[i + 7] + w[i + 7];
+ t2 = Sum0(b) + Maj(b, c, d);
+ e += t1;
+ a = t1 + t2;
+
+ i += 8;
+#endif
+ }
+
+ hd->h0 += a;
+ hd->h1 += b;
+ hd->h2 += c;
+ hd->h3 += d;
+ hd->h4 += e;
+ hd->h5 += f;
+ hd->h6 += g;
+ hd->h7 += h;
+}
+#undef S0
+#undef S1
+#undef R
+
+
+/* Update the message digest with the contents of INBUF with length INLEN. */
+MIR_CORE_DLL(void) mir_sha256_write(SHA256_CONTEXT *hd, const void *inbuf_arg, size_t inlen)
+{
+ const unsigned char *inbuf = (const unsigned char *)inbuf_arg;
+
+ if (hd->count == 64) { /* flush the buffer */
+ transform(hd, hd->buf);
+ hd->count = 0;
+ hd->nblocks++;
+ }
+ if (!inbuf)
+ return;
+ if (hd->count) {
+ for (; inlen && hd->count < 64; inlen--)
+ hd->buf[hd->count++] = *inbuf++;
+ mir_sha256_write(hd, nullptr, 0);
+ if (!inlen)
+ return;
+ }
+
+ while (inlen >= 64) {
+ transform(hd, inbuf);
+ hd->count = 0;
+ hd->nblocks++;
+ inlen -= 64;
+ inbuf += 64;
+ }
+ for (; inlen && hd->count < 64; inlen--)
+ hd->buf[hd->count++] = *inbuf++;
+}
+
+/*
+The routine finally terminates the computation and returns the
+digest. The handle is prepared for a new cycle, but adding bytes
+to the handle will the destroy the returned buffer. Returns: 32
+bytes with the message the digest. */
+
+MIR_CORE_DLL(void) mir_sha256_final(SHA256_CONTEXT *hd, BYTE hashout[MIR_SHA256_HASH_SIZE])
+{
+ uint32_t t, msb, lsb;
+
+ mir_sha256_write(hd, nullptr, 0); /* flush */;
+
+ t = hd->nblocks;
+ /* multiply by 64 to make a BYTE count */
+ lsb = t << 6;
+ msb = t >> 26;
+ /* add the count */
+ t = lsb;
+ if ((lsb += hd->count) < t)
+ msb++;
+ /* multiply by 8 to make a bit count */
+ t = lsb;
+ lsb <<= 3;
+ msb <<= 3;
+ msb |= t >> 29;
+
+ if (hd->count < 56) { /* enough room */
+ hd->buf[hd->count++] = 0x80; /* pad */
+ while (hd->count < 56)
+ hd->buf[hd->count++] = 0; /* pad */
+ }
+ else { /* need one extra block */
+ hd->buf[hd->count++] = 0x80; /* pad character */
+ while (hd->count < 64)
+ hd->buf[hd->count++] = 0;
+ mir_sha256_write(hd, nullptr, 0); /* flush */;
+ memset(hd->buf, 0, 56); /* fill next block with zeroes */
+ }
+ /* append the 64 bit count */
+ hd->buf[56] = msb >> 24;
+ hd->buf[57] = msb >> 16;
+ hd->buf[58] = msb >> 8;
+ hd->buf[59] = msb;
+ hd->buf[60] = lsb >> 24;
+ hd->buf[61] = lsb >> 16;
+ hd->buf[62] = lsb >> 8;
+ hd->buf[63] = lsb;
+ transform(hd, hd->buf);
+
+ BYTE *p = hashout;
+#ifdef WORDS_BIGENDIAN
+#define X(a) do { *(uint32_t*)p = hd->h##a ; p += 4; } while(0)
+#else /* little endian */
+#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
+ *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0)
+#endif
+ X(0);
+ X(1);
+ X(2);
+ X(3);
+ X(4);
+ X(5);
+ X(6);
+ X(7);
+#undef X
+}
+
+MIR_CORE_DLL(void) mir_sha256_hash(const void *dataIn, size_t len, BYTE hashout[MIR_SHA256_HASH_SIZE])
+{
+ SHA256_CONTEXT tmp;
+ mir_sha256_init(&tmp);
+ mir_sha256_write(&tmp, dataIn, len);
+ mir_sha256_final(&tmp, hashout);
+}
diff --git a/src/mir_core/src/stdafx.h b/src/mir_core/src/stdafx.h
index 9b9d913bfc..cbc7f7af48 100644
--- a/src/mir_core/src/stdafx.h
+++ b/src/mir_core/src/stdafx.h
@@ -1,74 +1,78 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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.
-*/
-
-#pragma once
-
-#define INCL_WINSOCK_API_TYPEDEFS 1
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#include <windowsx.h>
-#include <shlobj.h>
-#include <commctrl.h>
-#include <ShellAPI.h>
-#include <vssym32.h>
-#include <Uxtheme.h>
-#include <Richedit.h>
-#include <Wtsapi32.h>
-
-#include <malloc.h>
-#include <stdio.h>
-#include <time.h>
-#include <stddef.h>
-#include <process.h>
-#include <io.h>
-#include <limits.h>
-#include <string.h>
-#include <locale.h>
-#include <direct.h>
-
-#define __NO_CMPLUGIN_NEEDED
-#include <m_system.h>
-#include <m_database.h>
-#include <m_db_int.h>
-#include <newpluginapi.h>
-#include <m_langpack.h>
-#include <m_metacontacts.h>
-#include <m_skin.h>
-#include <m_icolib.h>
-#include <m_netlib.h>
-#include <m_timezones.h>
-#include <m_protocols.h>
-#include <m_button.h>
-#include <m_gui.h>
-#include <m_chat_int.h>
-
-#include "miranda.h"
-
-#include <m_xml.h>
-
-#include <m_string.inl>
-
-void GetDefaultLang(); \ No newline at end of file
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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.
+*/
+
+#pragma once
+
+#define INCL_WINSOCK_API_TYPEDEFS 1
+
+#ifdef _MSC_VER
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#include <windowsx.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <ShellAPI.h>
+#include <vssym32.h>
+#include <Uxtheme.h>
+#include <Richedit.h>
+#include <Wtsapi32.h>
+
+#include <process.h>
+#include <io.h>
+#include <direct.h>
+#endif // _WINDOWS
+
+#include <malloc.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+#include <locale.h>
+
+#define __NO_CMPLUGIN_NEEDED
+#include <m_system.h>
+#include <m_database.h>
+#include <m_db_int.h>
+#include <newpluginapi.h>
+#include <m_langpack.h>
+#include <m_metacontacts.h>
+#include <m_skin.h>
+#include <m_icolib.h>
+#include <m_netlib.h>
+#include <m_timezones.h>
+#include <m_protocols.h>
+#include <m_button.h>
+#include <m_gui.h>
+#include <m_chat_int.h>
+
+#include "miranda.h"
+
+#include <m_xml.h>
+
+#include <m_string.inl>
+
+void GetDefaultLang();
diff --git a/src/mir_core/src/utf.cpp b/src/mir_core/src/utf.cpp
index 4af4d97fee..b5bd37717f 100644
--- a/src/mir_core/src/utf.cpp
+++ b/src/mir_core/src/utf.cpp
@@ -1,437 +1,441 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
- Copyright 2000 Alexandre Julliard of Wine project
- (UTF-8 conversion routines)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
-static const char utf8_length[128] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0-0xcf */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xd0-0xdf */
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0-0xef */
- 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0-0xff */
-};
-
-/* first byte mask depending on UTF-8 sequence length */
-static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
-
-/* minimum Unicode value depending on UTF-8 sequence length */
-static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
-
-/* get the next char value taking surrogates into account */
-static unsigned int getSurrogateValue(const wchar_t *src, unsigned int srclen)
-{
- if (src[0] >= 0xd800 && src[0] <= 0xdfff) { /* surrogate pair */
- if (src[0] > 0xdbff || /* invalid high surrogate */
- srclen <= 1 || /* missing low surrogate */
- src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */
- return 0;
- return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff);
- }
- return src[0];
-}
-
-/* query necessary dst length for src string */
-static int mir_utf8len(const wchar_t *src, unsigned int srclen)
-{
- int len;
- unsigned int val;
-
- for (len = 0; srclen; srclen--, src++) {
- if (*src < 0x80) { /* 0x00-0x7f: 1 byte */
- len++;
- continue;
- }
- if (*src < 0x800) { /* 0x80-0x7ff: 2 bytes */
- len += 2;
- continue;
- }
- if (!(val = getSurrogateValue(src, srclen)))
- return -2;
-
- if (val < 0x10000) /* 0x800-0xffff: 3 bytes */
- len += 3;
- else { /* 0x10000-0x10ffff: 4 bytes */
- len += 4;
- src++;
- srclen--;
- }
- }
- return len;
-}
-
-MIR_CORE_DLL(int) mir_utf8lenW(const wchar_t *src)
-{
- if (src == nullptr)
- return 0;
-
- return mir_utf8len(src, (int)wcslen(src));
-}
-
-/* wide char to UTF-8 string conversion */
-/* return -1 on dst buffer overflow, -2 on invalid input char */
-int Ucs2toUtf8(const wchar_t *src, int srclen, char *dst, int dstlen)
-{
- int len;
-
- for (len = dstlen; srclen; srclen--, src++) {
- wchar_t ch = *src;
- unsigned int val;
-
- if (ch < 0x80) { /* 0x00-0x7f: 1 byte */
- if (!len--) return -1; /* overflow */
- *dst++ = ch;
- continue;
- }
-
- if (ch < 0x800) { /* 0x80-0x7ff: 2 bytes */
- if ((len -= 2) < 0) return -1; /* overflow */
- dst[1] = 0x80 | (ch & 0x3f);
- ch >>= 6;
- dst[0] = 0xc0 | ch;
- dst += 2;
- continue;
- }
-
- if (!(val = getSurrogateValue(src, srclen)))
- return -2;
-
- if (val < 0x10000) { /* 0x800-0xffff: 3 bytes */
- if ((len -= 3) < 0) return -1; /* overflow */
- dst[2] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[1] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[0] = 0xe0 | val;
- dst += 3;
- }
- else { /* 0x10000-0x10ffff: 4 bytes */
- if ((len -= 4) < 0) return -1; /* overflow */
- dst[3] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[2] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[1] = 0x80 | (val & 0x3f);
- val >>= 6;
- dst[0] = 0xf0 | val;
- dst += 4;
- src++;
- srclen--;
- }
- }
- return dstlen - len;
-}
-
-/* helper for the various utf8 mbstowcs functions */
-static unsigned int decodeUtf8Char(unsigned char ch, const char **str, const char *strend)
-{
- unsigned int len = utf8_length[ch - 0x80];
- unsigned int res = ch & utf8_mask[len];
- const char *end = *str + len;
-
- if (end > strend) return ~0;
- switch (len) {
- case 3:
- if ((ch = end[-3] ^ 0x80) >= 0x40) break;
- res = (res << 6) | ch;
- (*str)++;
-
- case 2:
- if ((ch = end[-2] ^ 0x80) >= 0x40) break;
- res = (res << 6) | ch;
- (*str)++;
-
- case 1:
- if ((ch = end[-1] ^ 0x80) >= 0x40) break;
- res = (res << 6) | ch;
- (*str)++;
- if (res < utf8_minval[len]) break;
- return res;
- }
- return ~0;
-}
-
-/* query necessary dst length for src string */
-static int Utf8toUcs2Len(const char *src, size_t srclen)
-{
- int ret = 0;
- unsigned int res;
- const char *srcend = src + srclen;
-
- while (src < srcend) {
- unsigned char ch = *src++;
- if (ch < 0x80) { /* special fast case for 7-bit ASCII */
- ret++;
- continue;
- }
- if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0x10ffff) {
- if (res > 0xffff) ret++;
- ret++;
- }
- else return -2; /* bad char */
- /* otherwise ignore it */
- }
- return ret;
-}
-
-/* UTF-8 to wide char string conversion */
-/* return -1 on dst buffer overflow, -2 on invalid input char */
-MIR_CORE_DLL(int) Utf8toUcs2(const char *src, size_t srclen, wchar_t *dst, size_t dstlen)
-{
- unsigned int res;
- const char *srcend = src + srclen; // including trailing zero
- wchar_t *dstend = dst + dstlen;
-
- while ((dst < dstend) && (src < srcend)) {
- unsigned char ch = *src++;
- if (ch < 0x80) { /* special fast case for 7-bit ASCII */
- *dst++ = ch;
- continue;
- }
-
- if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0xffff)
- *dst++ = res;
- else if (res <= 0x10ffff) { /* we need surrogates */
- if (dst == dstend - 1)
- return -1; /* overflow */
- res -= 0x10000;
- *dst++ = 0xd800 | (res >> 10);
- *dst++ = 0xdc00 | (res & 0x3ff);
- }
- else return -2; /* bad char */
- }
-
- if (src < srcend)
- return -1; /* overflow */
-
- return (int)(dstlen - (dstend - dst));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// mir_utf8decode - converts UTF8-encoded string to the UCS2/MBCS format
-
-MIR_CORE_DLL(char*) mir_utf8decodecp(char *str, int codepage, wchar_t **ucs2)
-{
- bool needs_free = false;
- wchar_t* tempBuf = nullptr;
- if (ucs2)
- *ucs2 = nullptr;
-
- if (str == nullptr)
- return nullptr;
-
- size_t len = strlen(str);
- if (len < 2) {
- if (ucs2 != nullptr) {
- *ucs2 = tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t));
- MultiByteToWideChar(codepage, 0, str, (int)len, tempBuf, (int)len);
- tempBuf[len] = 0;
- }
- return str;
- }
-
- int destlen = Utf8toUcs2Len(str, len);
- if (destlen < 0)
- return nullptr;
-
- if (ucs2 == nullptr) {
- __try {
- tempBuf = (wchar_t*)alloca((destlen + 1) * sizeof(wchar_t));
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- tempBuf = nullptr;
- needs_free = true;
- }
- }
-
- if (tempBuf == nullptr) {
- tempBuf = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t));
- if (tempBuf == nullptr)
- return nullptr;
- }
-
- Utf8toUcs2(str, len, tempBuf, destlen);
- tempBuf[destlen] = 0;
- WideCharToMultiByte(codepage, 0, tempBuf, -1, str, (int)len + 1, "?", nullptr);
-
- if (ucs2)
- *ucs2 = tempBuf;
- else if (needs_free)
- mir_free(tempBuf);
-
- return str;
-}
-
-MIR_CORE_DLL(char*) mir_utf8decode(char *str, wchar_t **ucs2)
-{
- return mir_utf8decodecp(str, Langpack_GetDefaultCodePage(), ucs2);
-}
-
-MIR_CORE_DLL(wchar_t*) mir_utf8decodeW(const char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- size_t len = strlen(str);
-
- int destlen = Utf8toUcs2Len(str, len);
- if (destlen < 0)
- return nullptr;
-
- wchar_t* ucs2 = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t));
- if (ucs2 == nullptr)
- return nullptr;
-
- if (Utf8toUcs2(str, len, ucs2, destlen) >= 0) {
- ucs2[destlen] = 0;
- return ucs2;
- }
-
- mir_free(ucs2);
-
- return nullptr;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// mir_utf8encode - converts MBCS string to the UTF8-encoded format
-
-MIR_CORE_DLL(char*) mir_utf8encodecp(const char* src, int codepage)
-{
- int len;
- bool needs_free = false;
- char* result = nullptr;
- wchar_t* tempBuf;
-
- if (src == nullptr)
- return nullptr;
-
- len = (int)strlen(src);
-
- __try {
- tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t));
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t));
- if (tempBuf == nullptr) return nullptr;
- needs_free = true;
- }
-
- len = MultiByteToWideChar(codepage, 0, src, -1, tempBuf, len + 1);
-
- int destlen = mir_utf8len(tempBuf, len);
- if (destlen >= 0) {
- result = (char*)mir_alloc(destlen + 1);
- if (result) {
- Ucs2toUtf8(tempBuf, len, result, destlen);
- result[destlen] = 0;
- }
- }
-
- if (needs_free)
- mir_free(tempBuf);
-
- return result;
-}
-
-MIR_CORE_DLL(char*) mir_utf8encode(const char* src)
-{
- return mir_utf8encodecp(src, Langpack_GetDefaultCodePage());
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// mir_utf8encode - converts UCS2 string to the UTF8-encoded format
-
-MIR_CORE_DLL(char*) mir_utf8encodeW(const wchar_t* src)
-{
- if (src == nullptr)
- return nullptr;
-
- int len = (int)wcslen(src);
-
- int destlen = mir_utf8len(src, len);
- if (destlen < 0) return nullptr;
-
- char* result = (char*)mir_alloc(destlen + 1);
- if (result == nullptr)
- return nullptr;
-
- Ucs2toUtf8(src, len, result, destlen);
- result[destlen] = 0;
-
- return result;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Utf8CheckString - checks if a string is a valid utf8-encoded string
-
-MIR_CORE_DLL(BOOL) Utf8CheckString(const char *str)
-{
- int expect_bytes = 0, utf_found = 0;
-
- if (!str) return 0;
-
- while (*str) {
- if ((*str & 0x80) == 0) {
- /* Looks like an ASCII character */
- if (expect_bytes)
- /* byte of UTF-8 character expected */
- return 0;
- }
- else {
- /* Looks like byte of an UTF-8 character */
- if (expect_bytes) {
- /* expect_bytes already set: first byte of UTF-8 char already seen */
- if ((*str & 0xC0) != 0x80) {
- /* again first byte ?!?! */
- return 0;
- }
- }
- else {
- /* First byte of the UTF-8 character */
- /* count initial one bits and set expect_bytes to 1 less */
- char ch = *str;
- while (ch & 0x80) {
- expect_bytes++;
- ch = (ch & 0x7f) << 1;
- }
- }
- /* OK, next byte of UTF-8 character */
- /* Decrement number of expected bytes */
- if (--expect_bytes == 0)
- utf_found = 1;
- }
- str++;
- }
-
- return (utf_found && expect_bytes == 0);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+ Copyright 2000 Alexandre Julliard of Wine project
+ (UTF-8 conversion routines)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
+static const char utf8_length[128] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xaf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0-0xbf */
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0-0xcf */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xd0-0xdf */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0-0xef */
+ 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0-0xff */
+};
+
+/* first byte mask depending on UTF-8 sequence length */
+static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
+
+/* minimum Unicode value depending on UTF-8 sequence length */
+static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
+
+/* get the next char value taking surrogates into account */
+static unsigned int getSurrogateValue(const wchar_t *src, unsigned int srclen)
+{
+ if (src[0] >= 0xd800 && src[0] <= 0xdfff) { /* surrogate pair */
+ if (src[0] > 0xdbff || /* invalid high surrogate */
+ srclen <= 1 || /* missing low surrogate */
+ src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */
+ return 0;
+ return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff);
+ }
+ return src[0];
+}
+
+/* query necessary dst length for src string */
+static int mir_utf8len(const wchar_t *src, unsigned int srclen)
+{
+ int len;
+ unsigned int val;
+
+ for (len = 0; srclen; srclen--, src++) {
+ if (*src < 0x80) { /* 0x00-0x7f: 1 byte */
+ len++;
+ continue;
+ }
+ if (*src < 0x800) { /* 0x80-0x7ff: 2 bytes */
+ len += 2;
+ continue;
+ }
+ if (!(val = getSurrogateValue(src, srclen)))
+ return -2;
+
+ if (val < 0x10000) /* 0x800-0xffff: 3 bytes */
+ len += 3;
+ else { /* 0x10000-0x10ffff: 4 bytes */
+ len += 4;
+ src++;
+ srclen--;
+ }
+ }
+ return len;
+}
+
+MIR_CORE_DLL(int) mir_utf8lenW(const wchar_t *src)
+{
+ if (src == nullptr)
+ return 0;
+
+ return mir_utf8len(src, (int)wcslen(src));
+}
+
+/* wide char to UTF-8 string conversion */
+/* return -1 on dst buffer overflow, -2 on invalid input char */
+int Ucs2toUtf8(const wchar_t *src, int srclen, char *dst, int dstlen)
+{
+ int len;
+
+ for (len = dstlen; srclen; srclen--, src++) {
+ wchar_t ch = *src;
+ unsigned int val;
+
+ if (ch < 0x80) { /* 0x00-0x7f: 1 byte */
+ if (!len--) return -1; /* overflow */
+ *dst++ = ch;
+ continue;
+ }
+
+ if (ch < 0x800) { /* 0x80-0x7ff: 2 bytes */
+ if ((len -= 2) < 0) return -1; /* overflow */
+ dst[1] = 0x80 | (ch & 0x3f);
+ ch >>= 6;
+ dst[0] = 0xc0 | ch;
+ dst += 2;
+ continue;
+ }
+
+ if (!(val = getSurrogateValue(src, srclen)))
+ return -2;
+
+ if (val < 0x10000) { /* 0x800-0xffff: 3 bytes */
+ if ((len -= 3) < 0) return -1; /* overflow */
+ dst[2] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[1] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[0] = 0xe0 | val;
+ dst += 3;
+ }
+ else { /* 0x10000-0x10ffff: 4 bytes */
+ if ((len -= 4) < 0) return -1; /* overflow */
+ dst[3] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[2] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[1] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[0] = 0xf0 | val;
+ dst += 4;
+ src++;
+ srclen--;
+ }
+ }
+ return dstlen - len;
+}
+
+/* helper for the various utf8 mbstowcs functions */
+static unsigned int decodeUtf8Char(unsigned char ch, const char **str, const char *strend)
+{
+ unsigned int len = utf8_length[ch - 0x80];
+ unsigned int res = ch & utf8_mask[len];
+ const char *end = *str + len;
+
+ if (end > strend) return ~0;
+ switch (len) {
+ case 3:
+ if ((ch = end[-3] ^ 0x80) >= 0x40) break;
+ res = (res << 6) | ch;
+ (*str)++;
+
+ case 2:
+ if ((ch = end[-2] ^ 0x80) >= 0x40) break;
+ res = (res << 6) | ch;
+ (*str)++;
+
+ case 1:
+ if ((ch = end[-1] ^ 0x80) >= 0x40) break;
+ res = (res << 6) | ch;
+ (*str)++;
+ if (res < utf8_minval[len]) break;
+ return res;
+ }
+ return ~0;
+}
+
+/* query necessary dst length for src string */
+static int Utf8toUcs2Len(const char *src, size_t srclen)
+{
+ int ret = 0;
+ unsigned int res;
+ const char *srcend = src + srclen;
+
+ while (src < srcend) {
+ unsigned char ch = *src++;
+ if (ch < 0x80) { /* special fast case for 7-bit ASCII */
+ ret++;
+ continue;
+ }
+ if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0x10ffff) {
+ if (res > 0xffff) ret++;
+ ret++;
+ }
+ else return -2; /* bad char */
+ /* otherwise ignore it */
+ }
+ return ret;
+}
+
+/* UTF-8 to wide char string conversion */
+/* return -1 on dst buffer overflow, -2 on invalid input char */
+MIR_CORE_DLL(int) Utf8toUcs2(const char *src, size_t srclen, wchar_t *dst, size_t dstlen)
+{
+ unsigned int res;
+ const char *srcend = src + srclen; // including trailing zero
+ wchar_t *dstend = dst + dstlen;
+
+ while ((dst < dstend) && (src < srcend)) {
+ unsigned char ch = *src++;
+ if (ch < 0x80) { /* special fast case for 7-bit ASCII */
+ *dst++ = ch;
+ continue;
+ }
+
+ if ((res = decodeUtf8Char(ch, &src, srcend)) <= 0xffff)
+ *dst++ = res;
+ else if (res <= 0x10ffff) { /* we need surrogates */
+ if (dst == dstend - 1)
+ return -1; /* overflow */
+ res -= 0x10000;
+ *dst++ = 0xd800 | (res >> 10);
+ *dst++ = 0xdc00 | (res & 0x3ff);
+ }
+ else return -2; /* bad char */
+ }
+
+ if (src < srcend)
+ return -1; /* overflow */
+
+ return (int)(dstlen - (dstend - dst));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// mir_utf8decode - converts UTF8-encoded string to the UCS2/MBCS format
+
+#ifdef _MSC_VER
+MIR_CORE_DLL(char*) mir_utf8decodecp(char *str, int codepage, wchar_t **ucs2)
+{
+ bool needs_free = false;
+ wchar_t* tempBuf = nullptr;
+ if (ucs2)
+ *ucs2 = nullptr;
+
+ if (str == nullptr)
+ return nullptr;
+
+ size_t len = strlen(str);
+ if (len < 2) {
+ if (ucs2 != nullptr) {
+ *ucs2 = tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t));
+ MultiByteToWideChar(codepage, 0, str, (int)len, tempBuf, (int)len);
+ tempBuf[len] = 0;
+ }
+ return str;
+ }
+
+ int destlen = Utf8toUcs2Len(str, len);
+ if (destlen < 0)
+ return nullptr;
+
+ if (ucs2 == nullptr) {
+ __try {
+ tempBuf = (wchar_t*)alloca((destlen + 1) * sizeof(wchar_t));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ tempBuf = nullptr;
+ needs_free = true;
+ }
+ }
+
+ if (tempBuf == nullptr) {
+ tempBuf = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t));
+ if (tempBuf == nullptr)
+ return nullptr;
+ }
+
+ Utf8toUcs2(str, len, tempBuf, destlen);
+ tempBuf[destlen] = 0;
+ WideCharToMultiByte(codepage, 0, tempBuf, -1, str, (int)len + 1, "?", nullptr);
+
+ if (ucs2)
+ *ucs2 = tempBuf;
+ else if (needs_free)
+ mir_free(tempBuf);
+
+ return str;
+}
+
+MIR_CORE_DLL(char*) mir_utf8decode(char *str, wchar_t **ucs2)
+{
+ return mir_utf8decodecp(str, Langpack_GetDefaultCodePage(), ucs2);
+}
+#endif
+
+MIR_CORE_DLL(wchar_t*) mir_utf8decodeW(const char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ size_t len = strlen(str);
+
+ int destlen = Utf8toUcs2Len(str, len);
+ if (destlen < 0)
+ return nullptr;
+
+ wchar_t* ucs2 = (wchar_t*)mir_alloc((destlen + 1) * sizeof(wchar_t));
+ if (ucs2 == nullptr)
+ return nullptr;
+
+ if (Utf8toUcs2(str, len, ucs2, destlen) >= 0) {
+ ucs2[destlen] = 0;
+ return ucs2;
+ }
+
+ mir_free(ucs2);
+
+ return nullptr;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// mir_utf8encode - converts MBCS string to the UTF8-encoded format
+
+#ifdef _MSC_VER
+MIR_CORE_DLL(char*) mir_utf8encodecp(const char* src, int codepage)
+{
+ int len;
+ bool needs_free = false;
+ char* result = nullptr;
+ wchar_t* tempBuf;
+
+ if (src == nullptr)
+ return nullptr;
+
+ len = (int)strlen(src);
+
+ __try {
+ tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ tempBuf = (wchar_t*)mir_alloc((len + 1) * sizeof(wchar_t));
+ if (tempBuf == nullptr) return nullptr;
+ needs_free = true;
+ }
+
+ len = MultiByteToWideChar(codepage, 0, src, -1, tempBuf, len + 1);
+
+ int destlen = mir_utf8len(tempBuf, len);
+ if (destlen >= 0) {
+ result = (char*)mir_alloc(destlen + 1);
+ if (result) {
+ Ucs2toUtf8(tempBuf, len, result, destlen);
+ result[destlen] = 0;
+ }
+ }
+
+ if (needs_free)
+ mir_free(tempBuf);
+
+ return result;
+}
+
+MIR_CORE_DLL(char*) mir_utf8encode(const char* src)
+{
+ return mir_utf8encodecp(src, Langpack_GetDefaultCodePage());
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// mir_utf8encode - converts UCS2 string to the UTF8-encoded format
+
+MIR_CORE_DLL(char*) mir_utf8encodeW(const wchar_t* src)
+{
+ if (src == nullptr)
+ return nullptr;
+
+ int len = (int)wcslen(src);
+
+ int destlen = mir_utf8len(src, len);
+ if (destlen < 0) return nullptr;
+
+ char* result = (char*)mir_alloc(destlen + 1);
+ if (result == nullptr)
+ return nullptr;
+
+ Ucs2toUtf8(src, len, result, destlen);
+ result[destlen] = 0;
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Utf8CheckString - checks if a string is a valid utf8-encoded string
+
+MIR_CORE_DLL(BOOL) Utf8CheckString(const char *str)
+{
+ int expect_bytes = 0, utf_found = 0;
+
+ if (!str) return 0;
+
+ while (*str) {
+ if ((*str & 0x80) == 0) {
+ /* Looks like an ASCII character */
+ if (expect_bytes)
+ /* byte of UTF-8 character expected */
+ return 0;
+ }
+ else {
+ /* Looks like byte of an UTF-8 character */
+ if (expect_bytes) {
+ /* expect_bytes already set: first byte of UTF-8 char already seen */
+ if ((*str & 0xC0) != 0x80) {
+ /* again first byte ?!?! */
+ return 0;
+ }
+ }
+ else {
+ /* First byte of the UTF-8 character */
+ /* count initial one bits and set expect_bytes to 1 less */
+ char ch = *str;
+ while (ch & 0x80) {
+ expect_bytes++;
+ ch = (ch & 0x7f) << 1;
+ }
+ }
+ /* OK, next byte of UTF-8 character */
+ /* Decrement number of expected bytes */
+ if (--expect_bytes == 0)
+ utf_found = 1;
+ }
+ str++;
+ }
+
+ return (utf_found && expect_bytes == 0);
+}
diff --git a/src/mir_core/src/utils.cpp b/src/mir_core/src/utils.cpp
index ccd89aabcc..26f6c2970b 100644
--- a/src/mir_core/src/utils.cpp
+++ b/src/mir_core/src/utils.cpp
@@ -1,561 +1,565 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "stdafx.h"
-
-MIR_CORE_DLL(char*) replaceStr(char* &dest, const char *src)
-{
- if (dest != nullptr)
- mir_free(dest);
-
- return dest = (src != nullptr) ? mir_strdup(src) : nullptr;
-}
-
-MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t* &dest, const wchar_t *src)
-{
- if (dest != nullptr)
- mir_free(dest);
-
- return dest = (src != nullptr) ? mir_wstrdup(src) : nullptr;
-}
-
-MIR_CORE_DLL(char*) rtrim(char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- char* p = strchr(str, 0);
- while (--p >= str) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- *p = 0; break;
- default:
- return str;
- }
- }
- return str;
-}
-
-MIR_CORE_DLL(wchar_t*) rtrimw(wchar_t *str)
-{
- if (str == nullptr)
- return nullptr;
-
- wchar_t *p = wcschr(str, 0);
- while (--p >= str) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- *p = 0; break;
- default:
- return str;
- }
- }
- return str;
-}
-
-MIR_CORE_DLL(char*) ltrim(char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- char* p = str;
- for (;;) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- ++p; break;
- default:
- memmove(str, p, strlen(p) + 1);
- return str;
- }
- }
-}
-
-MIR_CORE_DLL(wchar_t*) ltrimw(wchar_t *str)
-{
- if (str == nullptr)
- return nullptr;
-
- wchar_t *p = str;
- for (;;) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- ++p; break;
- default:
- memmove(str, p, sizeof(wchar_t)*(wcslen(p) + 1));
- return str;
- }
- }
-}
-
-MIR_CORE_DLL(char*) ltrimp(char *str)
-{
- if (str == nullptr)
- return nullptr;
-
- char *p = str;
- for (;;) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- ++p; break;
- default:
- return p;
- }
- }
-}
-
-MIR_CORE_DLL(wchar_t*) ltrimpw(wchar_t *str)
-{
- if (str == nullptr)
- return nullptr;
-
- wchar_t *p = str;
- for (;;) {
- switch (*p) {
- case ' ': case '\t': case '\n': case '\r':
- ++p; break;
- default:
- return p;
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(char*) strdel(char *str, size_t len)
-{
- char* p;
- for (p = str + len; *p != 0; p++)
- *(p - len) = *p;
-
- *(p - len) = '\0';
- return str;
-}
-
-MIR_CORE_DLL(wchar_t*) strdelw(wchar_t *str, size_t len)
-{
- wchar_t* p;
- for (p = str + len; *p != 0; p++)
- *(p - len) = *p;
-
- *(p - len) = '\0';
- return str;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) wildcmp(const char *name, const char *mask)
-{
- if (name == nullptr || mask == nullptr)
- return false;
-
- const char *last = nullptr;
- for (;; mask++, name++) {
- if (*mask != '?' && *mask != *name) break;
- if (*name == '\0') return ((BOOL)!*mask);
- }
- if (*mask != '*') return FALSE;
- for (;; mask++, name++) {
- while (*mask == '*') {
- last = mask++;
- if (*mask == '\0') return ((BOOL)!*mask); /* true */
- }
- if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
- if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
- }
-}
-
-MIR_CORE_DLL(int) wildcmpw(const wchar_t *name, const wchar_t *mask)
-{
- if (name == nullptr || mask == nullptr)
- return false;
-
- const wchar_t* last = nullptr;
- for (;; mask++, name++) {
- if (*mask != '?' && *mask != *name) break;
- if (*name == '\0') return ((BOOL)!*mask);
- }
- if (*mask != '*') return FALSE;
- for (;; mask++, name++) {
- while (*mask == '*') {
- last = mask++;
- if (*mask == '\0') return ((BOOL)!*mask); /* true */
- }
- if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
- if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
- }
-}
-
-#define _qtoupper(_c) (((_c) >= 'a' && (_c) <= 'z')?((_c)-'a'+'A'):(_c))
-
-MIR_CORE_DLL(int) wildcmpi(const char *name, const char *mask)
-{
- if (name == nullptr || mask == nullptr)
- return false;
-
- const char *last = nullptr;
- for (;; mask++, name++) {
- if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
- if (*name == '\0') return ((BOOL)!*mask);
- }
- if (*mask != '*') return FALSE;
- for (;; mask++, name++) {
- while (*mask == '*') {
- last = mask++;
- if (*mask == '\0') return ((BOOL)!*mask); /* true */
- }
- if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
- if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
- }
-}
-
-MIR_CORE_DLL(int) wildcmpiw(const wchar_t *name, const wchar_t *mask)
-{
- if (name == nullptr || mask == nullptr)
- return false;
-
- const wchar_t* last = nullptr;
- for (;; mask++, name++) {
- if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
- if (*name == '\0') return ((BOOL)!*mask);
- }
- if (*mask != '*') return FALSE;
- for (;; mask++, name++) {
- while (*mask == '*') {
- last = mask++;
- if (*mask == '\0') return ((BOOL)!*mask); /* true */
- }
- if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
- if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static char szHexTable[] = "0123456789abcdef";
-
-MIR_CORE_DLL(char*) bin2hex(const void *pData, size_t len, char *dest)
-{
- const BYTE *p = (const BYTE*)pData;
- char *d = dest;
-
- for (size_t i = 0; i < len; i++, p++) {
- *d++ = szHexTable[*p >> 4];
- *d++ = szHexTable[*p & 0x0F];
- }
- *d = 0;
-
- return dest;
-}
-
-MIR_CORE_DLL(wchar_t*) bin2hexW(const void *pData, size_t len, wchar_t *dest)
-{
- const BYTE *p = (const BYTE*)pData;
- wchar_t *d = dest;
-
- for (size_t i = 0; i < len; i++, p++) {
- *d++ = szHexTable[*p >> 4];
- *d++ = szHexTable[*p & 0x0F];
- }
- *d = 0;
-
- return dest;
-}
-
-static int hex2dec(int iHex)
-{
- if (iHex >= '0' && iHex <= '9')
- return iHex - '0';
- if (iHex >= 'a' && iHex <= 'f')
- return iHex - 'a' + 10;
- if (iHex >= 'A' && iHex <= 'F')
- return iHex - 'A' + 10;
- return 0;
-}
-
-MIR_CORE_DLL(bool) hex2bin(const char *pSrc, void *pData, size_t len)
-{
- if (pSrc == nullptr || pData == nullptr || len == 0)
- return false;
-
- size_t bufLen = strlen(pSrc)/2;
- if (pSrc[bufLen*2] != 0 || bufLen > len)
- return false;
-
- BYTE *pDest = (BYTE*)pData;
- const char *p = (const char *)pSrc;
- for (size_t i = 0; i < bufLen; i++, p += 2)
- pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]);
-
- if (bufLen < len)
- memset(pDest + bufLen, 0, len - bufLen);
- return true;
-}
-
-MIR_CORE_DLL(bool) hex2binW(const wchar_t *pSrc, void *pData, size_t len)
-{
- if (pSrc == nullptr || pData == nullptr || len == 0)
- return false;
-
- size_t bufLen = wcslen(pSrc)/2;
- if (pSrc[bufLen * 2] != 0 || bufLen > len)
- return false;
-
- BYTE *pDest = (BYTE*)pData;
- const wchar_t *p = (const wchar_t *)pSrc;
- for (size_t i = 0; i < bufLen; i++, p += 2)
- pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]);
-
- if (bufLen < len)
- memset(pDest+bufLen, 0, len - bufLen);
- return true;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma intrinsic(strlen, strcpy, strcat, strcmp, wcslen, wcscpy, wcscat, wcscmp)
-
-MIR_CORE_DLL(size_t) mir_strlen(const char *p)
-{
- return (p) ? strlen(p) : 0;
-}
-
-MIR_CORE_DLL(size_t) mir_wstrlen(const wchar_t *p)
-{
- return (p) ? wcslen(p) : 0;
-}
-
-MIR_CORE_DLL(char*) mir_strcpy(char *dest, const char *src)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr) {
- *dest = 0;
- return dest;
- }
-
- return strcpy(dest, src);
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrcpy(wchar_t *dest, const wchar_t *src)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr) {
- *dest = 0;
- return dest;
- }
-
- return wcscpy(dest, src);
-}
-
-MIR_CORE_DLL(char*) mir_strncpy(char *dest, const char *src, size_t len)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr)
- *dest = 0;
- else
- strncpy_s(dest, len, src, _TRUNCATE);
- return dest;
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrncpy(wchar_t *dest, const wchar_t *src, size_t len)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr)
- *dest = 0;
- else
- wcsncpy_s(dest, len, src, _TRUNCATE);
- return dest;
-}
-
-MIR_CORE_DLL(char*) mir_strcat(char *dest, const char *src)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr) {
- *dest = 0;
- return dest;
- }
-
- return strcat(dest, src);
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrcat(wchar_t *dest, const wchar_t *src)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr) {
- *dest = 0;
- return dest;
- }
-
- return wcscat(dest, src);
-}
-
-MIR_CORE_DLL(char*) mir_strncat(char *dest, const char *src, size_t len)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr)
- *dest = 0;
- else
- strncat_s(dest, len, src, _TRUNCATE);
- return dest;
-}
-
-MIR_CORE_DLL(wchar_t*) mir_wstrncat(wchar_t *dest, const wchar_t *src, size_t len)
-{
- if (dest == nullptr)
- return nullptr;
-
- if (src == nullptr)
- *dest = 0;
- else
- wcsncat_s(dest, len, src, _TRUNCATE);
- return dest;
-}
-
-MIR_CORE_DLL(int) mir_strcmp(const char *p1, const char *p2)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return strcmp(p1, p2);
-}
-
-MIR_CORE_DLL(int) mir_wstrcmp(const wchar_t *p1, const wchar_t *p2)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return wcscmp(p1, p2);
-}
-
-MIR_CORE_DLL(int) mir_strcmpi(const char *p1, const char *p2)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return stricmp(p1, p2);
-}
-
-MIR_CORE_DLL(int) mir_wstrcmpi(const wchar_t *p1, const wchar_t *p2)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return wcsicmp(p1, p2);
-}
-
-MIR_CORE_DLL(int) mir_strncmp(const char *p1, const char *p2, size_t n)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return strncmp(p1, p2, n);
-}
-
-MIR_CORE_DLL(int) mir_wstrncmp(const wchar_t *p1, const wchar_t *p2, size_t n)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return wcsncmp(p1, p2, n);
-}
-
-MIR_CORE_DLL(int) mir_strncmpi(const char *p1, const char *p2, size_t n)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return strnicmp(p1, p2, n);
-}
-
-MIR_CORE_DLL(int) mir_wstrncmpi(const wchar_t *p1, const wchar_t *p2, size_t n)
-{
- if (p1 == nullptr)
- return (p2 == nullptr) ? 0 : -1;
- if (p2 == nullptr)
- return 1;
- return wcsnicmp(p1, p2, n);
-}
-
-MIR_CORE_DLL(const wchar_t*) mir_wstrstri(const wchar_t *s1, const wchar_t *s2)
-{
- for (int i = 0; s1[i]; i++)
- for (int j = i, k = 0; towlower(s1[j]) == towlower(s2[k]); j++, k++)
- if (!s2[k + 1])
- return s1 + i;
-
- return nullptr;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-PGENRANDOM pfnRtlGenRandom;
-
-MIR_CORE_DLL(void) Utils_GetRandom(void *pszDest, size_t cbLen)
-{
- if (pszDest == nullptr || cbLen == 0)
- return;
-
- if (pfnRtlGenRandom != nullptr)
- pfnRtlGenRandom(pszDest, (ULONG)cbLen);
- else {
- srand(time(0));
- BYTE *p = (BYTE*)pszDest;
- for (size_t i = 0; i < cbLen; i++)
- p[i] = rand() & 0xFF;
- }
-}
-
-MIR_CORE_DLL(bool) Utils_IsRtl(const wchar_t *pszwText)
-{
- size_t iLen = mir_wstrlen(pszwText);
- mir_ptr<WORD> infoTypeC2((WORD*)mir_calloc(sizeof(WORD) * (iLen + 2)));
- GetStringTypeW(CT_CTYPE2, pszwText, (int)iLen, infoTypeC2);
-
- for (size_t i = 0; i < iLen; i++)
- if (infoTypeC2[i] == C2_RIGHTTOLEFT)
- return true;
-
- return false;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "stdafx.h"
+
+MIR_CORE_DLL(char*) replaceStr(char* &dest, const char *src)
+{
+ if (dest != nullptr)
+ mir_free(dest);
+
+ return dest = (src != nullptr) ? mir_strdup(src) : nullptr;
+}
+
+MIR_CORE_DLL(wchar_t*) replaceStrW(wchar_t* &dest, const wchar_t *src)
+{
+ if (dest != nullptr)
+ mir_free(dest);
+
+ return dest = (src != nullptr) ? mir_wstrdup(src) : nullptr;
+}
+
+MIR_CORE_DLL(char*) rtrim(char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ char* p = strchr(str, 0);
+ while (--p >= str) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ *p = 0; break;
+ default:
+ return str;
+ }
+ }
+ return str;
+}
+
+MIR_CORE_DLL(wchar_t*) rtrimw(wchar_t *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ wchar_t *p = wcschr(str, 0);
+ while (--p >= str) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ *p = 0; break;
+ default:
+ return str;
+ }
+ }
+ return str;
+}
+
+MIR_CORE_DLL(char*) ltrim(char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ char* p = str;
+ for (;;) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ ++p; break;
+ default:
+ memmove(str, p, strlen(p) + 1);
+ return str;
+ }
+ }
+}
+
+MIR_CORE_DLL(wchar_t*) ltrimw(wchar_t *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ wchar_t *p = str;
+ for (;;) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ ++p; break;
+ default:
+ memmove(str, p, sizeof(wchar_t)*(wcslen(p) + 1));
+ return str;
+ }
+ }
+}
+
+MIR_CORE_DLL(char*) ltrimp(char *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ char *p = str;
+ for (;;) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ ++p; break;
+ default:
+ return p;
+ }
+ }
+}
+
+MIR_CORE_DLL(wchar_t*) ltrimpw(wchar_t *str)
+{
+ if (str == nullptr)
+ return nullptr;
+
+ wchar_t *p = str;
+ for (;;) {
+ switch (*p) {
+ case ' ': case '\t': case '\n': case '\r':
+ ++p; break;
+ default:
+ return p;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(char*) strdel(char *str, size_t len)
+{
+ char* p;
+ for (p = str + len; *p != 0; p++)
+ *(p - len) = *p;
+
+ *(p - len) = '\0';
+ return str;
+}
+
+MIR_CORE_DLL(wchar_t*) strdelw(wchar_t *str, size_t len)
+{
+ wchar_t* p;
+ for (p = str + len; *p != 0; p++)
+ *(p - len) = *p;
+
+ *(p - len) = '\0';
+ return str;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) wildcmp(const char *name, const char *mask)
+{
+ if (name == nullptr || mask == nullptr)
+ return false;
+
+ const char *last = nullptr;
+ for (;; mask++, name++) {
+ if (*mask != '?' && *mask != *name) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++) {
+ while (*mask == '*') {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+MIR_CORE_DLL(int) wildcmpw(const wchar_t *name, const wchar_t *mask)
+{
+ if (name == nullptr || mask == nullptr)
+ return false;
+
+ const wchar_t* last = nullptr;
+ for (;; mask++, name++) {
+ if (*mask != '?' && *mask != *name) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++) {
+ while (*mask == '*') {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+#define _qtoupper(_c) (((_c) >= 'a' && (_c) <= 'z')?((_c)-'a'+'A'):(_c))
+
+MIR_CORE_DLL(int) wildcmpi(const char *name, const char *mask)
+{
+ if (name == nullptr || mask == nullptr)
+ return false;
+
+ const char *last = nullptr;
+ for (;; mask++, name++) {
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++) {
+ while (*mask == '*') {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+MIR_CORE_DLL(int) wildcmpiw(const wchar_t *name, const wchar_t *mask)
+{
+ if (name == nullptr || mask == nullptr)
+ return false;
+
+ const wchar_t* last = nullptr;
+ for (;; mask++, name++) {
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++) {
+ while (*mask == '*') {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static char szHexTable[] = "0123456789abcdef";
+
+MIR_CORE_DLL(char*) bin2hex(const void *pData, size_t len, char *dest)
+{
+ const BYTE *p = (const BYTE*)pData;
+ char *d = dest;
+
+ for (size_t i = 0; i < len; i++, p++) {
+ *d++ = szHexTable[*p >> 4];
+ *d++ = szHexTable[*p & 0x0F];
+ }
+ *d = 0;
+
+ return dest;
+}
+
+MIR_CORE_DLL(wchar_t*) bin2hexW(const void *pData, size_t len, wchar_t *dest)
+{
+ const BYTE *p = (const BYTE*)pData;
+ wchar_t *d = dest;
+
+ for (size_t i = 0; i < len; i++, p++) {
+ *d++ = szHexTable[*p >> 4];
+ *d++ = szHexTable[*p & 0x0F];
+ }
+ *d = 0;
+
+ return dest;
+}
+
+static int hex2dec(int iHex)
+{
+ if (iHex >= '0' && iHex <= '9')
+ return iHex - '0';
+ if (iHex >= 'a' && iHex <= 'f')
+ return iHex - 'a' + 10;
+ if (iHex >= 'A' && iHex <= 'F')
+ return iHex - 'A' + 10;
+ return 0;
+}
+
+MIR_CORE_DLL(bool) hex2bin(const char *pSrc, void *pData, size_t len)
+{
+ if (pSrc == nullptr || pData == nullptr || len == 0)
+ return false;
+
+ size_t bufLen = strlen(pSrc)/2;
+ if (pSrc[bufLen*2] != 0 || bufLen > len)
+ return false;
+
+ BYTE *pDest = (BYTE*)pData;
+ const char *p = (const char *)pSrc;
+ for (size_t i = 0; i < bufLen; i++, p += 2)
+ pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]);
+
+ if (bufLen < len)
+ memset(pDest + bufLen, 0, len - bufLen);
+ return true;
+}
+
+MIR_CORE_DLL(bool) hex2binW(const wchar_t *pSrc, void *pData, size_t len)
+{
+ if (pSrc == nullptr || pData == nullptr || len == 0)
+ return false;
+
+ size_t bufLen = wcslen(pSrc)/2;
+ if (pSrc[bufLen * 2] != 0 || bufLen > len)
+ return false;
+
+ BYTE *pDest = (BYTE*)pData;
+ const wchar_t *p = (const wchar_t *)pSrc;
+ for (size_t i = 0; i < bufLen; i++, p += 2)
+ pDest[i] = hex2dec(p[0]) * 16 + hex2dec(p[1]);
+
+ if (bufLen < len)
+ memset(pDest+bufLen, 0, len - bufLen);
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma intrinsic(strlen, strcpy, strcat, strcmp, wcslen, wcscpy, wcscat, wcscmp)
+
+MIR_CORE_DLL(size_t) mir_strlen(const char *p)
+{
+ return (p) ? strlen(p) : 0;
+}
+
+MIR_CORE_DLL(size_t) mir_wstrlen(const wchar_t *p)
+{
+ return (p) ? wcslen(p) : 0;
+}
+
+MIR_CORE_DLL(char*) mir_strcpy(char *dest, const char *src)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr) {
+ *dest = 0;
+ return dest;
+ }
+
+ return strcpy(dest, src);
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrcpy(wchar_t *dest, const wchar_t *src)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr) {
+ *dest = 0;
+ return dest;
+ }
+
+ return wcscpy(dest, src);
+}
+
+MIR_CORE_DLL(char*) mir_strncpy(char *dest, const char *src, size_t len)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr)
+ *dest = 0;
+ else
+ strncpy_s(dest, len, src, _TRUNCATE);
+ return dest;
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrncpy(wchar_t *dest, const wchar_t *src, size_t len)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr)
+ *dest = 0;
+ else
+ wcsncpy_s(dest, len, src, _TRUNCATE);
+ return dest;
+}
+
+MIR_CORE_DLL(char*) mir_strcat(char *dest, const char *src)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr) {
+ *dest = 0;
+ return dest;
+ }
+
+ return strcat(dest, src);
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrcat(wchar_t *dest, const wchar_t *src)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr) {
+ *dest = 0;
+ return dest;
+ }
+
+ return wcscat(dest, src);
+}
+
+MIR_CORE_DLL(char*) mir_strncat(char *dest, const char *src, size_t len)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr)
+ *dest = 0;
+ else
+ strncat_s(dest, len, src, _TRUNCATE);
+ return dest;
+}
+
+MIR_CORE_DLL(wchar_t*) mir_wstrncat(wchar_t *dest, const wchar_t *src, size_t len)
+{
+ if (dest == nullptr)
+ return nullptr;
+
+ if (src == nullptr)
+ *dest = 0;
+ else
+ wcsncat_s(dest, len, src, _TRUNCATE);
+ return dest;
+}
+
+MIR_CORE_DLL(int) mir_strcmp(const char *p1, const char *p2)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return strcmp(p1, p2);
+}
+
+MIR_CORE_DLL(int) mir_wstrcmp(const wchar_t *p1, const wchar_t *p2)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return wcscmp(p1, p2);
+}
+
+MIR_CORE_DLL(int) mir_strcmpi(const char *p1, const char *p2)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return stricmp(p1, p2);
+}
+
+MIR_CORE_DLL(int) mir_wstrcmpi(const wchar_t *p1, const wchar_t *p2)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return wcsicmp(p1, p2);
+}
+
+MIR_CORE_DLL(int) mir_strncmp(const char *p1, const char *p2, size_t n)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return strncmp(p1, p2, n);
+}
+
+MIR_CORE_DLL(int) mir_wstrncmp(const wchar_t *p1, const wchar_t *p2, size_t n)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return wcsncmp(p1, p2, n);
+}
+
+MIR_CORE_DLL(int) mir_strncmpi(const char *p1, const char *p2, size_t n)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return strnicmp(p1, p2, n);
+}
+
+MIR_CORE_DLL(int) mir_wstrncmpi(const wchar_t *p1, const wchar_t *p2, size_t n)
+{
+ if (p1 == nullptr)
+ return (p2 == nullptr) ? 0 : -1;
+ if (p2 == nullptr)
+ return 1;
+ return wcsnicmp(p1, p2, n);
+}
+
+#ifdef _MSC_VER
+MIR_CORE_DLL(const wchar_t*) mir_wstrstri(const wchar_t *s1, const wchar_t *s2)
+{
+ for (int i = 0; s1[i]; i++)
+ for (int j = i, k = 0; towlower(s1[j]) == towlower(s2[k]); j++, k++)
+ if (!s2[k + 1])
+ return s1 + i;
+
+ return nullptr;
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+PGENRANDOM pfnRtlGenRandom;
+
+MIR_CORE_DLL(void) Utils_GetRandom(void *pszDest, size_t cbLen)
+{
+ if (pszDest == nullptr || cbLen == 0)
+ return;
+
+ if (pfnRtlGenRandom != nullptr)
+ pfnRtlGenRandom(pszDest, (uint32_t)cbLen);
+ else {
+ srand(time(0));
+ BYTE *p = (BYTE*)pszDest;
+ for (size_t i = 0; i < cbLen; i++)
+ p[i] = rand() & 0xFF;
+ }
+}
+
+MIR_CORE_DLL(bool) Utils_IsRtl(const wchar_t *pszwText)
+{
+ #ifdef _MSC_VER
+ size_t iLen = mir_wstrlen(pszwText);
+ mir_ptr<WORD> infoTypeC2((WORD*)mir_calloc(sizeof(WORD) * (iLen + 2)));
+ GetStringTypeW(CT_CTYPE2, pszwText, (int)iLen, infoTypeC2);
+
+ for (size_t i = 0; i < iLen; i++)
+ if (infoTypeC2[i] == C2_RIGHTTOLEFT)
+ return true;
+ #endif
+
+ return false;
+}
diff --git a/src/miranda32/miranda32.cbp b/src/miranda32/miranda32.cbp
new file mode 100644
index 0000000000..27040ad943
--- /dev/null
+++ b/src/miranda32/miranda32.cbp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build />
+ <Extensions />
+ </Project>
+</CodeBlocks_project_file>
diff --git a/src/miranda32/miranda32.layout b/src/miranda32/miranda32.layout
new file mode 100644
index 0000000000..00cf04d503
--- /dev/null
+++ b/src/miranda32/miranda32.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <FileVersion major="1" minor="0" />
+ <ActiveTarget name="Debug x64" />
+</CodeBlocks_layout_file>