From 0a3cc6ed06a3eac9f9c2243c432c6d4443603aae Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Tue, 3 Jul 2012 18:25:01 +0000 Subject: AvatarHistory adopted git-svn-id: http://svn.miranda-ng.org/main/trunk@739 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/ExternalAPI/m_hotkey.h | 67 ++++++++++ plugins/ExternalAPI/m_hotkeysplus.h | 22 ++++ plugins/ExternalAPI/m_hotkeysservice.h | 213 ++++++++++++++++++++++++++++++++ plugins/ExternalAPI/m_mwclc.h | 44 +++++++ plugins/ExternalAPI/m_shutdown.h | 196 +++++++++++++++++++++++++++++ plugins/ExternalAPI/m_snappingwindows.h | 25 ++++ 6 files changed, 567 insertions(+) create mode 100644 plugins/ExternalAPI/m_hotkey.h create mode 100644 plugins/ExternalAPI/m_hotkeysplus.h create mode 100644 plugins/ExternalAPI/m_hotkeysservice.h create mode 100644 plugins/ExternalAPI/m_mwclc.h create mode 100644 plugins/ExternalAPI/m_shutdown.h create mode 100644 plugins/ExternalAPI/m_snappingwindows.h (limited to 'plugins/ExternalAPI') diff --git a/plugins/ExternalAPI/m_hotkey.h b/plugins/ExternalAPI/m_hotkey.h new file mode 100644 index 0000000000..1af34b4342 --- /dev/null +++ b/plugins/ExternalAPI/m_hotkey.h @@ -0,0 +1,67 @@ +#ifndef H_HOTKEY_H +#define H_HOTKEY_H + +//hotkey struct + typedef struct{ + BOOL isShift; //determines if hotkey uses shift + BOOL isCtrl; //determines if hotkey uses control + BOOL isAlt; //determines if hotkey uses alt + UINT vkCode; + + }KEYHASH,*PKEYHASH; + + //struct passed to HKS_GET_NAME_BYHASH the result of calling it will be stored in char* name + typedef struct{ + char* name; //pointer to buffer where the result will be stored + size_t bufferlen; //size of the buffer + }GETNAMEWPARAM; + + /*this below are registred miranda services and should be called by CallService */ + + /* this funtion registers new hot key function, function must be registred as miranda service + lParam = (KEYHASH*) hotKeyDefinition + wParam = (const char*)ServiceName + returns true on success and false if fails */ + #define HKS_REGISTERFUNCTION "mhotkeyregister" + /* unregisters function as hot key function + lParam = (KEYHASH*) hotKeyDefinition /search function by it's hotkey combination + wParam = NULL + and if + lParam = NULL + wParam = (const char*) functionName //search function by it's name + returns if function was propertly deleted returns true else returns false */ + #define HKS_UNREGISTERFUNCTION "mhotkeyunregister" + + /* + Updates hotkey to the specific function (if another function use this hot key it'll be assigned to this + and that function will be unregistred as hotkey function) + wParam = (const char*) FunctoinName // name of the function you want to update + lParam = (KEYHASH*)newHotKey + + returns: true on success and false on failure + */ + #define HKS_UPDATEHOTKEY "mhotkeyupdate" + + /* gets function hash by function name, the result is stored in lParam(KEYHASH*) + wParam = (const char*)functionName + lParam = (KEYHASH*) - here the result is stored + */ + #define HKS_GET_HASH_BYNAME "mhgethashbyname" + /* gets functoin name by it's hash the GETNAMEPARAM struct must be filled before calling this + it has to be passed as wParam, and there will be result stored. + wParam=(GETNAMEPARAM*)Result + lParam=(KEYHASH*)keyHash + */ + #define HKS_GET_NAME_BYHASH "mhgetnamebyhash" + /* converts keyHash to windows hotkey + wParam=(DWORD*)result + lParam=(KEYHASH*)hotKey + */ + #define HKS_HASH_TO_HOTKEY "mhhashtohotkey" + /*converts windows hotkey to keyHash + wParam=(DWORD*)hotkey + lParam=(KEYHASH*)result + */ + #define MKS_HOTKEY_TO_HASH "mhhotkeytohash" + +#endif \ No newline at end of file diff --git a/plugins/ExternalAPI/m_hotkeysplus.h b/plugins/ExternalAPI/m_hotkeysplus.h new file mode 100644 index 0000000000..3da357f109 --- /dev/null +++ b/plugins/ExternalAPI/m_hotkeysplus.h @@ -0,0 +1,22 @@ +#define MS_HOTKEYSPLUS_ADDKEY "HotkeysPlus/Add" + +/* +This service registers hotkey for +WPARAM - service to perform +LPARAM - decription of the service +Returned values: + 0 - success, + 1 - hotkey for this function is already existing, + 2 - the service, that you try to register the hotkey for, not exists +*/ + +#define MS_HOTKEYSPLUS_EXISTKEY "HotkeysPlus/Exist" +/* +This service checks whether hotkey for service (WPARAM) exists +LPARAM - not used +Returned values: + 0 - failed, + 1 - the hotkey for this function exists, + 2 - the service not exists +*/ + diff --git a/plugins/ExternalAPI/m_hotkeysservice.h b/plugins/ExternalAPI/m_hotkeysservice.h new file mode 100644 index 0000000000..6e777b1876 --- /dev/null +++ b/plugins/ExternalAPI/m_hotkeysservice.h @@ -0,0 +1,213 @@ +#ifndef __M_HOTKEYSSERVICE__ +# define __M_HOTKEYSSERVICE__ + + +#define HKS_SERVICE_NAME "HotkeysService" + +// Modifiers for hotkeys +//#define MOD_ALT 0x0001 +//#define MOD_CONTROL 0x0002 +//#define MOD_SHIFT 0x0004 +//#define MOD_WIN 0x0008 +#define MOD_GLOBAL 0x0010 + +// FLAGS +// inherit modifiers from group (specified modifiers ignored) +#define HKS_ACTION_SHAREMODIFIERS 1 +// register item, but disable +#define HKS_INITIALLY_DISABLED 2 + +#if defined(_MSC_VER) +#pragma warning(push) /* save warning settings */ +#pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union */ +#endif + +// Structure of hotkey +typedef union +{ + struct + { + WORD key; + WORD modifiers; + }; + DWORD hotkey; + +} THKSHotkey, *PHKSHotkey; + +#if defined(_MSC_VER) +#pragma warning(pop) /* restore warning settings */ +#endif + +// ITEM TYPES +#define HKS_ITEM_MODULE 1 +#define HKS_ITEM_GROUP 2 +#define HKS_ITEM_ACTION 3 +#define HKS_ITEM_MACRO 4 + + +// Structure passed to RegisterItem service. +// Used only for registration pursposes, so free it after call. +// name, owner and itemType field is mandatory. +// owner is item ID or must be 0 for 1st level items (module, single action or macro) +// itemType can be one of ITEM TYPES constants. +// flags can be combined from FLAGS constants. +// Group can contain other groups and items and optionally +// set group modifiers. Only item can be tree leaf. +// If creating group, hotkey.modifiers will be used +// as group modifiers (if nonzero) +// If creating action, hotkey is optional. If hotkey.key is filled, then +// hotkey will be assigned to item (if unused). +// If creating macro, hotkey is mandatory. + +typedef struct +{ + int owner; + char *name; + int itemType; + THKSHotkey hotkey; + int flags; + +} THKSItem, *PHKSItem; + + +// Register item +// wParam: item data in PKHSItem format +// lParam: 0 +// Returns HANDLE called "ID" in loWord. +// For actions and macros, hiWord returns state: 0 if ok, other if passed hotkey +// can't be registered (for example already used) +// In other cases hiWord is useless +#define MS_HKS_REGISTER_ITEM HKS_SERVICE_NAME "/RegisterItem" + +// Unregister item +// If item is Group, then all subItems will be unregistered. +// wParam: item ID +// lParam: 0 +// Returns: 0 on success, other on fail +#define MS_HKS_UNREGISTER_ITEM HKS_SERVICE_NAME "/UnregisterItem" + +// Assign hotkey to item. If item is group, then only +// modifiers are taken as group modifiers. Do not call on modules. +// Hotkey consists of modifiers in hiWord and key in loWord. +// wParam: item ID +// lParam: hotkey as PHKS_Hotkey to register +// Returns: +// on success: hotkey +// on error: 0 +#define MS_HKS_ASSIGN_HOTKEY HKS_SERVICE_NAME "/AssignHotkey" + +// Get hotkey assigned to item. Don't apply to modules. +// wParam: item ID +// lParam: 0 +// Returns: hotkey assigned, 0 otherwise. +#define MS_HKS_GET_HOTKEY HKS_SERVICE_NAME "/GetAssignedHotkey" + +// Unassign hotkey from item. Only valid on action and macro items. +// wParam: item ID +// lParam: 0 +// Returns: 0 on success, other on fail +#define MS_HKS_UNASSIGN_HOTKEY HKS_SERVICE_NAME "/UnassignHotkey" + +// Enable/Disable item. +// If item is group or module, then all subItems will be affected. +// wParam: item ID +// lParam: 1 to enable, anything else to disable +// Returns: 0 on success, other on fail +#define MS_HKS_ENABLE_ITEM HKS_SERVICE_NAME "/EnableItem" + +// Hotkey to text +// wParam: hotkey to textify +// lParam: address to place string, space must be allocated +// Returns: 0 +#define MS_HKS_TO_TEXT HKS_SERVICE_NAME "/HotkeyToText" + +// Get hotkey from text +// wParam: text to convert to hotkey +// lParam: 0 +// Returns: hotkey +#define MS_HKS_FROM_TEXT HKS_SERVICE_NAME "/HotkeyFromText" + + +typedef struct +{ + int itemId; + int moduleId; + char *name; + int itemType; + THKSHotkey hotkey; + +} THKSEvent, *PHKSEvent; + +// Event when hotkey is pressed +// wParam: PHKSEvent +// lParam: 0 +#define ME_HKS_KEY_PRESSED HKS_SERVICE_NAME "/HotkeyPressed" + + + + +// Util functions //////////////////////////////////////////////////////////////////////// + + +__inline static int HKS_RegisterModule(char *name) +{ + THKSItem item = {0}; + + if (!ServiceExists(MS_HKS_REGISTER_ITEM)) + return -1; + + item.name = name; + item.itemType = HKS_ITEM_MODULE; + + return LOWORD(CallService(MS_HKS_REGISTER_ITEM, (WPARAM) &item, 0)); +} + + +__inline static int HKS_RegisterAction(int owner, char *name, int modifiers, char key, int flags) +{ + THKSItem item = {0}; + + if (!ServiceExists(MS_HKS_REGISTER_ITEM)) + return -1; + + item.owner = owner; + item.name = name; + item.itemType = HKS_ITEM_ACTION; + item.flags = flags; + + if(key != 0) + { + item.hotkey.key = (WORD) key; + item.hotkey.modifiers = (WORD)modifiers; + } + + return LOWORD(CallService(MS_HKS_REGISTER_ITEM, (WPARAM) &item, 0)); +} + + +__inline static int HKS_RegisterGroup(int owner, char *name, int modifiers, int flags) +{ + THKSItem item = {0}; + + if (!ServiceExists(MS_HKS_REGISTER_ITEM)) + return -1; + + item.owner = owner; + item.name = name; + item.itemType = HKS_ITEM_GROUP; + item.flags = flags; + item.hotkey.modifiers = (WORD)modifiers; + + return LOWORD(CallService(MS_HKS_REGISTER_ITEM, (WPARAM) &item, 0)); +} + +__inline static int HKS_Unregister(int id) +{ + if (!ServiceExists(MS_HKS_UNREGISTER_ITEM)) + return -1; + + return CallService(MS_HKS_UNREGISTER_ITEM, (WPARAM) id, 0); +} + + +#endif diff --git a/plugins/ExternalAPI/m_mwclc.h b/plugins/ExternalAPI/m_mwclc.h new file mode 100644 index 0000000000..e72ce29904 --- /dev/null +++ b/plugins/ExternalAPI/m_mwclc.h @@ -0,0 +1,44 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _M_MWCLC_ +#define _M_MWCLC_ + +//add a new hotkey so it has a default and can be changed in the options dialog +//wParam=0 +//lParam=(LPARAM)(SKINHOTKEYDESC*)ssd; +//returns 0 on success, nonzero otherwise +typedef struct { + int cbSize; + const char *pszName; //name to refer to sound when playing and in db + const char *pszDescription; //description for options dialog +// const char *pszDefaultFile; //default sound file to use + const char *pszSection; //section name used to group sounds (NULL is acceptable) + const char *pszService; //Service to call when HotKey Pressed + + int DefHotKey; //default hot key for action +} SKINHOTKEYDESCEX; + +#define MS_SKIN_ADDHOTKEY "Skin/HotKeys/AddNew" +#define MS_SKIN_PLAYHOTKEY "Skin/HotKeys/Run" + +#endif \ No newline at end of file diff --git a/plugins/ExternalAPI/m_shutdown.h b/plugins/ExternalAPI/m_shutdown.h new file mode 100644 index 0000000000..87e25e8851 --- /dev/null +++ b/plugins/ExternalAPI/m_shutdown.h @@ -0,0 +1,196 @@ +/* + +'AutoShutdown'-Plugin for +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright (C) 2004-2007 H. Herkenrath + +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 (Shutdown-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_SHUTDOWN_H__ +#define M_SHUTDOWN_H__ + +#if defined (_MSC_VER) && (_MSC_VER >= 1020) + #pragma once +#endif + +/* + AutoShutdown v1.4.0.2 +*/ + +/* interface id */ +#if !defined(MIID_SHUTDOWN) + #define MIID_SHUTDOWN {0x142982a8,0x88cf,0x4c65,{0x87,0x21,0x6d,0xe2,0x7d,0x5c,0xe7,0xb5}} +#endif + +/******************************************************************/ +/************************* SERVICES *******************************/ +/******************************************************************/ + +/* Show settings dialog v1.3.0.0+ +Shows the dialog by which the shutdown watcher can be started. +If the dialog is already opened this brings it to foreground. + wParam=lParam=0 +Returns 0 on success, nonzero otherwise. +*/ +#define MS_AUTOSHUTDOWN_SHOWSETTINGSDIALOG "AutoShutdown/ShowSettingsDialog" + +/* Initiate shutdown process v1.3.0.0+ +Initiates the shutdown process for a given shutdown type. +If another shutdown process is already pending it will return error. +Associated events: ME_AUTOSHUTDOWN_OKTOSHUTDOWN, ME_AUTOSHUTDOWN_SHUTDOWN + wParam=shutdownType + lParam=(LPARAM)(BOOL)fShowConfirmDlg (whether to show the warning dialog or not) +Returns 0 on success, nonzero otherwise. +*/ +#define MS_AUTOSHUTDOWN_SHUTDOWN "AutoShutdown/Shutdown" + +/* shutdown types */ +#define SDSDT_CLOSEMIRANDA 1 // close miranda process +#define SDSDT_SETMIRANDAOFFLINE 2 // set all protocols to offline +#define SDSDT_LOGOFF 3 // logoff from Windows +#define SDSDT_REBOOT 4 // reboot computer +#define SDSDT_SHUTDOWN 5 // shutdown Windows and power off +#define SDSDT_STANDBY 6 // standby mode +#define SDSDT_HIBERNATE 7 // hibernate mode +#define SDSDT_LOCKWORKSTATION 8 // lock the workstation +#define SDSDT_CLOSERASCONNECTIONS 9 // close all dialup connections +#define SDSDT_MAX 9 + +/* Get shutdown type description v1.4.0.0+ +Gets a textual description of the given shutdown type. + wParam=shutdownType + lParam=flags (see GSTDF_* below) +Returns a static buffer of the description of the given shutdown type. +It does not need to be freed in any way. +The returned text is already translated. +Returns a pointer to a string on success, NULL on error. +*/ +#define MS_AUTOSHUTDOWN_GETTYPEDESCRIPTION "AutoShutdown/GetTypeDescription" + +#define GSTDF_LONGDESC 0x0001 // returns a long description +#define GSTDF_UNICODE 0x0002 // returns a Unicode string +#define GSTDF_UNTRANSLATED 0x0004 // returns an untranslated string +#if defined(_UNICODE) + #define GSTDF_TCHAR GSTDF_UNICODE // will return WCHAR* +#else + #define GSTDF_TCHAR 0 // will return char*, as usual +#endif + +/* Check if shutdown type is enabled v1.4.0.0+ +Tests if a specific shutdown type is activated and its use is possible +on the system. For example hibernate and stand-by modes are not available on +older versions of Windows (needs Windows ME/2000+). +Shutdown might also be prohibited by security restrictions. +This services checks it all. +However, there is no need to call this before calling MS_AUTOSHUTDOWN_SHUTDOWN. +MS_AUTOSHUTDOWN_SHUTDOWN will fail if the given shutdown type is not enabled. + wParam=shutdownType + lParam=0 +Returns TRUE if the given shutdown type is enabled, FALSE otherwise. +*/ +#define MS_AUTOSHUTDOWN_ISTYPEENABLED "AutoShutdown/IsTypeEnabled" + +/* Start shutdown watcher v1.4.0.0+ +Starts the watcher using the last settings specified on the dialog +shown by MS_AUTOSHUTDOWN_SHOWSETTINGSDIALOG. +Call MS_AUTOSHUTDOWN_SHOWSETTINGSDIALOG instead to offer +options about what watcher to use. +Associated event: ME_AUTOSHUTDOWN_WATCHERCHANGED + wParam=lParam=0 +Returns 0 on success, nonzero otherwise. +*/ +#define MS_AUTOSHUTDOWN_STARTWATCHER "AutoShutdown/StartWatcher" + +/* Stop shutdown watcher v1.4.0.0+ +Stops the currently running watcher. +If the watcher is not running, it returns error. +Associated event: ME_AUTOSHUTDOWN_WATCHERCHANGED + wParam=lParam=0 +Returns 0 on success, nonzero otherwise. +*/ +#define MS_AUTOSHUTDOWN_STOPWATCHER "AutoShutdown/StopWatcher" + +/* Check if watcher is running v1.4.0.0+ +Checks if the watcher is currently active or not. + wParam=lParam=0 +Returns TRUE if the watcher is enabled, FALSE otherwise. +*/ +#define MS_AUTOSHUTDOWN_ISWATCHERENABLED "AutoShutdown/IsWatcherEnabled" + +/******************************************************************/ +/************************** EVENTS ********************************/ +/******************************************************************/ + +/* Disallow shutdown process (event) v1.3.0.0+ +Gets fired when MS_AUTOSHUTDOWN_SHUTDOWN is called. +Parmeters are the same as specified at the call to MS_AUTOSHUTDOWN_SHUTDOWN. + wParam=shutdownType + lParam=(LPARAM)(BOOL)fShowConfirmDlg +Return 0 to allow shutdown, 1 to disallow. +*/ +#define ME_AUTOSHUTDOWN_OKTOSHUTDOWN "AutoShutdown/OkToShutdown" + +/* Shutdown process started (event) v1.3.0.1+ +Gets fired when ME_AUTOSHUTDOWN_OKTOSHUTDOWN was confirmed. +Parmeters are the same as specified at the call +to MS_AUTOSHUTDOWN_SHUTDOWN. + wParam=shutdownType + lParam=(LPARAM)(BOOL)fShowConfirmDlg +Unused, return always 0 here. +*/ +#define ME_AUTOSHUTDOWN_SHUTDOWN "AutoShutdown/ShutdownEvent" + +/* Watcher changed (event) v1.3.0.0+ +Fired when MS_AUTOSHUTDOWN_STARTWATCHER or MS_AUTOSHUTDOWN_STOPWATCHER +is called. + wParam=(WPARAM)(BOOL)fIsStarted (whether whe watcher is running now) + lParam=0 +Unused, return always 0 here. +*/ +#define ME_AUTOSHUTDOWN_WATCHERCHANGED "AutoShutdown/Watcher/Changed" + + +#ifndef SHUTDOWN_NOSETTINGS +#define SETTING_REMEMBERONRESTART_DEFAULT 0 // SDROR_RUNNING +#define SETTING_SHOWCONFIRMDLG_DEFAULT 1 +#define SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT 30 // seconds +#define SETTING_WEATHERSHUTDOWN_DEFAULT 0 +#define SETTING_HDDOVERHEATSHUTDOWN_DEFAULT 1 +#define SETTING_SMARTOFFLINECHECK_DEFAULT 1 + +#define SETTING_SHUTDOWNTYPE_DEFAULT SDSDT_SHUTDOWN +#define SETTING_WATCHERFLAGS_DEFAULT (SDWTF_SPECIFICTIME|SDWTF_ST_COUNTDOWN) +#define SETTING_COUNTDOWN_DEFAULT 30 +#define SETTING_COUNTDOWNUNIT_DEFAULT 60 // x times countdown seconds +#define SETTING_TIMESTAMP_DEFAULT (DWORD)(time(NULL)+(SETTING_COUNTDOWN_DEFAULT*SETTING_COUNTDOWNUNIT_DEFAULT)) +#define SETTING_CPUUSAGETHRESHOLD_DEFAULT 90 // percent + +#define SDWTF_SPECIFICTIME 0x0001 +#define SDWTF_ST_TIME 0x0002 +#define SDWTF_ST_COUNTDOWN 0x0004 +#define SDWTF_ST_MASK 0x0006 /* bitmask for SDWTF_ST_* bits */ +#define SDWTF_MESSAGE 0x0008 +#define SDWTF_FILETRANSFER 0x0010 +#define SDWTF_IDLE 0x0020 +#define SDWTF_STATUS 0x0040 +#define SDWTF_CPUUSAGE 0x0080 +#define SDWTF_MASK 0x00FF /* bitmask for all SDWTF_* bits */ + +#define SDROR_RUNNING 3 +#endif + +#endif // M_SHUTDOWN_H diff --git a/plugins/ExternalAPI/m_snappingwindows.h b/plugins/ExternalAPI/m_snappingwindows.h new file mode 100644 index 0000000000..fcfd679913 --- /dev/null +++ b/plugins/ExternalAPI/m_snappingwindows.h @@ -0,0 +1,25 @@ +#ifndef SNAPPING_WINDOWS_H +#define SNAPPING_WINDOWS_H + +struct SnapWindowProc_t +{ + HWND hWnd; + // + SIZE m_szMoveOffset; + WPARAM wParam; + LPARAM lParam; + // + int Reserved1; + int Reserved2; + int Reserved3; +}; + +#define CallSnappingWindowProc(hwnd,nMessage,wParam,lParam) {static struct SnapWindowProc_t SnapInfo; \ + if ((nMessage == WM_MOVING) || (nMessage == WM_NCLBUTTONDOWN) || (nMessage == WM_SYSCOMMAND) || (nMessage == WM_SIZING)){ \ + SnapInfo.hWnd = hwnd; \ + SnapInfo.wParam = wParam; \ + SnapInfo.lParam = lParam; \ + CallService("Utils/SnapWindowProc",(WPARAM)&SnapInfo,nMessage); \ + if (nMessage == WM_SIZING) return 1;}} + +#endif //SNAPPING_WINDOWS_H \ No newline at end of file -- cgit v1.2.3