From 59e53cb6cad99051eb3e46b919fd78ab7493061d Mon Sep 17 00:00:00 2001 From: mataes2007 Date: Wed, 23 Nov 2011 18:16:39 +0000 Subject: added Help plugin git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@201 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- Help/utils.c | 399 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 Help/utils.c (limited to 'Help/utils.c') diff --git a/Help/utils.c b/Help/utils.c new file mode 100644 index 0000000..a6fb7a0 --- /dev/null +++ b/Help/utils.c @@ -0,0 +1,399 @@ +/* +Miranda IM Help Plugin +Copyright (C) 2002 Richard Hughes, 2005-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 (Help-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#define _WIN32_WINNT 0x0500 +#define __RPCASYNC_H__ /* header shows warnings in VS6 */ +#include +#include +#define MIRANDA_VER 0x0600 +#include +#include +#include +#include +#include "help.h" + +#pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union */ +#include +#pragma warning(default:4201) /* nonstandard extension used : nameless struct/union */ +#include +#include +#include + +#define CHARBUFFER_ALLOCSTEP 512 // allocated buffer increase in bytes + +#ifdef EDITOR +extern const TCHAR *szControlTypeNames[]={ + _T("Unknown"),_T("Dialog Box"),_T("Button"),_T("Check Box"),_T("Radio Button"), + _T("Text"),_T("Image"),_T("Edit Box"),_T("Group Box"),_T("Combo Box"), + _T("List Box"),_T("Spin Edit Box"),_T("Progress Bar"),_T("Slider"),_T("List View"), + _T("Tree View"),_T("Date/Time Picker"),_T("IP Address"),_T("Status Bar"),_T("Hyperlink"), + _T("Contact List"),_T("Scroll Bar"),_T("Animation"),_T("Hotkey"),_T("Tabs"), + _T("Colour Picker"),_T("Tool Bar"),_T("Combo Edit Box"),_T("Size Grip")}; +#endif + +int GetControlType(HWND hwndCtl) +{ + TCHAR szClassName[32]; + DWORD style; + + if(GetClassLong(hwndCtl,GCW_ATOM)==32770) + return CTLTYPE_DIALOG; + if(!GetClassName(hwndCtl,szClassName,SIZEOF(szClassName))) return CTLTYPE_UNKNOWN; + if(!lstrcmpi(szClassName,_T("MDIClient"))) + return CTLTYPE_DIALOG; + else if(!lstrcmpi(szClassName,_T("Static"))) { + if(GetClassName(GetParent(hwndCtl),szClassName,SIZEOF(szClassName)) && !lstrcmpi(szClassName,_T("ComboBox")) || !lstrcmpi(szClassName,WC_COMBOBOXEX)) + return CTLTYPE_COMBO; + style=GetWindowLong(hwndCtl,GWL_STYLE); + switch(style&SS_TYPEMASK) { + case SS_BITMAP: + case SS_BLACKFRAME: + case SS_BLACKRECT: + case SS_ENHMETAFILE: + case SS_ETCHEDFRAME: + case SS_ETCHEDHORZ: + case SS_ETCHEDVERT: + case SS_WHITEFRAME: + case SS_WHITERECT: + case SS_GRAYFRAME: + case SS_GRAYRECT: + case SS_ICON: + case SS_OWNERDRAW: + return CTLTYPE_IMAGE; + } + return CTLTYPE_TEXT; + } + else if(GetClassLong(hwndCtl,GCW_ATOM)==32772) // WinNT/2000/XP: icon titles + return CTLTYPE_IMAGE; // class="#32772" + else if(!lstrcmpi(szClassName,_T("Button"))) { + style=GetWindowLong(hwndCtl,GWL_STYLE); + switch(style&0x24) { + case BS_CHECKBOX: + case BS_AUTOCHECKBOX: + case BS_3STATE: + case BS_AUTO3STATE: + if(style&BS_PUSHLIKE) break; + return CTLTYPE_CHECKBOX; + case BS_RADIOBUTTON: + case BS_AUTORADIOBUTTON: + if(style&BS_PUSHLIKE) break; + return CTLTYPE_RADIO; + case BS_GROUPBOX: + return CTLTYPE_GROUP; + } + return CTLTYPE_BUTTON; + } + else if(!lstrcmpi(szClassName,MIRANDABUTTONCLASS)) return CTLTYPE_BUTTON; + else if(!lstrcmpi(szClassName,_T("Edit"))) { + if(GetClassName(GetParent(hwndCtl),szClassName,SIZEOF(szClassName)) && !lstrcmpi(szClassName,_T("ComboBox"))) + return CTLTYPE_COMBO; + if(GetClassName(GetWindow(hwndCtl,GW_HWNDNEXT),szClassName,SIZEOF(szClassName)) && !lstrcmpi(szClassName,UPDOWN_CLASS)) + if((HWND)SendMessage(GetWindow(hwndCtl,GW_HWNDNEXT),UDM_GETBUDDY,0,0)==hwndCtl) + return CTLTYPE_SPINEDIT; + return CTLTYPE_EDIT; + } + else if(!_tcsnicmp(szClassName,_T("RichEdit"),8)) return CTLTYPE_EDIT; // RICHEDIT,RichEdit20A,RichEdit20W,RichEdit50W and future versions + else if(!lstrcmpi(szClassName,_T("ListBox"))) { + style=GetWindowLong(hwndCtl,GWL_STYLE); + if(style&LBS_COMBOBOX) return CTLTYPE_COMBO; + return CTLTYPE_LIST; + } else if(!lstrcmpi(szClassName,_T("ComboLBox")) || !lstrcmpi(szClassName,_T("ComboBox")) || !lstrcmpi(szClassName,WC_COMBOBOXEX)) + return CTLTYPE_COMBO; + else if(!lstrcmpi(szClassName,_T("ScrollBar"))) { + style=GetWindowLong(hwndCtl,GWL_STYLE); + if(style&SBS_SIZEBOX) return CTLTYPE_SIZEGRIP; + return CTLTYPE_SCROLL; + } + else if(!lstrcmpi(szClassName,WC_PAGESCROLLER)) return CTLTYPE_SCROLL; + else if(!lstrcmpi(szClassName,UPDOWN_CLASS)) { + if(GetClassName((HWND)SendMessage(hwndCtl,UDM_GETBUDDY,0,0),szClassName,SIZEOF(szClassName)) && !lstrcmpi(szClassName,_T("Edit"))) + return CTLTYPE_SPINEDIT; + return CTLTYPE_SCROLL; + } + else if(!lstrcmpi(szClassName,PROGRESS_CLASS)) return CTLTYPE_PROGRESS; + else if(!lstrcmpi(szClassName,TRACKBAR_CLASS)) return CTLTYPE_SLIDER; + else if(!lstrcmpi(szClassName,WC_LISTVIEW) || !lstrcmpi(szClassName,WC_HEADER)) + return CTLTYPE_LISTVIEW; + else if(!lstrcmpi(szClassName,WC_TREEVIEW)) return CTLTYPE_TREEVIEW; + else if(!lstrcmpi(szClassName,DATETIMEPICK_CLASS) || !lstrcmpi(szClassName,MONTHCAL_CLASS)) + return CTLTYPE_DATETIME; + else if(!lstrcmpi(szClassName,WC_IPADDRESS)) return CTLTYPE_IP; + else if(!lstrcmpi(szClassName,STATUSCLASSNAME)) return CTLTYPE_STATUSBAR; + else if(!lstrcmpi(szClassName,CLISTCONTROL_CLASS)) return CTLTYPE_CLC; + else if(!lstrcmpi(szClassName,WNDCLASS_HYPERLINK) || !lstrcmpi(szClassName,_T("SysLink"))) + return CTLTYPE_HYPERLINK; + else if(!lstrcmpi(szClassName,ANIMATE_CLASS)) return CTLTYPE_ANIMATION; + else if(!lstrcmpi(szClassName,HOTKEY_CLASS)) return CTLTYPE_HOTKEY; + else if(!lstrcmpi(szClassName,WC_TABCONTROL)) return CTLTYPE_TABS; + else if(!lstrcmpi(szClassName,WNDCLASS_COLOURPICKER)) return CTLTYPE_COLOUR; + else if(!lstrcmpi(szClassName,TOOLBARCLASSNAME) || !lstrcmpi(szClassName,REBARCLASSNAME)) + return CTLTYPE_TOOLBAR; + switch(SendMessage(hwndCtl,WM_GETDLGCODE,0,(LPARAM)NULL)&0x2070) { + case DLGC_RADIOBUTTON: + return CTLTYPE_RADIO; + case DLGC_DEFPUSHBUTTON: + case DLGC_UNDEFPUSHBUTTON: + case DLGC_BUTTON: + return CTLTYPE_BUTTON; + } + hwndCtl=GetWindow(hwndCtl,GW_CHILD); // check for owner-extended control + if(hwndCtl!=NULL) return GetControlType(hwndCtl); + return CTLTYPE_UNKNOWN; +} + +HWND GetControlDialog(HWND hwndCtl) +{ + TCHAR szClassName[32]; + while(hwndCtl!=NULL) { + if(GetClassLong(hwndCtl,GCW_ATOM)==32770) + return hwndCtl; + if(GetClassName(hwndCtl,szClassName,SIZEOF(szClassName))) + if(!lstrcmpi(szClassName,_T("MDIClient"))) + return hwndCtl; + hwndCtl=GetParent(hwndCtl); + } + return hwndCtl; +} + +// never fails +int GetControlTitle(HWND hwndCtl,TCHAR *pszTitle,int cchTitle) +{ + TCHAR *p; + int res=0; + if(cchTitle) pszTitle[0]=_T('\0'); + switch(GetControlType(hwndCtl)) { + case CTLTYPE_DIALOG: + case CTLTYPE_BUTTON: + case CTLTYPE_CHECKBOX: + case CTLTYPE_RADIO: + case CTLTYPE_GROUP: + case CTLTYPE_TEXT: + case CTLTYPE_HYPERLINK: + res=GetWindowText(hwndCtl,pszTitle,cchTitle); + } + hwndCtl=GetWindow(hwndCtl,GW_HWNDPREV); + if(hwndCtl) + switch(GetControlType(hwndCtl)) { + case CTLTYPE_TEXT: + case CTLTYPE_GROUP: + res=GetWindowText(hwndCtl,pszTitle,cchTitle); + } + if(res) + for(p=pszTitle;*p!=0;p++) { + // strip-off ampersand (&) prefix character + if(*p==_T('&') && *(p+1)!=_T('&')) { + MoveMemory(p,p+1,(lstrlen(p+1)+1)*sizeof(TCHAR)); + res--; + if(*(p+1)==0) break; + } + // strip-off last ':' + if(*p==_T(':') && *(p+1)==0) { + *p=0; + res--; + break; + } + } + return res; +} + +// mir_free() the return value +char *GetControlModuleName(HWND hwndCtl) +{ + char szModule[512],szMainModule[512]; + char *pszFile,*buf; + + if(!GetModuleFileNameA(NULL,szMainModule,sizeof(szMainModule))) + return NULL; + buf=strrchr(szMainModule,'\\'); + if(buf!=NULL) + *buf='\0'; + else buf=szMainModule; + + do { + if(!GetModuleFileNameA((HINSTANCE)GetWindowLong(hwndCtl,GWL_HINSTANCE),szModule,sizeof(szModule))) + return NULL; + pszFile=strrchr(szModule,'\\'); + if(pszFile!=NULL) { + *pszFile='\0'; + pszFile++; + } else pszFile=szModule; + if(lstrlenA(szModule)>lstrlenA(szMainModule)) + szModule[lstrlenA(szMainModule)]='\0'; + if(!lstrcmpiA(szModule,szMainModule)) break; // found miranda module + hwndCtl=GetParent(hwndCtl); + } while(hwndCtl!=NULL); + + buf=strrchr(pszFile,'.'); + if(buf!=NULL) *buf++='\0'; + return mir_strdup(pszFile); +} + + +struct CreateControlIdData { + int id; + HWND hwndCtl; +}; + +static BOOL CALLBACK CreateCtlIdEnumProc(HWND hwnd,LPARAM lParam) +{ + struct CreateControlIdData* ccid=(struct CreateControlIdData*)lParam; + TCHAR szClassName[32]; + if(GetClassLong(hwnd,GCW_ATOM)==32770) // class="#32770" + return TRUE; + if(GetClassName(hwnd,szClassName,SIZEOF(szClassName))) + if(!lstrcmpi(szClassName,_T("MDIClient"))) + return TRUE; + if(GetWindowLong(hwnd,GWL_ID)<=0 || GetWindowLong(hwnd,GWL_ID)==0xFFFF) + ccid->id--; + if(hwnd==ccid->hwndCtl) ccid->hwndCtl=NULL; + return ccid->hwndCtl!=NULL; +} + +int GetControlID(HWND hwndCtl) +{ + struct CreateControlIdData ccid; + TCHAR szClassName[32]; + + // obey context ID when set (rarely) + ccid.id=GetWindowContextHelpId(hwndCtl); + if(ccid.id!=0) return ccid.id; + + if(GetClassName(hwndCtl,szClassName,SIZEOF(szClassName))) { + if(!lstrcmpi(szClassName,UPDOWN_CLASS)) { // handle spinner controls as a whole + DWORD style; + HWND hwndBuddy; + style=GetWindowLong(hwndCtl,GWL_STYLE); + if(style&UDS_ALIGNRIGHT || style&UDS_ALIGNLEFT) { + hwndBuddy=(HWND)SendMessage(hwndCtl,UDM_GETBUDDY,0,0); + if(hwndBuddy!=NULL) hwndCtl=hwndBuddy; + } + } else if(GetClassLong(hwndCtl,GCW_ATOM)==32770 || !lstrcmpi(szClassName,_T("MDIClient"))) + return 0; // ensure this is always unset + } + ccid.id=GetWindowLong(hwndCtl,GWL_ID); + if(ccid.id<=0 || ccid.id==0xFFFF) { + ccid.id=-1; + ccid.hwndCtl=hwndCtl; + EnumChildWindows(GetParent(hwndCtl),CreateCtlIdEnumProc,(LPARAM)&ccid); + if(ccid.hwndCtl!=NULL) return -1; + } + return ccid.id; +} + +// mir_free() the return value +static char *Base64Encode(PBYTE pBuf,int cbBuf) +{ + NETLIBBASE64 nlb64; + nlb64.pbDecoded=pBuf; + nlb64.cbDecoded=cbBuf; + nlb64.cchEncoded=Netlib_GetBase64EncodedBufferSize(nlb64.cbDecoded); + nlb64.pszEncoded=(char*)mir_alloc(nlb64.cchEncoded); + if(nlb64.pszEncoded==NULL || !CallService(MS_NETLIB_BASE64ENCODE,0,(LPARAM)&nlb64)) { + mir_free(nlb64.pszEncoded); /* does NULL check */ + return NULL; + } + return nlb64.pszEncoded; +} + +struct CreateDialogIdBinaryData { + int alloced,count; + PBYTE buf; + HWND hwndParent; +}; + +static BOOL CALLBACK CreateDlgIdBinEnumProc(HWND hwnd,LPARAM lParam) +{ + struct CreateDialogIdBinaryData *cdib=(struct CreateDialogIdBinaryData*)lParam; + int type; + + if(GetParent(hwnd)!=cdib->hwndParent) return TRUE; + type=GetControlType(hwnd); + if(type==CTLTYPE_DIALOG || type==CTLTYPE_TEXT || type==CTLTYPE_GROUP) return TRUE; + if(cdib->count+3>cdib->alloced) { + PBYTE buf2; + buf2=(PBYTE)mir_realloc(cdib->buf,cdib->alloced+32); + if(buf2==NULL) return FALSE; + cdib->alloced+=32; + cdib->buf=buf2; + } + cdib->buf[cdib->count]=(BYTE)type; + *(PWORD)(cdib->buf+cdib->count+1)=(WORD)GetWindowLong(hwnd,GWL_ID); + cdib->count+=3; + return TRUE; +} + +// mir_free() the return value +char *CreateDialogIdString(HWND hwndDlg) +{ + struct CreateDialogIdBinaryData cdib; + char *szRet; + + ZeroMemory(&cdib, sizeof(cdib)); + if(hwndDlg==NULL) return NULL; + cdib.hwndParent=hwndDlg; + EnumChildWindows(hwndDlg,CreateDlgIdBinEnumProc,(LPARAM)&cdib); + if(cdib.buf==NULL) return NULL; + szRet=Base64Encode(cdib.buf,cdib.count); + mir_free(cdib.buf); + return szRet; +} + + +void AppendCharToCharBuffer(struct ResizableCharBuffer *rcb,char c) +{ + if(rcb->cbAlloced<=rcb->iEnd+1) { + char* buf=(char*)mir_realloc(rcb->sz,(rcb->cbAlloced+CHARBUFFER_ALLOCSTEP)); + if(buf==NULL) return; + rcb->sz=buf; + rcb->cbAlloced+=CHARBUFFER_ALLOCSTEP; + } + rcb->sz[rcb->iEnd++]=c; + rcb->sz[rcb->iEnd]='\0'; +} + +void AppendToCharBuffer(struct ResizableCharBuffer *rcb,const char *fmt,...) +{ + va_list va; + int charsDone; + char *buf; + + if(rcb->cbAlloced==0) { + buf=(char*)mir_alloc(CHARBUFFER_ALLOCSTEP); + if(buf==NULL) return; + rcb->sz=buf; + rcb->cbAlloced=CHARBUFFER_ALLOCSTEP; + } + va_start(va,fmt); + for(;;) { + charsDone=mir_vsnprintf(rcb->sz+rcb->iEnd,rcb->cbAlloced-rcb->iEnd,fmt,va); + if(charsDone>=0) break; // returns -1 when buffer not large enough + buf=(char*)mir_realloc(rcb->sz,rcb->cbAlloced+CHARBUFFER_ALLOCSTEP); + if(buf==NULL) { + charsDone=0; + break; + } + rcb->sz=buf; + rcb->cbAlloced+=CHARBUFFER_ALLOCSTEP; + } + va_end(va); + rcb->iEnd+=charsDone; +} -- cgit v1.2.3