From de40f3be3f08487937525c2ef096dad665dda61d Mon Sep 17 00:00:00 2001 From: dartraiden Date: Sat, 14 Jan 2023 01:30:59 +0300 Subject: Convert sources to CR+LF --- include/m_database.h | 1598 ++++++++++++------------- include/m_db_int.h | 814 ++++++------- include/m_gui.h | 3212 +++++++++++++++++++++++++------------------------- 3 files changed, 2812 insertions(+), 2812 deletions(-) (limited to 'include') diff --git a/include/m_database.h b/include/m_database.h index fda99b4b2f..ad0e16e60b 100644 --- a/include/m_database.h +++ b/include/m_database.h @@ -1,799 +1,799 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (C) 2012-23 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); - -// Checks if a module doesn't contain any settings (for the contact given) - -MIR_CORE_DLL(bool) db_is_module_empty(MCONTACT hContact, const char *module); - -// Copies a module to another module for the contact given (0 by default) - -EXTERN_C MIR_CORE_DLL(int) db_copy_module(const char *szModule, const char *szNewModule, MCONTACT hContact = 0); - -// 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 -{ - uint8_t type; - union { - uint8_t bVal; char cVal; - uint16_t wVal; short sVal; - uint32_t dVal; long lVal; - struct { - union { - char *pszVal; - wchar_t *pwszVal; - }; - uint16_t cchVal; //only used for db/contact/getsettingstatic - }; - struct { - uint16_t cpbVal; - uint8_t *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 - uint32_t 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. - uint32_t flags; // combination of DBEF_* flags - uint16_t 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); - -// Tries to find an event by its id if present -// if an event is found, it's edited, otherwise a new event is added - -EXTERN_C MIR_CORE_DLL(MEVENT) db_event_replace(MCONTACT hContact, 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 - -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 uint32_t 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); - -// Updates the server ID associated with an event -// Returns 0 on success or a failure otherwise - -EXTERN_C MIR_CORE_DLL(int) db_event_updateId(MEVENT hDbEvent, 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(uint32_t) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t 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, uint8_t val); -EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, uint16_t val); -EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t 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, const 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 -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 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 -// 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 - uint32_t 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)(*(uint32_t*)&dbei->pBlob[sizeof(uint32_t)]); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// 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, -// 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 uint8_t DBGetContactSettingRangedByte(MCONTACT hContact, const char *szModule, const char *szSetting, uint8_t errorValue, uint8_t minValue, uint8_t maxValue) -{ - uint8_t bVal = db_get_b(hContact, szModule, szSetting, errorValue); - return (bVal < minValue || bVal > maxValue) ? errorValue : bVal; -} - -__inline uint16_t DBGetContactSettingRangedWord(MCONTACT hContact, const char *szModule, const char *szSetting, uint16_t errorValue, uint16_t minValue, uint16_t maxValue) -{ - uint16_t wVal = db_get_w(hContact, szModule, szSetting, errorValue); - return (wVal < minValue || wVal > maxValue) ? errorValue : wVal; -} - -__inline uint32_t DBGetContactSettingRangedDword(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t errorValue, uint32_t minValue, uint32_t maxValue) -{ - uint32_t dwVal = db_get_dw(hContact, szModule, szSetting, errorValue); - return (dwVal < minValue || dwVal > maxValue) ? errorValue : dwVal; -} - -#endif - -namespace DB -{ - MIR_APP_DLL(bool) IsDuplicateEvent(MCONTACT hContact, DBEVENTINFO &dbei); - - ///////////////////////////////////////////////////////////////////////////////////////// - // 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(uint32_t), hContact(uint32_t), nick(UTF8), firstName(UTF8), lastName(UTF8), email(UTF8), reason(UTF8) - - #pragma warning(disable : 4251) - - class MIR_APP_EXPORT AUTH_BLOB - { - MCONTACT m_hContact; - uint32_t m_dwUin; - ptrA m_szNick, m_szFirstName, m_szLastName, m_szEmail, m_szReason; - uint32_t 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 uint8_t*() { return makeBlob(); } - - __forceinline uint32_t 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 uint32_t get_uin() const { return m_dwUin; } - __forceinline void set_uin(uint32_t 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-23 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); + +// Checks if a module doesn't contain any settings (for the contact given) + +MIR_CORE_DLL(bool) db_is_module_empty(MCONTACT hContact, const char *module); + +// Copies a module to another module for the contact given (0 by default) + +EXTERN_C MIR_CORE_DLL(int) db_copy_module(const char *szModule, const char *szNewModule, MCONTACT hContact = 0); + +// 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 +{ + uint8_t type; + union { + uint8_t bVal; char cVal; + uint16_t wVal; short sVal; + uint32_t dVal; long lVal; + struct { + union { + char *pszVal; + wchar_t *pwszVal; + }; + uint16_t cchVal; //only used for db/contact/getsettingstatic + }; + struct { + uint16_t cpbVal; + uint8_t *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 + uint32_t 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. + uint32_t flags; // combination of DBEF_* flags + uint16_t 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); + +// Tries to find an event by its id if present +// if an event is found, it's edited, otherwise a new event is added + +EXTERN_C MIR_CORE_DLL(MEVENT) db_event_replace(MCONTACT hContact, 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 + +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 uint32_t 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); + +// Updates the server ID associated with an event +// Returns 0 on success or a failure otherwise + +EXTERN_C MIR_CORE_DLL(int) db_event_updateId(MEVENT hDbEvent, 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(uint32_t) db_get_dw(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t 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, uint8_t val); +EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_w(MCONTACT hContact, const char *szModule, const char *szSetting, uint16_t val); +EXTERN_C MIR_CORE_DLL(INT_PTR) db_set_dw(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t 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, const 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 +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 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 +// 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 + uint32_t 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)(*(uint32_t*)&dbei->pBlob[sizeof(uint32_t)]); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// 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, +// 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 uint8_t DBGetContactSettingRangedByte(MCONTACT hContact, const char *szModule, const char *szSetting, uint8_t errorValue, uint8_t minValue, uint8_t maxValue) +{ + uint8_t bVal = db_get_b(hContact, szModule, szSetting, errorValue); + return (bVal < minValue || bVal > maxValue) ? errorValue : bVal; +} + +__inline uint16_t DBGetContactSettingRangedWord(MCONTACT hContact, const char *szModule, const char *szSetting, uint16_t errorValue, uint16_t minValue, uint16_t maxValue) +{ + uint16_t wVal = db_get_w(hContact, szModule, szSetting, errorValue); + return (wVal < minValue || wVal > maxValue) ? errorValue : wVal; +} + +__inline uint32_t DBGetContactSettingRangedDword(MCONTACT hContact, const char *szModule, const char *szSetting, uint32_t errorValue, uint32_t minValue, uint32_t maxValue) +{ + uint32_t dwVal = db_get_dw(hContact, szModule, szSetting, errorValue); + return (dwVal < minValue || dwVal > maxValue) ? errorValue : dwVal; +} + +#endif + +namespace DB +{ + MIR_APP_DLL(bool) IsDuplicateEvent(MCONTACT hContact, DBEVENTINFO &dbei); + + ///////////////////////////////////////////////////////////////////////////////////////// + // 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(uint32_t), hContact(uint32_t), nick(UTF8), firstName(UTF8), lastName(UTF8), email(UTF8), reason(UTF8) + + #pragma warning(disable : 4251) + + class MIR_APP_EXPORT AUTH_BLOB + { + MCONTACT m_hContact; + uint32_t m_dwUin; + ptrA m_szNick, m_szFirstName, m_szLastName, m_szEmail, m_szReason; + uint32_t 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 uint8_t*() { return makeBlob(); } + + __forceinline uint32_t 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 uint32_t get_uin() const { return m_dwUin; } + __forceinline void set_uin(uint32_t 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 2516208764..661ad565f4 100644 --- a/include/m_db_int.h +++ b/include/m_db_int.h @@ -1,407 +1,407 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-23 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 -#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 -{ - uint32_t 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, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) 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_(int, UpdateEventId)(MEVENT hDbEvent, const char *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 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, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) 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; - STDMETHODIMP_(int) UpdateEventId(MEVENT hDbEvent, const char *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:\..\.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-23 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 +#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 +{ + uint32_t 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, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) 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_(int, UpdateEventId)(MEVENT hDbEvent, const char *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 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, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) 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; + STDMETHODIMP_(int) UpdateEventId(MEVENT hDbEvent, const char *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:\..\.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 48041ff696..60d4dc2933 100644 --- a/include/m_gui.h +++ b/include/m_gui.h @@ -1,1606 +1,1606 @@ -/* - -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-23 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 -#endif // _WINDOWS - -#include -#include -#include - -#pragma warning(disable:4355 4251 4481) - -///////////////////////////////////////////////////////////////////////////////////////// -// helpers for the option's visualization - -template -struct CMDBTraits -{ -}; - -template<> -struct CMDBTraits<1> -{ - typedef uint8_t 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 uint16_t 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 uint32_t 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 uint32_t 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; } - - __forceinline void Delete() const - { db_unset(0, m_szModuleName, 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 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::Get(m_szModuleName, m_szSetting, m_default); - } - - __forceinline Type operator= (Type value) - { - #ifdef _MSC_VER - CMDBTraits::Set(m_szModuleName, m_szSetting, (CMDBTraits::DBType)value); - #else - CMDBTraits::Set(m_szModuleName, m_szSetting, value); - #endif - return value; - } - -private: - Type m_default; -}; - -template<> -class CMOption : 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 m_value; -}; - -template<> -class CMOption : 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 m_value; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// CDbLink - -class MIR_CORE_EXPORT CDataLink -{ -protected: - uint8_t m_type; - -public: - __inline CDataLink(uint8_t type) : m_type(type) {} - virtual ~CDataLink() {} - - __inline uint8_t GetDataType() const { return m_type; } - - virtual uint32_t LoadInt() = 0; - virtual void SaveInt(uint32_t 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; - - uint32_t m_iDefault; - wchar_t *m_szDefault; - - DBVARIANT dbv; - -public: - CDbLink(const char *szModule, const char *szSetting, uint8_t type, uint32_t iValue); - CDbLink(const char *szModule, const char *szSetting, uint8_t type, wchar_t *szValue); - ~CDbLink(); - - uint32_t LoadInt() override; - void SaveInt(uint32_t value) override; - - wchar_t* LoadText() override; - void SaveText(wchar_t *value) override; -}; - -template -class CMOptionLink : public CDataLink -{ -private: - CMOption *m_option; - -public: - __forceinline CMOptionLink(CMOption &option) : - CDataLink(CMDBTraits::DBTypeId), m_option(&option) - {} - - __forceinline uint32_t LoadInt() override { return (uint32_t)(T)*m_option; } - __forceinline void SaveInt(uint32_t value) override { *m_option = (T)value; } - - __forceinline wchar_t* LoadText() override { return nullptr; } - __forceinline void SaveText(wchar_t*) override {} -}; - -template<> -class CMOptionLink : public CDataLink -{ -private: - typedef wchar_t *T; - CMOption *m_option; - -public: - __forceinline CMOptionLink(CMOption &option) : - CDataLink(DBVT_WCHAR), m_option(&option) - {} - - __forceinline uint32_t LoadInt() override { return 0; } - __forceinline void SaveInt(uint32_t) override { } - - __forceinline wchar_t* LoadText() override { return *m_option; } - __forceinline void SaveText(wchar_t *value) override { *m_option = value; } -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// CCtrlBase - -struct CContextMenuPos -{ - const class 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 MWindow 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(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t /*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: - MWindow m_hwnd = nullptr; // must be the first data item - int m_idCtrl; - bool m_bChanged = false, m_bSilent = false, m_bUseSystemColors = false, m_bNotifiable = false; - CDlgBase *m_parentWnd; - -public: - CCallback OnChange; - CCallback 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(MWindow hwnd, UINT msg, WPARAM wParam, LPARAM lParam); -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// 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, uint8_t type, uint32_t 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 uint8_t GetDataType() { return m_dbLink ? m_dbLink->GetDataType() : DBVT_DELETED; } - __inline uint32_t LoadInt() { return m_dbLink ? m_dbLink->LoadInt() : 0; } - __inline void SaveInt(uint32_t 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); } -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// 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(MWindow hwnd); - - void SetCaption(const wchar_t *ptszCaption); - void SetDraw(bool bEnable); - void NotifyChange(void); // sends a notification to a parent window - - HINSTANCE GetInst() const; - - __forceinline MWindow 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(MWindow hwnd) { m_hwndParent = hwnd; } - - __forceinline CCtrlBase* operator[](int iControlId) { return FindControl(iControlId); } - - static CDlgBase* Find(MWindow hwnd); - -protected: - MWindow m_hwnd = nullptr; // must be the first data item - MWindow m_hwndParent = nullptr; - int m_idDialog; - - bool m_isModal = false; - bool m_bInitialized = false; - bool m_forceResizable = false; - bool m_bFixedSize; - 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 }; - uint8_t 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 OnResize(); - virtual void OnReset(); - virtual void OnChange(); - - // main dialog procedure - virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam); - - CCallback 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, uint8_t type, uint32_t iValue); - void CreateLink(class CCtrlData& ctrl, const char *szSetting, wchar_t *szValue); - - template - __inline void CreateLink(CCtrlData& ctrl, CMOption &option) - { - ctrl.CreateDbLink(new CMOptionLink(option)); - } - - // win32 stuff - void ThemeDialogBackground(BOOL tabbed); - -private: - LIST m_timers; - LIST 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(MWindow hwnd, LPARAM lParam); - static INT_PTR CALLBACK GlobalDlgProc(MWindow hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - static int GlobalDlgResizer(MWindow 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 MWindow 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 OnEvent; - -protected: - UINT_PTR m_idEvent; - CDlgBase* m_wnd; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// 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(MWindow hwndCtrl, uint16_t idCtrl, uint16_t idCode) override; - - CCallback 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(MWindow hwndCtrl, uint16_t idCtrl, uint16_t idCode) override; - - CCallback 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(uint16_t max, uint16_t min = 0); - void SetPosition(uint16_t value); - void SetStep(uint16_t value); - uint16_t Move(uint16_t 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, uint32_t flags); - HANDLE FindContact(MCONTACT hContact); - HANDLE FindGroup(MGROUP hGroup); - COLORREF GetBkColor() const; - bool GetCheck(HANDLE hItem) const; - int GetCount() const; - MWindow GetEditControl() const; - uint32_t GetExStyle() const; - uint32_t GetExpand(HANDLE hItem) const; - int GetExtraColumns() const; - uint8_t 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, uint32_t flags) const; - HANDLE GetSelection() const; - HANDLE HitTest(int x, int y, uint32_t *hitTest) const; - void SelectItem(HANDLE hItem); - void SetBkColor(COLORREF clBack); - void SetCheck(HANDLE hItem, bool check); - void SetExStyle(uint32_t 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(uint32_t modes); - void SetUseGroups(bool state); - - struct TEventInfo - { - CCtrlClc *ctrl; - NMCLISTCONTROL *info; - }; - - CCallback OnExpanded; - CCallback OnListRebuilt; - CCallback OnItemChecked; - CCallback OnDragging; - CCallback OnDropped; - CCallback OnListSizeChange; - CCallback OnOptionsChanged; - CCallback OnDragStop; - CCallback OnNewContact; - CCallback OnContactMoved; - CCallback OnCheckChanged; - CCallback OnClick; - -protected: - BOOL OnNotify(int idCtrl, NMHDR *pnmh) override; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// CCtrlCheck - -class MIR_CORE_EXPORT CCtrlCheck : public CCtrlData -{ - typedef CCtrlData CSuper; - -public: - CCtrlCheck(CDlgBase *dlg, int ctrlId); - BOOL OnCommand(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t /*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(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t /*idCode*/) override; - - bool OnApply() override; - void OnReset() override; - - uint32_t GetColor(); - void SetColor(uint32_t 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(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t 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(MWindow hwndCtrl, uint16_t idCtrl, uint16_t 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; - - int16_t m_wMin, m_wMax, m_wCurr; - - BOOL OnNotify(int, NMHDR*) override; - -public: - CCtrlSpin(CDlgBase *dlg, int ctrlId, int16_t max = 100, int16_t min = 0); - - bool OnApply() override; - void OnReset() override; - - int16_t GetPosition(); - void SetPosition(int16_t 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 OnDblClick; - CCallback OnSelCancel; - CCallback OnSelChange; - -protected: - BOOL OnCommand(MWindow hwndCtrl, uint16_t idCtrl, uint16_t 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(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t 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 OnCloseup; - CCallback OnDropdown; - CCallback OnKillFocus; - CCallback 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 - uint32_t 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); - MWindow 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(LVBKIMAGE *plvbki) const; - UINT GetCallbackMask() const; - BOOL GetCheckState(UINT iIndex) const; - void GetColumn(int iCol, LVCOLUMN *pcol) const; - void GetColumnOrderArray(int iCount, int *lpiArray) const; - int GetColumnWidth(int iCol) const; - int GetCountPerPage() const; - MWindow GetEditControl() const; - uint32_t GetExtendedListViewStyle() const; - int GetFocusedGroup() const; - int GetGroupCount() const; - void GetGroupInfo(int iGroupId, LVGROUP *pgrp) const; - void GetGroupInfoByIndex(int iIndex, LVGROUP *pgrp) const; - void GetGroupMetrics(LVGROUPMETRICS *pGroupMetrics) const; - UINT GetGroupState(UINT dwGroupId, UINT dwMask) const; - MWindow GetHeader() const; - HCURSOR GetHotCursor() const; - int GetHotItem() const; - uint32_t GetHoverTime() const; - HIMAGELIST GetImageList(int iImageList) const; - BOOL GetInsertMark(LVINSERTMARK *plvim) const; - COLORREF GetInsertMarkColor() const; - int GetInsertMarkRect(RECT *prc) const; - BOOL GetISearchString(LPSTR lpsz) const; - bool GetItem(LVITEM *pitem) const; - int GetItemCount() const; - void GetItemPosition(int i, POINT *ppt) const; - void GetItemRect(int i, RECT *prc, int code) const; - uint32_t 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(LVTILEINFO *plvtinfo) const; - void GetTileViewInfo(LVTILEVIEWINFO *plvtvinfo) const; - MWindow GetToolTips() const; - int GetTopIndex() const; - BOOL GetUnicodeFormat() const; - uint32_t GetView() const; - BOOL GetViewRect(RECT *prc) const; - void GetWorkAreas(int nWorkAreas, RECT *lprc) const; - BOOL HasGroup(int dwGroupId); - int HitTest(LVHITTESTINFO *pinfo) const; - int HitTestEx(LVHITTESTINFO *pinfo); - int InsertColumn(int iCol, const LVCOLUMN *pcol); - int InsertGroup(int index, LVGROUP *pgrp); - void InsertGroupSorted(LVINSERTGROUPSORTED *structInsert); - int InsertItem(const 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(LVBKIMAGE *plvbki); - BOOL SetCallbackMask(UINT mask); - void SetCheckState(UINT iIndex, BOOL fCheck); - BOOL SetColumn(int iCol, LVCOLUMN *pcol); - BOOL SetColumnOrderArray(int iCount, int *lpiArray); - BOOL SetColumnWidth(int iCol, int cx); - void SetExtendedListViewStyle(uint32_t dwExStyle); - void SetExtendedListViewStyleEx(uint32_t dwExMask, uint32_t dwExStyle); - int SetGroupInfo(int iGroupId, LVGROUP *pgrp); - void SetGroupMetrics(LVGROUPMETRICS *pGroupMetrics); - void SetGroupState(UINT dwGroupId, UINT dwMask, UINT dwState); - HCURSOR SetHotCursor(HCURSOR hCursor); - int SetHotItem(int iIndex); - void SetHoverTime(uint32_t dwHoverTime); - uint32_t SetIconSpacing(int cx, int cy); - HIMAGELIST SetImageList(HIMAGELIST himl, int iImageList); - BOOL SetInfoTip(LVSETINFOTIP *plvSetInfoTip); - BOOL SetInsertMark(LVINSERTMARK *plvim); - COLORREF SetInsertMarkColor(COLORREF color); - BOOL SetItem(const LVITEM *pitem); - void SetItemCount(int cItems); - void SetItemCountEx(int cItems, uint32_t 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(LVTILEINFO *plvtinfo); - BOOL SetTileViewInfo(LVTILEVIEWINFO *plvtvinfo); - MWindow SetToolTips(MWindow ToolTip); - BOOL SetUnicodeFormat(BOOL fUnicode); - int SetView(uint32_t iView); - void SetWorkAreas(int nWorkAreas, RECT *lprc); - int SubItemHitTest(LVHITTESTINFO *pInfo) const; - int SubItemHitTestEx(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 { - NMHDR *nmhdr; - NMLISTVIEW *nmlv; - NMLVDISPINFO *nmlvdi; - NMLVSCROLL *nmlvscr; - NMLVGETINFOTIP *nmlvit; - NMLVFINDITEM *nmlvfi; - NMITEMACTIVATE *nmlvia; - NMLVKEYDOWN *nmlvkey; - NMLVCUSTOMDRAW *nmcd; - }; - }; - - CCallback OnBeginDrag; - CCallback OnBeginLabelEdit; - CCallback OnBeginRDrag; - CCallback OnBeginScroll; - CCallback OnColumnClick; - CCallback OnCustomDraw; - CCallback OnDeleteAllItems; - CCallback OnDeleteItem; - CCallback OnClick; - CCallback OnDoubleClick; - CCallback OnEndLabelEdit; - CCallback OnEndScroll; - CCallback OnGetDispInfo; - CCallback OnGetInfoTip; - CCallback OnHotTrack; - CCallback OnIncrementalSearch; - CCallback OnInsertItem; - CCallback OnItemActivate; - CCallback OnItemChanged; - CCallback OnItemChanging; - CCallback OnKeyDown; - CCallback OnMarqueeBegin; - CCallback 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); - MWindow EditLabel(HTREEITEM hItem); - void EndEditLabelNow(BOOL cancel); - void EnsureVisible(HTREEITEM hItem); - void Expand(HTREEITEM hItem, uint32_t flag); - COLORREF GetBkColor() const; - uint32_t GetCheckState(HTREEITEM hItem) const; - HTREEITEM GetChild(HTREEITEM hItem) const; - int GetCount() const; - HTREEITEM GetDropHilight() const; - MWindow 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; - uint32_t GetItemState(HTREEITEM hItem, uint32_t stateMask) const; - HTREEITEM GetLastVisible() const; - COLORREF GetLineColor() const; - HTREEITEM GetNextItem(HTREEITEM hItem, uint32_t 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; - uint32_t GetScrollTime() const; - HTREEITEM GetSelection() const; - COLORREF GetTextColor() const; - MWindow GetToolTips() const; - BOOL GetUnicodeFormat() const; - unsigned GetVisibleCount() const; - HTREEITEM HitTest(TVHITTESTINFO *hti) const; - HTREEITEM InsertItem(TVINSERTSTRUCT *tvis); - void Select(HTREEITEM hItem, uint32_t flag); - void SelectDropTarget(HTREEITEM hItem); - void SelectItem(HTREEITEM hItem); - void SelectSetFirstVisible(HTREEITEM hItem); - COLORREF SetBkColor(COLORREF clBack); - void SetCheckState(HTREEITEM hItem, uint32_t state); - HIMAGELIST 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, uint32_t state, uint32_t stateMask); - COLORREF SetLineColor(COLORREF clLine); - void SetScrollTime(UINT uMaxScrollTime); - COLORREF SetTextColor(COLORREF clText); - MWindow SetToolTips(MWindow 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 OnBeginDrag; - CCallback OnBeginLabelEdit; - CCallback OnBeginRDrag; - CCallback OnCustomDraw; - CCallback OnDeleteItem; - CCallback OnEndLabelEdit; - CCallback OnGetDispInfo; - CCallback OnGetInfoTip; - CCallback OnItemChanged; - CCallback OnItemExpanded; - CCallback OnItemExpanding; - CCallback OnKeyDown; - CCallback OnRightClick; - CCallback OnSelChanged; - CCallback OnSelChanging; - CCallback OnSetDispInfo; - CCallback OnSingleExpand; - -protected: - void OnInit() 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 &option); - void AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, bool &option); - void AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, uint32_t &option, uint32_t mask); - - 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; - - union - { - CMOption *m_option; - bool *m_pBool; - struct - { - uint32_t *m_pDword; - uint32_t m_mask; - }; - }; - - HTREEITEM m_hItem = nullptr; - enum OptionItemType { CMOPTION = 1, BOOL = 2, MASK = 3 }; - OptionItemType m_type; - - COptionsItem(const wchar_t *pwszSection, const wchar_t *pwszName, OptionItemType type) : - m_pwszSection(pwszSection), - m_pwszName(pwszName), - m_type(type) - {} - }; - - OBJLIST m_options; - - void ProcessItemClick(HTREEITEM hti); -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// CCtrlPages - -#define PSN_INFOCHANGED 1 - -// 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 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, uint8_t type, uint32_t iValue); - void CreateLink(CCtrlData &ctrl, const char *szSetting, wchar_t *szValue); - - template - __inline void CreateLink(CCtrlData &ctrl, CMOption &option) - { - ctrl.CreateDbLink(new CMOptionLink(option)); - } - - __inline PROTO_INTERFACE *GetProtoInterface() { return m_proto_interface; } - - void SetStatusText(const wchar_t *statusText); - -protected: - PROTO_INTERFACE *m_proto_interface; - MWindow 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 -class CProtoDlgBase : public CProtoIntDlgBase -{ - typedef CProtoIntDlgBase CSuper; - -public: - __inline CProtoDlgBase(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-23 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 +#endif // _WINDOWS + +#include +#include +#include + +#pragma warning(disable:4355 4251 4481) + +///////////////////////////////////////////////////////////////////////////////////////// +// helpers for the option's visualization + +template +struct CMDBTraits +{ +}; + +template<> +struct CMDBTraits<1> +{ + typedef uint8_t 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 uint16_t 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 uint32_t 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 uint32_t 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; } + + __forceinline void Delete() const + { db_unset(0, m_szModuleName, 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 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::Get(m_szModuleName, m_szSetting, m_default); + } + + __forceinline Type operator= (Type value) + { + #ifdef _MSC_VER + CMDBTraits::Set(m_szModuleName, m_szSetting, (CMDBTraits::DBType)value); + #else + CMDBTraits::Set(m_szModuleName, m_szSetting, value); + #endif + return value; + } + +private: + Type m_default; +}; + +template<> +class CMOption : 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 m_value; +}; + +template<> +class CMOption : 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 m_value; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// CDbLink + +class MIR_CORE_EXPORT CDataLink +{ +protected: + uint8_t m_type; + +public: + __inline CDataLink(uint8_t type) : m_type(type) {} + virtual ~CDataLink() {} + + __inline uint8_t GetDataType() const { return m_type; } + + virtual uint32_t LoadInt() = 0; + virtual void SaveInt(uint32_t 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; + + uint32_t m_iDefault; + wchar_t *m_szDefault; + + DBVARIANT dbv; + +public: + CDbLink(const char *szModule, const char *szSetting, uint8_t type, uint32_t iValue); + CDbLink(const char *szModule, const char *szSetting, uint8_t type, wchar_t *szValue); + ~CDbLink(); + + uint32_t LoadInt() override; + void SaveInt(uint32_t value) override; + + wchar_t* LoadText() override; + void SaveText(wchar_t *value) override; +}; + +template +class CMOptionLink : public CDataLink +{ +private: + CMOption *m_option; + +public: + __forceinline CMOptionLink(CMOption &option) : + CDataLink(CMDBTraits::DBTypeId), m_option(&option) + {} + + __forceinline uint32_t LoadInt() override { return (uint32_t)(T)*m_option; } + __forceinline void SaveInt(uint32_t value) override { *m_option = (T)value; } + + __forceinline wchar_t* LoadText() override { return nullptr; } + __forceinline void SaveText(wchar_t*) override {} +}; + +template<> +class CMOptionLink : public CDataLink +{ +private: + typedef wchar_t *T; + CMOption *m_option; + +public: + __forceinline CMOptionLink(CMOption &option) : + CDataLink(DBVT_WCHAR), m_option(&option) + {} + + __forceinline uint32_t LoadInt() override { return 0; } + __forceinline void SaveInt(uint32_t) override { } + + __forceinline wchar_t* LoadText() override { return *m_option; } + __forceinline void SaveText(wchar_t *value) override { *m_option = value; } +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// CCtrlBase + +struct CContextMenuPos +{ + const class 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 MWindow 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(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t /*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: + MWindow m_hwnd = nullptr; // must be the first data item + int m_idCtrl; + bool m_bChanged = false, m_bSilent = false, m_bUseSystemColors = false, m_bNotifiable = false; + CDlgBase *m_parentWnd; + +public: + CCallback OnChange; + CCallback 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(MWindow hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// 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, uint8_t type, uint32_t 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 uint8_t GetDataType() { return m_dbLink ? m_dbLink->GetDataType() : DBVT_DELETED; } + __inline uint32_t LoadInt() { return m_dbLink ? m_dbLink->LoadInt() : 0; } + __inline void SaveInt(uint32_t 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); } +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// 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(MWindow hwnd); + + void SetCaption(const wchar_t *ptszCaption); + void SetDraw(bool bEnable); + void NotifyChange(void); // sends a notification to a parent window + + HINSTANCE GetInst() const; + + __forceinline MWindow 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(MWindow hwnd) { m_hwndParent = hwnd; } + + __forceinline CCtrlBase* operator[](int iControlId) { return FindControl(iControlId); } + + static CDlgBase* Find(MWindow hwnd); + +protected: + MWindow m_hwnd = nullptr; // must be the first data item + MWindow m_hwndParent = nullptr; + int m_idDialog; + + bool m_isModal = false; + bool m_bInitialized = false; + bool m_forceResizable = false; + bool m_bFixedSize; + 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 }; + uint8_t 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 OnResize(); + virtual void OnReset(); + virtual void OnChange(); + + // main dialog procedure + virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam); + + CCallback 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, uint8_t type, uint32_t iValue); + void CreateLink(class CCtrlData& ctrl, const char *szSetting, wchar_t *szValue); + + template + __inline void CreateLink(CCtrlData& ctrl, CMOption &option) + { + ctrl.CreateDbLink(new CMOptionLink(option)); + } + + // win32 stuff + void ThemeDialogBackground(BOOL tabbed); + +private: + LIST m_timers; + LIST 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(MWindow hwnd, LPARAM lParam); + static INT_PTR CALLBACK GlobalDlgProc(MWindow hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + static int GlobalDlgResizer(MWindow 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 MWindow 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 OnEvent; + +protected: + UINT_PTR m_idEvent; + CDlgBase* m_wnd; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// 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(MWindow hwndCtrl, uint16_t idCtrl, uint16_t idCode) override; + + CCallback 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(MWindow hwndCtrl, uint16_t idCtrl, uint16_t idCode) override; + + CCallback 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(uint16_t max, uint16_t min = 0); + void SetPosition(uint16_t value); + void SetStep(uint16_t value); + uint16_t Move(uint16_t 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, uint32_t flags); + HANDLE FindContact(MCONTACT hContact); + HANDLE FindGroup(MGROUP hGroup); + COLORREF GetBkColor() const; + bool GetCheck(HANDLE hItem) const; + int GetCount() const; + MWindow GetEditControl() const; + uint32_t GetExStyle() const; + uint32_t GetExpand(HANDLE hItem) const; + int GetExtraColumns() const; + uint8_t 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, uint32_t flags) const; + HANDLE GetSelection() const; + HANDLE HitTest(int x, int y, uint32_t *hitTest) const; + void SelectItem(HANDLE hItem); + void SetBkColor(COLORREF clBack); + void SetCheck(HANDLE hItem, bool check); + void SetExStyle(uint32_t 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(uint32_t modes); + void SetUseGroups(bool state); + + struct TEventInfo + { + CCtrlClc *ctrl; + NMCLISTCONTROL *info; + }; + + CCallback OnExpanded; + CCallback OnListRebuilt; + CCallback OnItemChecked; + CCallback OnDragging; + CCallback OnDropped; + CCallback OnListSizeChange; + CCallback OnOptionsChanged; + CCallback OnDragStop; + CCallback OnNewContact; + CCallback OnContactMoved; + CCallback OnCheckChanged; + CCallback OnClick; + +protected: + BOOL OnNotify(int idCtrl, NMHDR *pnmh) override; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// CCtrlCheck + +class MIR_CORE_EXPORT CCtrlCheck : public CCtrlData +{ + typedef CCtrlData CSuper; + +public: + CCtrlCheck(CDlgBase *dlg, int ctrlId); + BOOL OnCommand(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t /*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(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t /*idCode*/) override; + + bool OnApply() override; + void OnReset() override; + + uint32_t GetColor(); + void SetColor(uint32_t 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(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t 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(MWindow hwndCtrl, uint16_t idCtrl, uint16_t 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; + + int16_t m_wMin, m_wMax, m_wCurr; + + BOOL OnNotify(int, NMHDR*) override; + +public: + CCtrlSpin(CDlgBase *dlg, int ctrlId, int16_t max = 100, int16_t min = 0); + + bool OnApply() override; + void OnReset() override; + + int16_t GetPosition(); + void SetPosition(int16_t 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 OnDblClick; + CCallback OnSelCancel; + CCallback OnSelChange; + +protected: + BOOL OnCommand(MWindow hwndCtrl, uint16_t idCtrl, uint16_t 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(MWindow /*hwndCtrl*/, uint16_t /*idCtrl*/, uint16_t 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 OnCloseup; + CCallback OnDropdown; + CCallback OnKillFocus; + CCallback 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 + uint32_t 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); + MWindow 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(LVBKIMAGE *plvbki) const; + UINT GetCallbackMask() const; + BOOL GetCheckState(UINT iIndex) const; + void GetColumn(int iCol, LVCOLUMN *pcol) const; + void GetColumnOrderArray(int iCount, int *lpiArray) const; + int GetColumnWidth(int iCol) const; + int GetCountPerPage() const; + MWindow GetEditControl() const; + uint32_t GetExtendedListViewStyle() const; + int GetFocusedGroup() const; + int GetGroupCount() const; + void GetGroupInfo(int iGroupId, LVGROUP *pgrp) const; + void GetGroupInfoByIndex(int iIndex, LVGROUP *pgrp) const; + void GetGroupMetrics(LVGROUPMETRICS *pGroupMetrics) const; + UINT GetGroupState(UINT dwGroupId, UINT dwMask) const; + MWindow GetHeader() const; + HCURSOR GetHotCursor() const; + int GetHotItem() const; + uint32_t GetHoverTime() const; + HIMAGELIST GetImageList(int iImageList) const; + BOOL GetInsertMark(LVINSERTMARK *plvim) const; + COLORREF GetInsertMarkColor() const; + int GetInsertMarkRect(RECT *prc) const; + BOOL GetISearchString(LPSTR lpsz) const; + bool GetItem(LVITEM *pitem) const; + int GetItemCount() const; + void GetItemPosition(int i, POINT *ppt) const; + void GetItemRect(int i, RECT *prc, int code) const; + uint32_t 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(LVTILEINFO *plvtinfo) const; + void GetTileViewInfo(LVTILEVIEWINFO *plvtvinfo) const; + MWindow GetToolTips() const; + int GetTopIndex() const; + BOOL GetUnicodeFormat() const; + uint32_t GetView() const; + BOOL GetViewRect(RECT *prc) const; + void GetWorkAreas(int nWorkAreas, RECT *lprc) const; + BOOL HasGroup(int dwGroupId); + int HitTest(LVHITTESTINFO *pinfo) const; + int HitTestEx(LVHITTESTINFO *pinfo); + int InsertColumn(int iCol, const LVCOLUMN *pcol); + int InsertGroup(int index, LVGROUP *pgrp); + void InsertGroupSorted(LVINSERTGROUPSORTED *structInsert); + int InsertItem(const 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(LVBKIMAGE *plvbki); + BOOL SetCallbackMask(UINT mask); + void SetCheckState(UINT iIndex, BOOL fCheck); + BOOL SetColumn(int iCol, LVCOLUMN *pcol); + BOOL SetColumnOrderArray(int iCount, int *lpiArray); + BOOL SetColumnWidth(int iCol, int cx); + void SetExtendedListViewStyle(uint32_t dwExStyle); + void SetExtendedListViewStyleEx(uint32_t dwExMask, uint32_t dwExStyle); + int SetGroupInfo(int iGroupId, LVGROUP *pgrp); + void SetGroupMetrics(LVGROUPMETRICS *pGroupMetrics); + void SetGroupState(UINT dwGroupId, UINT dwMask, UINT dwState); + HCURSOR SetHotCursor(HCURSOR hCursor); + int SetHotItem(int iIndex); + void SetHoverTime(uint32_t dwHoverTime); + uint32_t SetIconSpacing(int cx, int cy); + HIMAGELIST SetImageList(HIMAGELIST himl, int iImageList); + BOOL SetInfoTip(LVSETINFOTIP *plvSetInfoTip); + BOOL SetInsertMark(LVINSERTMARK *plvim); + COLORREF SetInsertMarkColor(COLORREF color); + BOOL SetItem(const LVITEM *pitem); + void SetItemCount(int cItems); + void SetItemCountEx(int cItems, uint32_t 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(LVTILEINFO *plvtinfo); + BOOL SetTileViewInfo(LVTILEVIEWINFO *plvtvinfo); + MWindow SetToolTips(MWindow ToolTip); + BOOL SetUnicodeFormat(BOOL fUnicode); + int SetView(uint32_t iView); + void SetWorkAreas(int nWorkAreas, RECT *lprc); + int SubItemHitTest(LVHITTESTINFO *pInfo) const; + int SubItemHitTestEx(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 { + NMHDR *nmhdr; + NMLISTVIEW *nmlv; + NMLVDISPINFO *nmlvdi; + NMLVSCROLL *nmlvscr; + NMLVGETINFOTIP *nmlvit; + NMLVFINDITEM *nmlvfi; + NMITEMACTIVATE *nmlvia; + NMLVKEYDOWN *nmlvkey; + NMLVCUSTOMDRAW *nmcd; + }; + }; + + CCallback OnBeginDrag; + CCallback OnBeginLabelEdit; + CCallback OnBeginRDrag; + CCallback OnBeginScroll; + CCallback OnColumnClick; + CCallback OnCustomDraw; + CCallback OnDeleteAllItems; + CCallback OnDeleteItem; + CCallback OnClick; + CCallback OnDoubleClick; + CCallback OnEndLabelEdit; + CCallback OnEndScroll; + CCallback OnGetDispInfo; + CCallback OnGetInfoTip; + CCallback OnHotTrack; + CCallback OnIncrementalSearch; + CCallback OnInsertItem; + CCallback OnItemActivate; + CCallback OnItemChanged; + CCallback OnItemChanging; + CCallback OnKeyDown; + CCallback OnMarqueeBegin; + CCallback 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); + MWindow EditLabel(HTREEITEM hItem); + void EndEditLabelNow(BOOL cancel); + void EnsureVisible(HTREEITEM hItem); + void Expand(HTREEITEM hItem, uint32_t flag); + COLORREF GetBkColor() const; + uint32_t GetCheckState(HTREEITEM hItem) const; + HTREEITEM GetChild(HTREEITEM hItem) const; + int GetCount() const; + HTREEITEM GetDropHilight() const; + MWindow 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; + uint32_t GetItemState(HTREEITEM hItem, uint32_t stateMask) const; + HTREEITEM GetLastVisible() const; + COLORREF GetLineColor() const; + HTREEITEM GetNextItem(HTREEITEM hItem, uint32_t 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; + uint32_t GetScrollTime() const; + HTREEITEM GetSelection() const; + COLORREF GetTextColor() const; + MWindow GetToolTips() const; + BOOL GetUnicodeFormat() const; + unsigned GetVisibleCount() const; + HTREEITEM HitTest(TVHITTESTINFO *hti) const; + HTREEITEM InsertItem(TVINSERTSTRUCT *tvis); + void Select(HTREEITEM hItem, uint32_t flag); + void SelectDropTarget(HTREEITEM hItem); + void SelectItem(HTREEITEM hItem); + void SelectSetFirstVisible(HTREEITEM hItem); + COLORREF SetBkColor(COLORREF clBack); + void SetCheckState(HTREEITEM hItem, uint32_t state); + HIMAGELIST 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, uint32_t state, uint32_t stateMask); + COLORREF SetLineColor(COLORREF clLine); + void SetScrollTime(UINT uMaxScrollTime); + COLORREF SetTextColor(COLORREF clText); + MWindow SetToolTips(MWindow 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 OnBeginDrag; + CCallback OnBeginLabelEdit; + CCallback OnBeginRDrag; + CCallback OnCustomDraw; + CCallback OnDeleteItem; + CCallback OnEndLabelEdit; + CCallback OnGetDispInfo; + CCallback OnGetInfoTip; + CCallback OnItemChanged; + CCallback OnItemExpanded; + CCallback OnItemExpanding; + CCallback OnKeyDown; + CCallback OnRightClick; + CCallback OnSelChanged; + CCallback OnSelChanging; + CCallback OnSetDispInfo; + CCallback OnSingleExpand; + +protected: + void OnInit() 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 &option); + void AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, bool &option); + void AddOption(const wchar_t *pwszSection, const wchar_t *pwszName, uint32_t &option, uint32_t mask); + + 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; + + union + { + CMOption *m_option; + bool *m_pBool; + struct + { + uint32_t *m_pDword; + uint32_t m_mask; + }; + }; + + HTREEITEM m_hItem = nullptr; + enum OptionItemType { CMOPTION = 1, BOOL = 2, MASK = 3 }; + OptionItemType m_type; + + COptionsItem(const wchar_t *pwszSection, const wchar_t *pwszName, OptionItemType type) : + m_pwszSection(pwszSection), + m_pwszName(pwszName), + m_type(type) + {} + }; + + OBJLIST m_options; + + void ProcessItemClick(HTREEITEM hti); +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// CCtrlPages + +#define PSN_INFOCHANGED 1 + +// 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 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, uint8_t type, uint32_t iValue); + void CreateLink(CCtrlData &ctrl, const char *szSetting, wchar_t *szValue); + + template + __inline void CreateLink(CCtrlData &ctrl, CMOption &option) + { + ctrl.CreateDbLink(new CMOptionLink(option)); + } + + __inline PROTO_INTERFACE *GetProtoInterface() { return m_proto_interface; } + + void SetStatusText(const wchar_t *statusText); + +protected: + PROTO_INTERFACE *m_proto_interface; + MWindow 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 +class CProtoDlgBase : public CProtoIntDlgBase +{ + typedef CProtoIntDlgBase CSuper; + +public: + __inline CProtoDlgBase(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 -- cgit v1.2.3