summaryrefslogtreecommitdiff
path: root/Help/helpdlg.c
diff options
context:
space:
mode:
Diffstat (limited to 'Help/helpdlg.c')
-rw-r--r--Help/helpdlg.c700
1 files changed, 700 insertions, 0 deletions
diff --git a/Help/helpdlg.c b/Help/helpdlg.c
new file mode 100644
index 0000000..8fa78bd
--- /dev/null
+++ b/Help/helpdlg.c
@@ -0,0 +1,700 @@
+/*
+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 <tchar.h>
+#include <stdio.h>
+#define _WIN32_WINNT 0x0500
+#define __RPCASYNC_H__ /* header shows warnings in VS6 */
+#include <windows.h>
+#include <win2k.h>
+
+#define MIRANDA_VER 0x0600
+#include <newpluginapi.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_system.h>
+#include "help.h"
+
+#include <richedit.h>
+#pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union */
+#include <commctrl.h>
+#pragma warning(default:4201) /* nonstandard extension used : nameless struct/union */
+#include "resource.h"
+
+extern HINSTANCE hInst;
+HWND hwndHelpDlg;
+
+static int HelpDialogResize(HWND hwndDlg,LPARAM lParam,UTILRESIZECONTROL *urc)
+{
+ UNREFERENCED_PARAMETER(hwndDlg);
+ UNREFERENCED_PARAMETER(lParam);
+ switch(urc->wId) {
+ case IDC_CTLTEXT:
+#ifdef EDITOR
+ case IDC_DLGID:
+ case IDC_MODULE:
+#endif
+ return RD_ANCHORX_WIDTH|RD_ANCHORY_TOP;
+ case IDC_TEXT:
+ return RD_ANCHORX_WIDTH|RD_ANCHORY_HEIGHT;
+ }
+ return RD_ANCHORX_LEFT|RD_ANCHORY_TOP;
+}
+
+#ifndef EDITOR
+BOOL CALLBACK ShadowDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(wParam);
+ switch(msg) {
+ case WM_INITDIALOG:
+ { BOOL (WINAPI *pfnSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
+ *(FARPROC*)&pfnSetLayeredWindowAttributes=GetProcAddress(GetModuleHandleA("USER32"),"SetLayeredWindowAttributes");
+ if(!pfnSetLayeredWindowAttributes) {
+ *(HANDLE*)lParam=NULL; // hwndShadowDlg reset
+ DestroyWindow(hwndDlg);
+ return FALSE;
+ }
+ EnableWindow(hwndDlg,FALSE);
+ SetWindowLong(hwndDlg,GWL_EXSTYLE,GetWindowLong(hwndDlg,GWL_EXSTYLE)|WS_EX_LAYERED);
+ pfnSetLayeredWindowAttributes(hwndDlg,RGB(0,0,0),96,LWA_ALPHA);
+ return FALSE;
+ }
+ case WM_CTLCOLORDLG:
+ return (BOOL)GetSysColorBrush(COLOR_WINDOWFRAME);
+ }
+ return FALSE;
+}
+
+// in client coordinates
+int GetCharRangeRect(HWND hwndEdit,LONG *cpMin,LONG cpMax,RECT *rcRange)
+{
+ LONG cpLineBreak;
+ { LONG nLine,nLinePrev;
+ if(*cpMin>cpMax) return 1;
+ nLine=SendMessage(hwndEdit,EM_EXLINEFROMCHAR,0,*cpMin);
+ for(cpLineBreak=*cpMin+1;cpLineBreak<=cpMax;cpLineBreak++) {
+ nLinePrev=nLine;
+ nLine=SendMessage(hwndEdit,EM_EXLINEFROMCHAR,0,cpLineBreak);
+ if(nLine!=nLinePrev) break;
+ }
+ cpMax=cpLineBreak-1;
+ }
+ { POINTL pt;
+ if(SendMessage(hwndEdit,EM_SETTYPOGRAPHYOPTIONS,0,0)) { // test for richedit v3.0
+ SendMessage(hwndEdit,EM_POSFROMCHAR,(WPARAM)&pt,*cpMin);
+ rcRange->left=pt.x; rcRange->top=pt.y;
+ SendMessage(hwndEdit,EM_POSFROMCHAR,(WPARAM)&pt,cpMax);
+ rcRange->right=pt.x; rcRange->bottom=pt.y;
+ }
+ else {
+ DWORD pos;
+ pos=SendMessage(hwndEdit,EM_POSFROMCHAR,(WPARAM)*cpMin,0);
+ POINTSTOPOINT(pt,MAKEPOINTS(pos));
+ rcRange->left=pt.x; rcRange->top=pt.y;
+ pos=SendMessage(hwndEdit,EM_POSFROMCHAR,(WPARAM)cpMax,0);
+ POINTSTOPOINT(pt,MAKEPOINTS(pos));
+ rcRange->right=pt.x; rcRange->bottom=pt.y;
+ }
+ }
+ { FORMATRANGE fr;
+ ZeroMemory(&fr,sizeof(fr));
+ fr.chrg.cpMin=*cpMin;
+ fr.chrg.cpMax=cpMax;
+ fr.hdc=fr.hdcTarget=GetDC(hwndEdit);
+ if(fr.hdc==NULL) return 1;
+ SendMessage(hwndEdit,EM_FORMATRANGE,0,(LPARAM)&fr);
+ PostMessage(hwndEdit,EM_FORMATRANGE,0,0); // clear memory
+ rcRange->bottom+=MulDiv(fr.rc.bottom,GetDeviceCaps(fr.hdc,LOGPIXELSY),1440); // twips to pixels
+ ReleaseDC(hwndEdit,fr.hdc);
+ }
+ *cpMin=cpLineBreak;
+ return 0;
+}
+
+static HCURSOR hHandCursor;
+static LRESULT CALLBACK HelpSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_KEYDOWN:
+ if(GetKeyState(VK_CONTROL)&0x8000 && wParam=='C') {
+ SendMessage(GetParent(hwnd),M_CLIPBOARDCOPY,0,0);
+ return 0;
+ }
+ break;
+ case WM_LBUTTONDBLCLK:
+ DestroyWindow(GetParent(hwnd));
+ return 0;
+ case WM_CONTEXTMENU:
+ return DefWindowProc(hwnd,msg,wParam,lParam); // redirect to parent
+ case WM_SETCURSOR: // not available via EN_MSGFILTER
+ if(GetDlgCtrlID((HWND)wParam)==IDC_TEXT) {
+ POINT pt;
+ DWORD pos;
+ CHARRANGE rng;
+ pos=GetMessagePos();
+ POINTSTOPOINT(pt,MAKEPOINTS(pos));
+ ScreenToClient((HWND)wParam,&pt);
+ pos=SendMessage((HWND)wParam,EM_CHARFROMPOS,0,(WPARAM)&pt);
+ if(IsHyperlink(pos,&rng.cpMin,&rng.cpMax,NULL)) {
+ RECT rc;
+ while(!GetCharRangeRect((HWND)wParam,&rng.cpMin,rng.cpMax,&rc))
+ if(PtInRect(&rc,pt)) {
+ SetCursor(hHandCursor);
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ return CallWindowProc((WNDPROC)GetWindowLong(hwnd,GWL_USERDATA),hwnd,msg,wParam,lParam);
+}
+#endif // !defined EDITOR
+
+BOOL CALLBACK HelpDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ HWND hwndCtl=(HWND)GetWindowLong(hwndDlg,GWL_USERDATA);
+ static LCID locale;
+#ifndef EDITOR
+ static HWND hwndShadowDlg;
+ static HWND hwndToolTip;
+#endif
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ hwndHelpDlg=hwndDlg;
+#ifdef EDITOR
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_DLGID),GWL_STYLE,GetWindowLong(GetDlgItem(hwndDlg,IDC_DLGID),GWL_STYLE)|SS_ENDELLIPSIS);
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_SETEVENTMASK,0,ENM_KEYEVENTS);
+ { RECT rcDlg,rcWork;
+ if(SystemParametersInfo(SPI_GETWORKAREA,0,&rcWork,FALSE) && GetWindowRect(hwndDlg,&rcDlg))
+ SetWindowPos(hwndDlg,0,rcDlg.left,rcWork.bottom-rcDlg.bottom+rcDlg.top,0,0,SWP_NOZORDER|SWP_NOSIZE);
+ }
+#else
+ { RECT rc,rcBuf;
+ SendDlgItemMessage(hwndDlg,IDC_CTLTEXT,EM_GETRECT,0,(LPARAM)&rcBuf);
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_GETRECT,0,(LPARAM)&rc);
+ rc.left=rcBuf.left; // sync richedit offset with edit
+ rc.right=rcBuf.right;
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_SETRECTNP,0,(LPARAM)&rc);
+ }
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_CTLTEXT),GWL_USERDATA,SetWindowLong(GetDlgItem(hwndDlg,IDC_CTLTEXT),GWL_WNDPROC,(LONG)HelpSubclassProc));
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_CARETSUCKER),GWL_USERDATA,SetWindowLong(GetDlgItem(hwndDlg,IDC_CARETSUCKER),GWL_WNDPROC,(LONG)HelpSubclassProc));
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_SETEVENTMASK,0,ENM_KEYEVENTS|ENM_MOUSEEVENTS|ENM_REQUESTRESIZE);
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_SETBKGNDCOLOR,0,GetSysColor(COLOR_INFOBK));
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_SETEDITSTYLE,SES_EXTENDBACKCOLOR,SES_EXTENDBACKCOLOR);
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT),GWL_USERDATA,SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT),GWL_WNDPROC,(LONG)HelpSubclassProc));
+ hwndShadowDlg=CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_SHADOW),hwndDlg,ShadowDlgProc,(LPARAM)&hwndShadowDlg);
+ hwndToolTip=CreateWindowEx(WS_EX_TOPMOST,TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_ALWAYSTIP|TTS_NOPREFIX,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hwndDlg,NULL,hInst,NULL);
+ if(hwndToolTip!=NULL) {
+ SetWindowPos(hwndToolTip,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ SendMessage(hwndToolTip,TTM_SETTIPBKCOLOR,GetSysColor(COLOR_WINDOW),0); // yelleow on yellow looks silly
+ SendMessage(hwndToolTip,TTM_SETDELAYTIME,TTDT_AUTOMATIC,GetDoubleClickTime()*3);
+ }
+ hHandCursor=(HCURSOR)LoadImage(NULL,IDC_HAND,IMAGE_CURSOR,0,0,LR_DEFAULTSIZE|LR_SHARED);
+ if(hHandCursor==NULL) // use fallback out of miranda32.exe
+ hHandCursor=(HCURSOR)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(214),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE|LR_SHARED);
+#endif
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_SETLANGOPTIONS,0,SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_GETLANGOPTIONS,0,0)|IMF_UIFONTS);
+ SetWindowPos(hwndDlg,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ return TRUE;
+ case WM_SIZE:
+ { UTILRESIZEDIALOG urd;
+ ZeroMemory(&urd,sizeof(urd));
+ urd.cbSize=sizeof(urd);
+ urd.hInstance=hInst;
+ urd.hwndDlg=hwndDlg;
+ urd.lpTemplate=MAKEINTRESOURCEA(IDD_HELP);
+ urd.pfnResizer=HelpDialogResize;
+ CallService(MS_UTILS_RESIZEDIALOG,0,(LPARAM)&urd);
+ InvalidateRect(hwndDlg,NULL,TRUE);
+#ifdef EDITOR
+ break;
+#endif
+ }
+#ifndef EDITOR
+ case WM_MOVE:
+ if(IsWindow(hwndShadowDlg)) {
+ RECT rc;
+ HRGN hRgnShadow,hRgnDlg;
+ if(!GetWindowRect(hwndDlg,&rc)) break;
+ hRgnShadow=CreateRectRgnIndirect(&rc);
+ if(hRgnShadow==NULL) break;
+ OffsetRgn(hRgnShadow,5,5);
+ hRgnDlg=CreateRectRgnIndirect(&rc);
+ if(hRgnDlg==NULL) break;
+ if(CombineRgn(hRgnShadow,hRgnShadow,hRgnDlg,RGN_DIFF)==ERROR) {
+ DeleteObject(hRgnShadow);
+ DeleteObject(hRgnDlg);
+ break;
+ }
+ DeleteObject(hRgnDlg);
+ OffsetRgn(hRgnShadow,-rc.left-5,-rc.top-5);
+ SetWindowRgn(hwndShadowDlg,hRgnShadow,FALSE); // system gets ownership of hRgnShadow
+ SetWindowPos(hwndShadowDlg,HWND_TOPMOST,rc.left+5,rc.top+5,rc.right-rc.left,rc.bottom-rc.top,SWP_SHOWWINDOW);
+ SetWindowPos(hwndDlg,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
+ }
+ break;
+ case WM_KEYDOWN:
+ if(GetKeyState(VK_CONTROL)&0x8000 && wParam=='C') {
+ SendMessage(hwndDlg,M_CLIPBOARDCOPY,0,0);
+ return TRUE;
+ }
+ break;
+ case WM_CONTEXTMENU:
+ { HMENU hMenu;
+ POINT pt;
+ POINTSTOPOINT(pt,MAKEPOINTS(lParam));
+ hMenu=CreatePopupMenu();
+ AppendMenu(hMenu,MF_STRING,WM_COPY,TranslateT("&Copy"));
+ if(TrackPopupMenuEx(hMenu,TPM_LEFTALIGN|TPM_TOPALIGN|TPM_HORPOSANIMATION|TPM_VERPOSANIMATION|TPM_RIGHTBUTTON|TPM_RETURNCMD|TPM_NONOTIFY,pt.x,pt.y,hwndDlg,NULL))
+ SendMessage(hwndDlg,M_CLIPBOARDCOPY,0,0);
+ DestroyMenu(hMenu);
+ }
+ return 0;
+ case WM_LBUTTONDBLCLK:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ case M_CLIPBOARDCOPY:
+ { HWND hwnd=GetFocus();
+ if(hwnd==GetDlgItem(hwndDlg,IDC_CTLTEXT) || hwnd==GetDlgItem(hwndDlg,IDC_TEXT)) {
+ CHARRANGE sel;
+ ZeroMemory(&sel,sizeof(sel));
+ SendMessage(hwnd,EM_GETSEL,(WPARAM)&sel.cpMin,(LPARAM)&sel.cpMax);
+ if(sel.cpMin!=sel.cpMax) {
+ SendMessage(hwnd,WM_COPY,0,0);
+ return TRUE;
+ }
+ }
+ }
+ if(OpenClipboard(hwndDlg)) {
+ HGLOBAL hglb;
+ int cch,len;
+ EmptyClipboard();
+ hglb=GlobalAlloc(GMEM_MOVEABLE,sizeof(LCID));
+ if(hglb!=NULL) {
+ LCID *plocale=GlobalLock(hglb);
+ if(plocale!=NULL) {
+ *plocale=locale;
+ GlobalUnlock(hglb);
+ if(!SetClipboardData(CF_LOCALE,hglb)) GlobalFree(hglb); // shell takes ownership
+ } else GlobalFree(hglb);
+ }
+ cch=GetWindowTextLength(GetDlgItem(hwndDlg,IDC_CTLTEXT))+GetWindowTextLength(GetDlgItem(hwndDlg,IDC_TEXT))+3;
+ hglb=GlobalAlloc(GMEM_MOVEABLE,(cch+1)*sizeof(TCHAR));
+ if(hglb!=NULL) {
+ TCHAR *pszText=GlobalLock(hglb);
+ if(pszText!=NULL) {
+ if(!GetWindowText(GetDlgItem(hwndDlg,IDC_CTLTEXT),pszText,cch-2)) pszText[0]=_T('\0');
+ len=lstrlen(pszText);
+ if(GetWindowText(GetDlgItem(hwndDlg,IDC_TEXT),pszText+len+2,cch-2-len) && len) {
+ pszText[len]=_T('\r');
+ pszText[len+1]=_T('\n');
+ }
+ GlobalUnlock(hglb);
+#if defined(_UNICODE)
+ if(!SetClipboardData(CF_UNICODETEXT,hglb)) GlobalFree(hglb); // shell takes ownership
+#else
+ if(!SetClipboardData(CF_TEXT,hglb)) GlobalFree(hglb); // shell takes ownership
+#endif
+ } else GlobalFree(hglb);
+ }
+ CloseClipboard();
+ }
+ return TRUE;
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORSTATIC:
+ SetTextColor((HDC)wParam,GetSysColor(COLOR_INFOTEXT));
+ SetBkColor((HDC)wParam,GetSysColor(COLOR_INFOBK));
+ return (BOOL)GetSysColorBrush(COLOR_INFOBK);
+ case WM_ACTIVATE:
+ if(LOWORD(wParam)!=WA_INACTIVE) break;
+ if(GetParent((HWND)lParam)==hwndDlg) break;
+ // fall through
+ case WM_SYSCOLORCHANGE:
+ case WM_ACTIVATEAPP:
+ PostMessage(hwndDlg,WM_CLOSE,0,0); // no DestroyWindow() here! would cause recursion
+ break;
+#endif // !defined EDITOR
+ case M_CHANGEHELPCONTROL:
+ if(hwndCtl==(HWND)lParam) break;
+ SetWindowLong(hwndDlg,GWL_USERDATA,lParam);
+ hwndCtl=(HWND)lParam;
+ SetDlgItemText(hwndDlg,IDC_CTLTEXT,NULL);
+#ifdef EDITOR
+ { TCHAR text[1024];
+ char *szModule,*szDlgId;
+
+ GetControlTitle(hwndCtl,text,SIZEOF(text));
+ SetDlgItemText(hwndDlg,IDC_CTLTEXT,text);
+ mir_sntprintf(text,SIZEOF(text),TranslateT("Control ID: %d"),GetControlID(hwndCtl));
+ SetDlgItemText(hwndDlg,IDC_CTLID,text);
+
+ szDlgId=CreateDialogIdString(GetControlDialog(hwndCtl));
+ mir_sntprintf(text,SIZEOF(text),TranslateT("Dialog ID: %hs"),(szDlgId!=NULL)?szDlgId:Translate("Unknown"));
+ mir_free(szDlgId); // does NULL check
+ SetDlgItemText(hwndDlg,IDC_DLGID,text);
+
+ mir_sntprintf(text,SIZEOF(text),TranslateT("Type: %s"),TranslateTS(szControlTypeNames[GetControlType(hwndCtl)]));
+ SetDlgItemText(hwndDlg,IDC_CTLTYPE,text);
+
+ szModule=GetControlModuleName(hwndCtl);
+ mir_sntprintf(text,SIZEOF(text),TranslateT("Module: %hs"),szModule?szModule:Translate("Unknown"));
+ mir_free(szModule); // does NULL check
+ SetDlgItemText(hwndDlg,IDC_MODULE,text);
+ }
+#endif // defined EDITOR
+ SetDlgItemText(hwndDlg,IDC_TEXT,NULL);
+ SendMessage(hwndDlg,M_LOADHELP,0,0);
+#ifdef EDITOR
+ ShowWindow(hwndDlg,SW_SHOWNORMAL);
+#else
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_REQUESTRESIZE,0,0);
+ return FALSE;
+#endif
+ return TRUE;
+ case M_HELPLOADFAILED:
+ if(hwndCtl!=(HWND)lParam) break;
+#ifdef EDITOR
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),TRUE);
+ { TCHAR text[2024];
+ GetControlTitle(hwndCtl,text,SIZEOF(text));
+ SetDlgItemText(hwndDlg,IDC_CTLTEXT,text);
+ }
+#else
+ SetDlgItemText(hwndDlg,IDC_CTLTEXT,TranslateT("No Help Pack installed!"));
+#endif
+ SetDlgItemText(hwndDlg,IDC_TEXT,NULL);
+ MessageBeep(MB_ICONERROR);
+ break;
+#ifdef EDITOR
+ case M_SAVECOMPLETE:
+#endif
+ case M_HELPLOADED:
+ if(hwndCtl!=(HWND)lParam) break;
+ case M_LOADHELP:
+ { TCHAR *szTitle;
+ char *szText;
+ char *szDlgId,*szModule;
+ UINT codepage;
+ BOOL isRTL;
+ int id,loading;
+#ifdef EDITOR
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),TRUE);
+#endif
+ szDlgId=CreateDialogIdString(GetControlDialog(hwndCtl));
+ szModule=GetControlModuleName(hwndCtl);
+ id=GetControlID(hwndCtl);
+#ifndef EDITOR
+ // show id string instead of help text when 'ctrl' key pressed
+ if(msg==M_LOADHELP && GetAsyncKeyState(VK_CONTROL)&0x8000) {
+ char *buf;
+ HWND hwnd;
+ buf=CreateControlIdentifier(szDlgId?szDlgId:"unknown",szModule?szModule:"unknown",id,hwndCtl);
+ hwnd=GetDlgItem(hwndDlg,IDC_CTLTEXT);
+ SetWindowTextA(hwnd,buf); // accepts NULL
+ SetDlgItemText(hwndDlg,IDC_TEXT,NULL);
+ mir_free(buf); // does NULL check
+ mir_free(szDlgId); // does NULL check
+ mir_free(szModule); // does NULL check
+ break;
+ }
+#endif
+ if(szDlgId==NULL || szModule==NULL) {
+ SetDlgItemText(hwndDlg,IDC_TEXT,NULL);
+#ifndef EDITOR
+ SetDlgItemText(hwndDlg,IDC_CTLTEXT,TranslateT("No help available for this item."));
+#endif
+ mir_free(szDlgId); // does NULL check
+ mir_free(szModule); // does NULL check
+ break;
+ }
+
+ loading=GetControlHelp(hwndCtl,szDlgId,szModule,id,&szTitle,&szText,NULL,&locale,&codepage,&isRTL,(msg==M_HELPLOADED)?GCHF_DONTLOAD:0);
+ if(!loading) {
+ if(szText) StreamInHtml(GetDlgItem(hwndDlg,IDC_TEXT),szText,codepage,RGB(255,0,0));
+ else SetDlgItemText(hwndDlg,IDC_TEXT,NULL);
+ if(szTitle) {
+ TCHAR buf[128];
+ RECT rc;
+ HFONT hFontPrev;
+ DWORD exStyle;
+ HWND hwndCtlText;
+ HDC hdc;
+ hwndCtlText=GetDlgItem(hwndDlg,IDC_CTLTEXT);
+ exStyle=GetWindowLong(GetDlgItem(hwndDlg,IDC_CTLTEXT),GWL_EXSTYLE);
+ hdc=GetDC(hwndCtlText);
+ { DWORD (WINAPI *pfnGetLayout)(HDC); // obey right-to-left languages
+ *(FARPROC*)&pfnGetLayout=GetProcAddress(GetModuleHandleA("GDI32"),"GetLayout");
+ if(pfnGetLayout) isRTL=(isRTL && !pfnGetLayout(hdc));
+ if(isRTL) exStyle|=WS_EX_RTLREADING|WS_EX_RIGHT;
+ else exStyle&=~(WS_EX_RTLREADING|WS_EX_RIGHT);
+ }
+ mir_sntprintf(buf,SIZEOF(buf)-4,_T("%s"),szTitle);
+ if(hdc!=NULL && hwndCtlText!=NULL) {
+ SendMessage(hwndCtlText,EM_GETRECT,0,(LPARAM)&rc);
+ hFontPrev=SelectObject(hdc,(HFONT)SendMessage(hwndCtlText,WM_GETFONT,0,0));
+ // doesn't actually draw the string due to DT_CALCRECT
+ DrawTextEx(hdc,buf,-1,&rc,DT_MODIFYSTRING|DT_CALCRECT|DT_EDITCONTROL|DT_END_ELLIPSIS|DT_INTERNAL|(isRTL?(DT_RTLREADING|DT_RIGHT):DT_LEFT)|DT_NOPREFIX|DT_SINGLELINE,NULL);
+ SelectObject(hdc,hFontPrev);
+ ReleaseDC(hwndCtlText,hdc);
+ }
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_CTLTEXT),GWL_EXSTYLE,exStyle);
+ SetWindowText(hwndCtlText,buf);
+ } else SetDlgItemText(hwndDlg,IDC_CTLTEXT,NULL);
+ }
+ else {
+ if(msg==M_HELPLOADED) {
+ SetDlgItemText(hwndDlg,IDC_TEXT,NULL);
+#ifndef EDITOR
+ SetDlgItemText(hwndDlg,IDC_CTLTEXT,TranslateT("No help available for this item."));
+#endif
+ }
+ else {
+#ifdef EDITOR
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),FALSE);
+ SetDlgItemText(hwndDlg,IDC_TEXT,TranslateT("Loading..."));
+#else
+ SetDlgItemText(hwndDlg,IDC_CTLTEXT,TranslateT("Loading..."));
+ SetDlgItemText(hwndDlg,IDC_TEXT,NULL);
+#endif
+ }
+ }
+ mir_free(szDlgId);
+ mir_free(szModule);
+ break;
+ }
+ case WM_NOTIFY:
+ switch(((NMHDR*)lParam)->idFrom) {
+ case IDC_TEXT:
+ switch(((NMHDR*)lParam)->code) {
+#ifdef EDITOR
+ case EN_MSGFILTER:
+ switch(((MSGFILTER*)lParam)->msg) {
+ case WM_CHAR:
+ switch(((MSGFILTER*)lParam)->wParam) {
+ case 'B'-'A'+1:
+ case 'I'-'A'+1:
+ case 'U'-'A'+1:
+ case 'H'-'A'+1:
+ case 'L'-'A'+1:
+ case 'S'-'A'+1:
+ case 'G'-'A'+1:
+ SetWindowLong(hwndDlg,DWL_MSGRESULT,TRUE);
+ return TRUE;
+ }
+ break;
+ case WM_KEYDOWN:
+ { CHARFORMAT cf;
+ int changes=0;
+
+ ZeroMemory(&cf,sizeof(cf));
+ if(!(GetKeyState(VK_CONTROL)&0x8000)) break;
+ cf.cbSize=sizeof(cf);
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_GETCHARFORMAT,TRUE,(LPARAM)&cf);
+ switch(((MSGFILTER*)lParam)->wParam) {
+ case 'B':
+ cf.dwEffects^=CFE_BOLD;
+ cf.dwMask=CFM_BOLD;
+ changes=1;
+ break;
+ case 'I':
+ cf.dwEffects^=CFE_ITALIC;
+ cf.dwMask=CFM_ITALIC;
+ changes=1;
+ break;
+ case 'U':
+ cf.dwEffects^=CFE_UNDERLINE;
+ cf.dwMask=CFM_UNDERLINE;
+ changes=1;
+ break;
+ case 'L':
+ { CHOOSECOLOR cc;
+ COLORREF custCol[16];
+ ZeroMemory(&custCol,sizeof(custCol));
+ ZeroMemory(&cc,sizeof(cc));
+ cc.lStructSize=sizeof(cc);
+ cc.hwndOwner=hwndDlg;
+ cc.lpCustColors=custCol;
+ cc.rgbResult=cf.crTextColor;
+ cc.Flags=CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT;
+ if(!ChooseColor(&cc)) break;
+ cf.crTextColor=0;
+ cf.dwEffects=0;
+ if(cc.rgbResult) cf.crTextColor=cc.rgbResult;
+ else cf.dwEffects=CFE_AUTOCOLOR;
+ cf.dwMask=CFM_COLOR;
+ changes=1;
+ break;
+ }
+ case 'H':
+ cf.dwEffects^=CFE_STRIKEOUT;
+ cf.dwMask=CFM_STRIKEOUT;
+ changes=1;
+ break;
+ case VK_OEM_PLUS:
+ cf.yHeight=((GetKeyState(VK_SHIFT)&0x8000)?TEXTSIZE_BIG:TEXTSIZE_NORMAL)*10;
+ cf.dwMask=CFM_SIZE;
+ changes=1;
+ break;
+ case VK_OEM_MINUS:
+ cf.yHeight=TEXTSIZE_SMALL*10;
+ cf.dwMask=CFM_SIZE;
+ changes=1;
+ break;
+ case 'S':
+ { TCHAR szTitle[1024];
+ char *szText,*szDlgId,*szModule;
+ if(!GetDlgItemText(hwndDlg,IDC_CTLTEXT,szTitle,SIZEOF(szTitle))) break;
+ szDlgId=CreateDialogIdString(GetControlDialog(hwndCtl));
+ if(szDlgId==NULL) break;
+ szText=StreamOutHtml(GetDlgItem(hwndDlg,IDC_TEXT));
+ szModule=GetControlModuleName(hwndCtl);
+ if(szModule==NULL) {
+ mir_free(szDlgId);
+ break;
+ }
+ SetControlHelp(szDlgId,szModule,GetControlID(hwndCtl),szTitle,szText,GetControlType(hwndCtl));
+ mir_free(szText);
+ mir_free(szDlgId);
+ mir_free(szModule);
+ SaveDialogCache();
+ SetWindowLong(hwndDlg,DWL_MSGRESULT,TRUE);
+ return TRUE;
+ }
+ case 'G':
+ SendMessage(hwndDlg,M_LOADHELP,0,0);
+ SetWindowLong(hwndDlg,DWL_MSGRESULT,TRUE);
+ return TRUE;
+ }
+ if(changes) {
+ SendDlgItemMessage(hwndDlg,IDC_TEXT,EM_SETCHARFORMAT,SCF_WORD|SCF_SELECTION,(LPARAM)&cf);
+ SetWindowLong(hwndDlg,DWL_MSGRESULT,TRUE);
+ return TRUE;
+ }
+ break;
+ }
+ }
+ break;
+#else // defined EDITOR
+ case EN_MSGFILTER:
+ { MSGFILTER *msgf=(MSGFILTER*)lParam;
+ switch(msgf->msg) {
+ case WM_LBUTTONUP:
+ { POINT pt;
+ DWORD pos;
+ CHARRANGE sel;
+ char *pszLink;
+ HWND hwndEdit=msgf->nmhdr.hwndFrom;
+
+ ZeroMemory(&sel,sizeof(sel));
+ SendMessage(msgf->nmhdr.hwndFrom,EM_EXGETSEL,0,(LPARAM)&sel);
+ if(sel.cpMin!=sel.cpMax) break;
+ POINTSTOPOINT(pt,MAKEPOINTS(msgf->lParam));
+ pos=SendMessage(hwndEdit,EM_CHARFROMPOS,0,(WPARAM)&pt);
+ if(IsHyperlink(pos,NULL,NULL,&pszLink)) {
+ CallService(MS_UTILS_OPENURL,1,(LPARAM)pszLink); // pszLink is MBCS string in CP_ACP
+ SetWindowLong(hwndDlg,DWL_MSGRESULT,TRUE);
+ return TRUE;
+ }
+ }
+ break;
+ case WM_MOUSEMOVE: // register hyperlink tooltips when current
+ if(hwndToolTip!=NULL) {
+ POINTL pt;
+ DWORD pos;
+ CHARRANGE rng;
+ char *pszLink;
+
+ POINTSTOPOINT(pt,MAKEPOINTS(msgf->lParam));
+ pos=SendMessage(msgf->nmhdr.hwndFrom,EM_CHARFROMPOS,0,(WPARAM)&pt);
+ if(IsHyperlink(pos,&rng.cpMin,&rng.cpMax,&pszLink)) { // pszLink is MBCS in CP_ACP
+ TTTOOLINFOA ti;
+ ZeroMemory(&ti,sizeof(ti));
+ ti.cbSize=sizeof(ti);
+ ti.hwnd=msgf->nmhdr.hwndFrom;
+ ti.uId=(UINT)rng.cpMin;
+ if(!SendMessage(hwndToolTip,TTM_GETTOOLINFOA,0,(LPARAM)&ti)) {
+ LONG cpRectMin;
+ ti.uFlags=TTF_SUBCLASS;
+ ti.lpszText=pszLink;
+ cpRectMin=rng.cpMin;
+ while(!GetCharRangeRect(ti.hwnd,&rng.cpMin,rng.cpMax,&ti.rect)) {
+ ti.uId=(UINT)cpRectMin;
+ SendMessage(hwndToolTip,TTM_ADDTOOLA,0,(LPARAM)&ti);
+ cpRectMin=rng.cpMin;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+ case EN_REQUESTRESIZE:
+ { RECT rcDlg,rcEdit,rcCtl,rcNew;
+ REQRESIZE *rr=(REQRESIZE*)lParam;
+ POINT ptScreenBottomRight;
+
+ if(!GetWindowRect(hwndDlg,&rcDlg)) break;
+ if(!GetWindowRect(hwndCtl,&rcCtl)) break;
+ if(!GetWindowRect(GetDlgItem(hwndDlg,IDC_TEXT),&rcEdit)) break;
+ rcNew.left=rcCtl.left+30;
+ rcNew.top=rcCtl.bottom+10;
+ rcNew.right=rcNew.left+(rr->rc.right-rr->rc.left)+(rcDlg.right-rcDlg.left)-(rcEdit.right-rcEdit.left)+(GetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT),GWL_STYLE)&WS_VSCROLL?GetSystemMetrics(SM_CXVSCROLL):0);
+ if(GetWindowTextLength(GetDlgItem(hwndDlg,IDC_TEXT)))
+ rcNew.bottom=rcNew.top+min(GetSystemMetrics(SM_CYSCREEN)/5,(rr->rc.bottom-rr->rc.top)+(rcDlg.bottom-rcDlg.top)-(rcEdit.bottom-rcEdit.top));
+ else
+ rcNew.bottom=rcNew.top+min(GetSystemMetrics(SM_CYSCREEN)/5,(rcDlg.bottom-rcDlg.top)-(rcEdit.bottom-rcEdit.top));
+ if(GetSystemMetrics(SM_CXVIRTUALSCREEN)) {
+ ptScreenBottomRight.x=GetSystemMetrics(SM_CXVIRTUALSCREEN)+GetSystemMetrics(SM_XVIRTUALSCREEN);
+ ptScreenBottomRight.y=GetSystemMetrics(SM_CYVIRTUALSCREEN)+GetSystemMetrics(SM_YVIRTUALSCREEN);
+ }
+ else {
+ ptScreenBottomRight.x=GetSystemMetrics(SM_CXSCREEN);
+ ptScreenBottomRight.y=GetSystemMetrics(SM_CYSCREEN);
+ }
+ if(rcNew.right>=ptScreenBottomRight.x) OffsetRect(&rcNew,ptScreenBottomRight.x-rcNew.right,0);
+ if(rcNew.bottom>=ptScreenBottomRight.y) OffsetRect(&rcNew,0,ptScreenBottomRight.y-rcNew.bottom);
+ SetWindowPos(hwndDlg,0,rcNew.left,rcNew.top,rcNew.right-rcNew.left,rcNew.bottom-rcNew.top,SWP_NOZORDER);
+ ShowWindow(hwndDlg,SW_SHOWNORMAL);
+ break;
+ }
+#endif // defined EDITOR
+ }
+ }
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDCANCEL: // WM_CLOSE
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ break;
+ case WM_DESTROY:
+#ifndef EDITOR
+ FreeHyperlinkData();
+ if(IsWindow(hwndShadowDlg)) DestroyWindow(hwndShadowDlg);
+ if(hwndToolTip!=NULL) DestroyWindow(hwndToolTip);
+#endif
+ hwndHelpDlg=NULL;
+ break;
+ }
+ return FALSE;
+}