Helpers.c
上传用户:tj_dwf
上传日期:2020-11-17
资源大小:215k
文件大小:57k
源码类别:

RichEdit

开发平台:

Visual C++

  1. /******************************************************************************
  2. *
  3. *
  4. * Notepad2
  5. *
  6. * Helpers.c
  7. *   General helper functions
  8. *   Parts taken from SciTE, (c) Neil Hodgson, http://www.scintilla.org
  9. *   MinimizeToTray (c) 2000 Matthew Ellis
  10. *
  11. * See Readme.txt for more information about this source code.
  12. * Please send me your comments to this work.
  13. *
  14. * See License.txt for details about distribution and modification.
  15. *
  16. *                                              (c) Florian Balmer 1996-2010
  17. *                                                  florian.balmer@gmail.com
  18. *                                               http://www.flos-freeware.ch
  19. *
  20. *
  21. ******************************************************************************/
  22. #define _WIN32_WINNT 0x501
  23. #include <windows.h>
  24. #include <shlobj.h>
  25. #include <shlwapi.h>
  26. #include <commctrl.h>
  27. #include <uxtheme.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include "helpers.h"
  31. #include "resource.h"
  32. //=============================================================================
  33. //
  34. //  Manipulation of (cached) ini file sections
  35. //
  36. int IniSectionGetString(
  37.       LPCWSTR lpCachedIniSection,
  38.       LPCWSTR lpName,
  39.       LPCWSTR lpDefault,
  40.       LPWSTR lpReturnedString,
  41.       int cchReturnedString)
  42. {
  43.   WCHAR *p = (WCHAR *)lpCachedIniSection;
  44.   WCHAR tch[256];
  45.   int  ich;
  46.   if (p) {
  47.     lstrcpy(tch,lpName);
  48.     lstrcat(tch,L"=");
  49.     ich = lstrlen(tch);
  50.     while (*p) {
  51.       if (StrCmpNI(p,tch,ich) == 0) {
  52.         lstrcpyn(lpReturnedString,p + ich,cchReturnedString);
  53.         return(lstrlen(lpReturnedString));
  54.       }
  55.       else
  56.         p = StrEnd(p) + 1;
  57.     }
  58.   }
  59.   lstrcpyn(lpReturnedString,lpDefault,cchReturnedString);
  60.   return(lstrlen(lpReturnedString));
  61. }
  62. int IniSectionGetInt(
  63.       LPCWSTR lpCachedIniSection,
  64.       LPCWSTR lpName,
  65.       int iDefault)
  66. {
  67.   WCHAR *p = (WCHAR *)lpCachedIniSection;
  68.   WCHAR tch[256];
  69.   int  ich;
  70.   int  i;
  71.   if (p) {
  72.     lstrcpy(tch,lpName);
  73.     lstrcat(tch,L"=");
  74.     ich = lstrlen(tch);
  75.     while (*p) {
  76.       if (StrCmpNI(p,tch,ich) == 0) {
  77.         if (swscanf(p + ich,L"%i",&i) == 1)
  78.           return(i);
  79.         else
  80.           return(iDefault);
  81.       }
  82.       else
  83.         p = StrEnd(p) + 1;
  84.     }
  85.   }
  86.   return(iDefault);
  87. }
  88. BOOL IniSectionSetString(LPWSTR lpCachedIniSection,LPCWSTR lpName,LPCWSTR lpString)
  89. {
  90.   WCHAR tch[32+512*3+32];
  91.   WCHAR *p = lpCachedIniSection;
  92.   if (p) {
  93.     while (*p) {
  94.       p = StrEnd(p) + 1;
  95.     }
  96.     wsprintf(tch,L"%s=%s",lpName,lpString);
  97.     lstrcpy(p,tch);
  98.     p = StrEnd(p) + 1;
  99.     *p = 0;
  100.     return(TRUE);
  101.   }
  102.   return(FALSE);
  103. }
  104. //=============================================================================
  105. //
  106. //  BeginWaitCursor()
  107. //
  108. void BeginWaitCursor()
  109. {
  110.   DestroyCursor(
  111.     SetCursor(
  112.     LoadCursor(NULL,IDC_WAIT)));
  113. }
  114. //=============================================================================
  115. //
  116. //  EndWaitCursor()
  117. //
  118. void EndWaitCursor()
  119. {
  120.   DestroyCursor(
  121.     SetCursor(
  122.     LoadCursor(NULL,IDC_ARROW)));
  123. }
  124. //=============================================================================
  125. //
  126. //  PrivateIsAppThemed()
  127. //
  128. extern HMODULE hModUxTheme;
  129. BOOL PrivateIsAppThemed()
  130. {
  131.   FARPROC pfnIsAppThemed;
  132.   BOOL bIsAppThemed = FALSE;
  133.   if (hModUxTheme) {
  134.     pfnIsAppThemed = GetProcAddress(hModUxTheme,"IsAppThemed");
  135.     if (pfnIsAppThemed)
  136.       bIsAppThemed = pfnIsAppThemed();
  137.   }
  138.   return bIsAppThemed;
  139. }
  140. //=============================================================================
  141. //
  142. //  PrivateSetCurrentProcessExplicitAppUserModelID()
  143. //
  144. HRESULT PrivateSetCurrentProcessExplicitAppUserModelID(PCWSTR AppID)
  145. {
  146.   FARPROC pfnSetCurrentProcessExplicitAppUserModelID;
  147.   if (lstrlen(AppID) == 0)
  148.     return(S_OK);
  149.   if (lstrcmpi(AppID,L"(default)") == 0)
  150.     return(S_OK);
  151.   pfnSetCurrentProcessExplicitAppUserModelID =
  152.     GetProcAddress(GetModuleHandleA("shell32.dll"),"SetCurrentProcessExplicitAppUserModelID");
  153.   if (pfnSetCurrentProcessExplicitAppUserModelID)
  154.     return(pfnSetCurrentProcessExplicitAppUserModelID(AppID));
  155.   else
  156.     return(S_OK);
  157. }
  158. //=============================================================================
  159. //
  160. //  IsElevated()
  161. //
  162. BOOL IsElevated() {
  163.   BOOL bIsElevated = FALSE;
  164.   HANDLE hToken = NULL;
  165.   if (!IsVista())
  166.     return(FALSE);
  167.   if (OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&hToken)) {
  168.     struct {
  169.       DWORD TokenIsElevated;
  170.     } /*TOKEN_ELEVATION*/te;
  171.     DWORD dwReturnLength = 0;
  172.     if (GetTokenInformation(hToken,/*TokenElevation*/20,&te,sizeof(te),&dwReturnLength)) {
  173.         if (dwReturnLength == sizeof(te))
  174.           bIsElevated = te.TokenIsElevated;
  175.     }
  176.     CloseHandle( hToken );
  177.   }
  178.   return bIsElevated;
  179. }
  180. //=============================================================================
  181. //
  182. //  SetExplorerTheme()
  183. //
  184. //BOOL SetExplorerTheme(HWND hwnd)
  185. //{
  186. //  FARPROC pfnSetWindowTheme;
  187. //
  188. //  if (IsVista()) {
  189. //    if (hModUxTheme) {
  190. //      pfnSetWindowTheme = GetProcAddress(hModUxTheme,"SetWindowTheme");
  191. //
  192. //      if (pfnSetWindowTheme)
  193. //        return (S_OK == pfnSetWindowTheme(hwnd,L"Explorer",NULL));
  194. //    }
  195. //  }
  196. //  return FALSE;
  197. //}
  198. //=============================================================================
  199. //
  200. //  VerifyContrast()
  201. //  Check if two colors can be distinguished
  202. //
  203. BOOL VerifyContrast(COLORREF cr1,COLORREF cr2)
  204. {
  205.   BYTE r1 = GetRValue(cr1);
  206.   BYTE g1 = GetGValue(cr1);
  207.   BYTE b1 = GetBValue(cr1);
  208.   BYTE r2 = GetRValue(cr2);
  209.   BYTE g2 = GetGValue(cr2);
  210.   BYTE b2 = GetBValue(cr2);
  211.   return(
  212.     ((abs((3*r1 + 5*g1 + 1*b1) - (3*r2 + 6*g2 + 1*b2))) >= 400) ||
  213.     ((abs(r1-r2) + abs(b1-b2) + abs(g1-g2)) >= 400));
  214. }
  215. //=============================================================================
  216. //
  217. //  SetWindowTitle()
  218. //
  219. BOOL bFreezeAppTitle = FALSE;
  220. BOOL SetWindowTitle(HWND hwnd,UINT uIDAppName,BOOL bIsElevated,UINT uIDUntitled,
  221.                     LPCWSTR lpszFile,int iFormat,BOOL bModified,
  222.                     UINT uIDReadOnly,BOOL bReadOnly,LPCWSTR lpszExcerpt)
  223. {
  224.   WCHAR szUntitled[128];
  225.   WCHAR szExcrptQuot[256];
  226.   WCHAR szExcrptFmt[32];
  227.   WCHAR szAppName[128];
  228.   WCHAR szElevatedAppName[128];
  229.   WCHAR szReadOnly[32];
  230.   WCHAR szTitle[512];
  231.   static const WCHAR *pszSep = L" - ";
  232.   static const WCHAR *pszMod = L"* ";
  233.   if (bFreezeAppTitle)
  234.     return FALSE;
  235.   if (!GetString(uIDAppName,szAppName,COUNTOF(szAppName)) ||
  236.       !GetString(uIDUntitled,szUntitled,COUNTOF(szUntitled)))
  237.     return FALSE;
  238.   if (bIsElevated) {
  239.     FormatString(szElevatedAppName,COUNTOF(szElevatedAppName),IDS_APPTITLE_ELEVATED,szAppName);
  240.     StrCpyN(szAppName,szElevatedAppName,COUNTOF(szAppName));
  241.   }
  242.   if (bModified)
  243.     lstrcpy(szTitle,pszMod);
  244.   else
  245.     lstrcpy(szTitle,L"");
  246.   if (lstrlen(lpszExcerpt)) {
  247.     GetString(IDS_TITLEEXCERPT,szExcrptFmt,COUNTOF(szExcrptFmt));
  248.     wsprintf(szExcrptQuot,szExcrptFmt,lpszExcerpt);
  249.     StrCat(szTitle,szExcrptQuot);
  250.   }
  251.   else if (lstrlen(lpszFile))
  252.   {
  253.     if (iFormat < 2 && !PathIsRoot(lpszFile))
  254.     {
  255.       SHFILEINFO shfi;
  256.       if (SHGetFileInfo2(lpszFile,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME))
  257.         lstrcat(szTitle,shfi.szDisplayName);
  258.       else
  259.         lstrcat(szTitle,PathFindFileName(lpszFile));
  260.       if (iFormat == 1) {
  261.         WCHAR tchPath[MAX_PATH];
  262.         StrCpyN(tchPath,lpszFile,COUNTOF(tchPath));
  263.         PathRemoveFileSpec(tchPath);
  264.         StrCat(szTitle,L" [");
  265.         StrCat(szTitle,tchPath);
  266.         StrCat(szTitle,L"]");
  267.       }
  268.     }
  269.     else
  270.       lstrcat(szTitle,lpszFile);
  271.   }
  272.   else
  273.     lstrcat(szTitle,szUntitled);
  274.   if (bReadOnly && GetString(uIDReadOnly,szReadOnly,COUNTOF(szReadOnly)))
  275.   {
  276.     lstrcat(szTitle,L" ");
  277.     lstrcat(szTitle,szReadOnly);
  278.   }
  279.   lstrcat(szTitle,pszSep);
  280.   lstrcat(szTitle,szAppName);
  281.   return SetWindowText(hwnd,szTitle);
  282. }
  283. //=============================================================================
  284. //
  285. //  SetWindowTransparentMode()
  286. //
  287. void SetWindowTransparentMode(HWND hwnd,BOOL bTransparentMode)
  288. {
  289.   FARPROC fp;
  290.   int  iAlphaPercent;
  291.   BYTE bAlpha;
  292.   if (bTransparentMode) {
  293.     if (fp = GetProcAddress(GetModuleHandle(L"User32"),"SetLayeredWindowAttributes")) {
  294.       SetWindowLong(hwnd,GWL_EXSTYLE,
  295.         GetWindowLong(hwnd,GWL_EXSTYLE) | WS_EX_LAYERED);
  296.       // get opacity level from registry
  297.       iAlphaPercent = IniGetInt(L"Settings2",L"OpacityLevel",75);
  298.       if (iAlphaPercent < 0 || iAlphaPercent > 100)
  299.         iAlphaPercent = 75;
  300.       bAlpha = iAlphaPercent * 255 / 100;
  301.       fp(hwnd,0,bAlpha,LWA_ALPHA);
  302.     }
  303.   }
  304.   else
  305.     SetWindowLong(hwnd,GWL_EXSTYLE,
  306.       GetWindowLong(hwnd,GWL_EXSTYLE) & ~WS_EX_LAYERED);
  307. }
  308. //=============================================================================
  309. //
  310. //  CenterDlgInParent()
  311. //
  312. void CenterDlgInParent(HWND hDlg)
  313. {
  314.   RECT rcDlg;
  315.   HWND hParent;
  316.   RECT rcParent;
  317.   MONITORINFO mi;
  318.   HMONITOR hMonitor;
  319.   int xMin, yMin, xMax, yMax, x, y;
  320.   GetWindowRect(hDlg,&rcDlg);
  321.   hParent = GetParent(hDlg);
  322.   GetWindowRect(hParent,&rcParent);
  323.   hMonitor = MonitorFromRect(&rcParent,MONITOR_DEFAULTTONEAREST);
  324.   mi.cbSize = sizeof(mi);
  325.   GetMonitorInfo(hMonitor,&mi);
  326.   xMin = mi.rcWork.left;
  327.   yMin = mi.rcWork.top;
  328.   xMax = (mi.rcWork.right) - (rcDlg.right - rcDlg.left);
  329.   yMax = (mi.rcWork.bottom) - (rcDlg.bottom - rcDlg.top);
  330.   if ((rcParent.right - rcParent.left) - (rcDlg.right - rcDlg.left) > 20)
  331.     x = rcParent.left + (((rcParent.right - rcParent.left) - (rcDlg.right - rcDlg.left)) / 2);
  332.   else
  333.     x = rcParent.left + 70;
  334.   if ((rcParent.bottom - rcParent.top) - (rcDlg.bottom - rcDlg.top) > 20)
  335.     y = rcParent.top  + (((rcParent.bottom - rcParent.top) - (rcDlg.bottom - rcDlg.top)) / 2);
  336.   else
  337.     y = rcParent.top + 60;
  338.   SetWindowPos(hDlg,NULL,max(xMin,min(xMax,x)),max(yMin,min(yMax,y)),0,0,SWP_NOZORDER|SWP_NOSIZE);
  339. }
  340. //=============================================================================
  341. //
  342. //  GetDlgPos()
  343. //
  344. void GetDlgPos(HWND hDlg,LPINT xDlg,LPINT yDlg)
  345. {
  346.   RECT rcDlg;
  347.   HWND hParent;
  348.   RECT rcParent;
  349.   GetWindowRect(hDlg,&rcDlg);
  350.   hParent = GetParent(hDlg);
  351.   GetWindowRect(hParent,&rcParent);
  352.   // return positions relative to parent window
  353.   *xDlg = rcDlg.left - rcParent.left;
  354.   *yDlg = rcDlg.top - rcParent.top;
  355. }
  356. //=============================================================================
  357. //
  358. //  SetDlgPos()
  359. //
  360. void SetDlgPos(HWND hDlg,int xDlg,int yDlg)
  361. {
  362.   RECT rcDlg;
  363.   HWND hParent;
  364.   RECT rcParent;
  365.   MONITORINFO mi;
  366.   HMONITOR hMonitor;
  367.   int xMin, yMin, xMax, yMax, x, y;
  368.   GetWindowRect(hDlg,&rcDlg);
  369.   hParent = GetParent(hDlg);
  370.   GetWindowRect(hParent,&rcParent);
  371.   hMonitor = MonitorFromRect(&rcParent,MONITOR_DEFAULTTONEAREST);
  372.   mi.cbSize = sizeof(mi);
  373.   GetMonitorInfo(hMonitor,&mi);
  374.   xMin = mi.rcWork.left;
  375.   yMin = mi.rcWork.top;
  376.   xMax = (mi.rcWork.right) - (rcDlg.right - rcDlg.left);
  377.   yMax = (mi.rcWork.bottom) - (rcDlg.bottom - rcDlg.top);
  378.   // desired positions relative to parent window
  379.   x = rcParent.left + xDlg;
  380.   y = rcParent.top + yDlg;
  381.   SetWindowPos(hDlg,NULL,max(xMin,min(xMax,x)),max(yMin,min(yMax,y)),0,0,SWP_NOZORDER|SWP_NOSIZE);
  382. }
  383. //=============================================================================
  384. //
  385. //  Resize Dialog Helpers()
  386. //
  387. typedef struct _resizedlg {
  388.   int cxClient;
  389.   int cyClient;
  390.   int cxFrame;
  391.   int cyFrame;
  392.   int mmiPtMinX;
  393.   int mmiPtMinY;
  394. } RESIZEDLG, *PRESIZEDLG;
  395. void ResizeDlg_Init(HWND hwnd,int cxFrame,int cyFrame,int nIdGrip)
  396. {
  397.   RECT rc;
  398.   WCHAR wch[64];
  399.   int cGrip;
  400.   RESIZEDLG *pm = LocalAlloc(LPTR,sizeof(RESIZEDLG));
  401.   GetClientRect(hwnd,&rc);
  402.   pm->cxClient = rc.right - rc.left;
  403.   pm->cyClient = rc.bottom - rc.top;
  404.   pm->cxFrame = cxFrame;
  405.   pm->cyFrame = cyFrame;
  406.   AdjustWindowRectEx(&rc,GetWindowLongPtr(hwnd,GWL_STYLE)|WS_THICKFRAME,FALSE,0);
  407.   pm->mmiPtMinX = rc.right-rc.left;
  408.   pm->mmiPtMinY = rc.bottom-rc.top;
  409.   if (pm->cxFrame < (rc.right-rc.left))
  410.     pm->cxFrame = rc.right-rc.left;
  411.   if (pm->cyFrame < (rc.bottom-rc.top))
  412.     pm->cyFrame = rc.bottom-rc.top;
  413.   SetProp(hwnd,L"ResizeDlg",(HANDLE)pm);
  414.   SetWindowPos(hwnd,NULL,rc.left,rc.top,pm->cxFrame,pm->cyFrame,SWP_NOZORDER);
  415.   SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)|WS_THICKFRAME);
  416.   SetWindowPos(hwnd,NULL,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED);
  417.   GetMenuString(GetSystemMenu(GetParent(hwnd),FALSE),SC_SIZE,wch,COUNTOF(wch),MF_BYCOMMAND);
  418.   InsertMenu(GetSystemMenu(hwnd,FALSE),SC_CLOSE,MF_BYCOMMAND|MF_STRING|MF_ENABLED,SC_SIZE,wch);
  419.   InsertMenu(GetSystemMenu(hwnd,FALSE),SC_CLOSE,MF_BYCOMMAND|MF_SEPARATOR,0,NULL);
  420.   SetWindowLongPtr(GetDlgItem(hwnd,nIdGrip),GWL_STYLE,
  421.     GetWindowLongPtr(GetDlgItem(hwnd,nIdGrip),GWL_STYLE)|SBS_SIZEGRIP|WS_CLIPSIBLINGS);
  422.   cGrip = GetSystemMetrics(SM_CXHTHUMB);
  423.   SetWindowPos(GetDlgItem(hwnd,nIdGrip),NULL,pm->cxClient-cGrip,pm->cyClient-cGrip,cGrip,cGrip,SWP_NOZORDER);
  424. }
  425. void ResizeDlg_Destroy(HWND hwnd,int *cxFrame,int *cyFrame)
  426. {
  427.   RECT rc;
  428.   PRESIZEDLG pm = GetProp(hwnd,L"ResizeDlg");
  429.   GetWindowRect(hwnd,&rc);
  430.   *cxFrame = rc.right-rc.left;
  431.   *cyFrame = rc.bottom-rc.top;
  432.   RemoveProp(hwnd,L"ResizeDlg");
  433.   LocalFree(pm);
  434. }
  435. void ResizeDlg_Size(HWND hwnd,LPARAM lParam,int *cx,int *cy)
  436. {
  437.   PRESIZEDLG pm = GetProp(hwnd,L"ResizeDlg");
  438.   *cx = LOWORD(lParam) - pm->cxClient;
  439.   *cy = HIWORD(lParam) - pm->cyClient;
  440.   pm->cxClient = LOWORD(lParam);
  441.   pm->cyClient = HIWORD(lParam);
  442. }
  443. void ResizeDlg_GetMinMaxInfo(HWND hwnd,LPARAM lParam)
  444. {
  445.   PRESIZEDLG pm = GetProp(hwnd,L"ResizeDlg");
  446.   LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam;
  447.   lpmmi->ptMinTrackSize.x = pm->mmiPtMinX;
  448.   lpmmi->ptMinTrackSize.y = pm->mmiPtMinY;
  449. }
  450. HDWP DeferCtlPos(HDWP hdwp,HWND hwndDlg,int nCtlId,int dx,int dy,UINT uFlags)
  451. {
  452.   RECT rc;
  453.   HWND hwndCtl = GetDlgItem(hwndDlg,nCtlId);
  454.   GetWindowRect(hwndCtl,&rc);
  455.   MapWindowPoints(NULL,hwndDlg,(LPPOINT)&rc,2);
  456.   if (uFlags & SWP_NOSIZE)
  457.     return(DeferWindowPos(hdwp,hwndCtl,NULL,rc.left+dx,rc.top+dy,0,0,SWP_NOZORDER|SWP_NOSIZE));
  458.   else
  459.     return(DeferWindowPos(hdwp,hwndCtl,NULL,0,0,rc.right-rc.left+dx,rc.bottom-rc.top+dy,SWP_NOZORDER|SWP_NOMOVE));
  460. }
  461. //=============================================================================
  462. //
  463. //  MakeBitmapButton()
  464. //
  465. void MakeBitmapButton(HWND hwnd,int nCtlId,HINSTANCE hInstance,UINT uBmpId)
  466. {
  467.   HWND hwndCtl = GetDlgItem(hwnd,nCtlId);
  468.   BITMAP bmp;
  469.   BUTTON_IMAGELIST bi;
  470.   HBITMAP hBmp = LoadImage(hInstance,MAKEINTRESOURCE(uBmpId),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
  471.   GetObject(hBmp,sizeof(BITMAP),&bmp);
  472.   bi.himl = ImageList_Create(bmp.bmWidth,bmp.bmHeight,ILC_COLOR32|ILC_MASK,1,0);
  473.   ImageList_AddMasked(bi.himl,hBmp,CLR_DEFAULT);
  474.   DeleteObject(hBmp);
  475.   SetRect(&bi.margin,0,0,0,0);
  476.   bi.uAlign = BUTTON_IMAGELIST_ALIGN_CENTER;
  477.   SendMessage(hwndCtl,BCM_SETIMAGELIST,0,(LPARAM)&bi);
  478. }
  479. //=============================================================================
  480. //
  481. //  MakeColorPickButton()
  482. //
  483. void MakeColorPickButton(HWND hwnd,int nCtlId,HINSTANCE hInstance,COLORREF crColor)
  484. {
  485.   HWND hwndCtl = GetDlgItem(hwnd,nCtlId);
  486.   BUTTON_IMAGELIST bi;
  487.   HIMAGELIST himlOld = NULL;
  488.   HBITMAP hBmp;
  489.   COLORMAP colormap[2];
  490.   if (SendMessage(hwndCtl,BCM_GETIMAGELIST,0,(LPARAM)&bi))
  491.     himlOld = bi.himl;
  492.   if (IsWindowEnabled(hwndCtl) && crColor != -1) {
  493.     colormap[0].from = RGB(0x00,0x00,0x00);
  494.     colormap[0].to   = GetSysColor(COLOR_3DSHADOW);
  495.   }
  496.   else {
  497.     colormap[0].from = RGB(0x00,0x00,0x00);
  498.     colormap[0].to   = RGB(0xFF,0xFF,0xFF);
  499.   }
  500.   if (IsWindowEnabled(hwndCtl) && crColor != -1) {
  501.     if (crColor == RGB(0xFF,0xFF,0xFF))
  502.       crColor = RGB(0xFF,0xFF,0xFE);
  503.     colormap[1].from = RGB(0xFF,0xFF,0xFF);
  504.     colormap[1].to   = crColor;
  505.   }
  506.   else {
  507.     colormap[1].from = RGB(0xFF,0xFF,0xFF);
  508.     colormap[1].to   = RGB(0xFF,0xFF,0xFF);
  509.   }
  510.   hBmp = CreateMappedBitmap(hInstance,IDB_PICK,0,colormap,2);
  511.   bi.himl = ImageList_Create(10,10,ILC_COLORDDB|ILC_MASK,1,0);
  512.   ImageList_AddMasked(bi.himl,hBmp,RGB(0xFF,0xFF,0xFF));
  513.   DeleteObject(hBmp);
  514.   SetRect(&bi.margin,0,0,4,0);
  515.   bi.uAlign = BUTTON_IMAGELIST_ALIGN_RIGHT;
  516.   SendMessage(hwndCtl,BCM_SETIMAGELIST,0,(LPARAM)&bi);
  517.   InvalidateRect(hwndCtl,NULL,TRUE);
  518.   if (himlOld)
  519.     ImageList_Destroy(himlOld);
  520. }
  521. //=============================================================================
  522. //
  523. //  DeleteBitmapButton()
  524. //
  525. void DeleteBitmapButton(HWND hwnd,int nCtlId)
  526. {
  527.   HWND hwndCtl = GetDlgItem(hwnd,nCtlId);
  528.   BUTTON_IMAGELIST bi;
  529.   if (SendMessage(hwndCtl,BCM_GETIMAGELIST,0,(LPARAM)&bi))
  530.     ImageList_Destroy(bi.himl);
  531. }
  532. //=============================================================================
  533. //
  534. //  StatusSetText()
  535. //
  536. BOOL StatusSetText(HWND hwnd,UINT nPart,LPCWSTR lpszText)
  537. {
  538.   UINT uFlags = (nPart == 255) ? nPart|SBT_NOBORDERS : nPart;
  539.   return SendMessage(hwnd,SB_SETTEXT,uFlags,(LPARAM)lpszText);
  540. }
  541. //=============================================================================
  542. //
  543. //  SendWMSize()
  544. //
  545. LRESULT SendWMSize(HWND hwnd)
  546. {
  547.   RECT rc; GetClientRect(hwnd,&rc);
  548.   return(SendMessage(hwnd,WM_SIZE,SIZE_RESTORED,
  549.          MAKELPARAM(rc.right,rc.bottom)));
  550. }
  551. //=============================================================================
  552. //
  553. //  StatusSetTextID()
  554. //
  555. BOOL StatusSetTextID(HWND hwnd,UINT nPart,UINT uID)
  556. {
  557.   WCHAR szText[256];
  558.   UINT uFlags = (nPart == 255) ? nPart|SBT_NOBORDERS : nPart;
  559.   if (!uID)
  560.   {
  561.     SendMessage(hwnd,SB_SETTEXT,uFlags,0);
  562.     return TRUE;
  563.   }
  564.   if (!GetString(uID,szText,256))
  565.     return FALSE;
  566.   return SendMessage(hwnd,SB_SETTEXT,uFlags,(LPARAM)szText);
  567. }
  568. //=============================================================================
  569. //
  570. //  StatusCalcPaneWidth()
  571. //
  572. int StatusCalcPaneWidth(HWND hwnd,LPCWSTR lpsz)
  573. {
  574.   SIZE  size;
  575.   HDC   hdc   = GetDC(hwnd);
  576.   HFONT hfont = (HFONT)SendMessage(hwnd,WM_GETFONT,0,0);
  577.   HFONT hfold = SelectObject(hdc,hfont);
  578.   int   mmode = SetMapMode(hdc,MM_TEXT);
  579.   GetTextExtentPoint32(hdc,lpsz,lstrlen(lpsz),&size);
  580.   SetMapMode(hdc,mmode);
  581.   SelectObject(hdc,hfold);
  582.   ReleaseDC(hwnd,hdc);
  583.   return(size.cx + 9);
  584. }
  585. //=============================================================================
  586. //
  587. //  Toolbar_Get/SetButtons()
  588. //
  589. int Toolbar_GetButtons(HWND hwnd,int cmdBase,LPWSTR lpszButtons,int cchButtons)
  590. {
  591.   WCHAR tchButtons[512];
  592.   WCHAR tchItem[32];
  593.   int i,c;
  594.   TBBUTTON tbb;
  595.   lstrcpy(tchButtons,L"");
  596.   c = min(50,SendMessage(hwnd,TB_BUTTONCOUNT,0,0));
  597.   for (i = 0; i < c; i++) {
  598.     SendMessage(hwnd,TB_GETBUTTON,(WPARAM)i,(LPARAM)&tbb);
  599.     wsprintf(tchItem,L"%i ",
  600.       (tbb.idCommand==0)?0:tbb.idCommand-cmdBase+1);
  601.     lstrcat(tchButtons,tchItem);
  602.   }
  603.   TrimString(tchButtons);
  604.   lstrcpyn(lpszButtons,tchButtons,cchButtons);
  605.   return(c);
  606. }
  607. int Toolbar_SetButtons(HWND hwnd,int cmdBase,LPCWSTR lpszButtons,LPCTBBUTTON ptbb,int ctbb)
  608. {
  609.   WCHAR tchButtons[512];
  610.   WCHAR *p;
  611.   int i,c;
  612.   int iCmd;
  613.   ZeroMemory(tchButtons,COUNTOF(tchButtons)*sizeof(tchButtons[0]));
  614.   lstrcpyn(tchButtons,lpszButtons,COUNTOF(tchButtons)-2);
  615.   TrimString(tchButtons);
  616.   while (p = StrStr(tchButtons,L"  "))
  617.     MoveMemory((WCHAR*)p,(WCHAR*)p+1,(lstrlen(p) + 1) * sizeof(WCHAR));
  618.   c = SendMessage(hwnd,TB_BUTTONCOUNT,0,0);
  619.   for (i = 0; i < c; i++)
  620.     SendMessage(hwnd,TB_DELETEBUTTON,0,0);
  621.   for (i = 0; i < COUNTOF(tchButtons); i++)
  622.     if (tchButtons[i] == L' ') tchButtons[i] = 0;
  623.   p = tchButtons;
  624.   while (*p) {
  625.     if (swscanf(p,L"%i",&iCmd) == 1) {
  626.       iCmd = (iCmd==0)?0:iCmd+cmdBase-1;
  627.       for (i = 0; i < ctbb; i++) {
  628.         if (ptbb[i].idCommand == iCmd) {
  629.           SendMessage(hwnd,TB_ADDBUTTONS,(WPARAM)1,(LPARAM)&ptbb[i]);
  630.           break;
  631.         }
  632.       }
  633.     }
  634.     p = StrEnd(p)+1;
  635.   }
  636.   return(SendMessage(hwnd,TB_BUTTONCOUNT,0,0));
  637. }
  638. //=============================================================================
  639. //
  640. //  IsCmdEnabled()
  641. //
  642. BOOL IsCmdEnabled(HWND hwnd,UINT uId)
  643. {
  644.   HMENU hmenu;
  645.   UINT ustate;
  646.   hmenu = GetMenu(hwnd);
  647.   SendMessage(hwnd,WM_INITMENU,(WPARAM)hmenu,0);
  648.   ustate = GetMenuState(hmenu,uId,MF_BYCOMMAND);
  649.   if (ustate == 0xFFFFFFFF)
  650.     return TRUE;
  651.   else
  652.     return (!(ustate & (MF_GRAYED|MF_DISABLED)));
  653. }
  654. //=============================================================================
  655. //
  656. //  FormatString()
  657. //
  658. int FormatString(LPWSTR lpOutput,int nOutput,UINT uIdFormat,...)
  659. {
  660.   WCHAR *p = LocalAlloc(LPTR,sizeof(WCHAR)*nOutput);
  661.   if (GetString(uIdFormat,p,nOutput))
  662.     wvsprintf(lpOutput,p,(LPVOID)((PUINT_PTR)&uIdFormat+1));
  663.   LocalFree(p);
  664.   return lstrlen(lpOutput);
  665. }
  666. //=============================================================================
  667. //
  668. //  PathRelativeToApp()
  669. //
  670. void PathRelativeToApp(
  671.   LPWSTR lpszSrc,LPWSTR lpszDest,int cchDest,BOOL bSrcIsFile,
  672.   BOOL bUnexpandEnv,BOOL bUnexpandMyDocs) {
  673.   WCHAR wchAppPath[MAX_PATH];
  674.   WCHAR wchWinDir[MAX_PATH];
  675.   WCHAR wchUserFiles[MAX_PATH];
  676.   WCHAR wchPath[MAX_PATH];
  677.   WCHAR wchResult[MAX_PATH];
  678.   DWORD dwAttrTo = (bSrcIsFile) ? 0 : FILE_ATTRIBUTE_DIRECTORY;
  679.   GetModuleFileName(NULL,wchAppPath,COUNTOF(wchAppPath));
  680.   PathRemoveFileSpec(wchAppPath);
  681.   GetWindowsDirectory(wchWinDir,COUNTOF(wchWinDir));
  682.   SHGetFolderPath(NULL,CSIDL_PERSONAL,NULL,SHGFP_TYPE_CURRENT,wchUserFiles);
  683.   if (bUnexpandMyDocs &&
  684.       !PathIsRelative(lpszSrc) &&
  685.       !PathIsPrefix(wchUserFiles,wchAppPath) &&
  686.        PathIsPrefix(wchUserFiles,lpszSrc) &&
  687.        PathRelativePathTo(wchPath,wchUserFiles,FILE_ATTRIBUTE_DIRECTORY,lpszSrc,dwAttrTo)) {
  688.     lstrcpy(wchUserFiles,L"%CSIDL:MYDOCUMENTS%");
  689.     PathAppend(wchUserFiles,wchPath);
  690.     lstrcpy(wchPath,wchUserFiles);
  691.   }
  692.   else if (PathIsRelative(lpszSrc) || PathCommonPrefix(wchAppPath,wchWinDir,NULL))
  693.     lstrcpyn(wchPath,lpszSrc,COUNTOF(wchPath));
  694.   else {
  695.     if (!PathRelativePathTo(wchPath,wchAppPath,FILE_ATTRIBUTE_DIRECTORY,lpszSrc,dwAttrTo))
  696.       lstrcpyn(wchPath,lpszSrc,COUNTOF(wchPath));
  697.   }
  698.   if (bUnexpandEnv) {
  699.     if (!PathUnExpandEnvStrings(wchPath,wchResult,COUNTOF(wchResult)))
  700.       lstrcpyn(wchResult,wchPath,COUNTOF(wchResult));
  701.   }
  702.   else
  703.     lstrcpyn(wchResult,wchPath,COUNTOF(wchResult));
  704.   if (lpszDest == NULL || lpszSrc == lpszDest)
  705.     lstrcpyn(lpszSrc,wchResult,(cchDest == 0) ? MAX_PATH : cchDest);
  706.   else
  707.     lstrcpyn(lpszDest,wchResult,(cchDest == 0) ? MAX_PATH : cchDest);
  708. }
  709. //=============================================================================
  710. //
  711. //  PathAbsoluteFromApp()
  712. //
  713. void PathAbsoluteFromApp(LPWSTR lpszSrc,LPWSTR lpszDest,int cchDest,BOOL bExpandEnv) {
  714.   WCHAR wchPath[MAX_PATH];
  715.   WCHAR wchResult[MAX_PATH];
  716.   if (StrCmpNI(lpszSrc,L"%CSIDL:MYDOCUMENTS%",COUNTOF("%CSIDL:MYDOCUMENTS%")-1) == 0) {
  717.     SHGetFolderPath(NULL,CSIDL_PERSONAL,NULL,SHGFP_TYPE_CURRENT,wchPath);
  718.     PathAppend(wchPath,lpszSrc+COUNTOF("%CSIDL:MYDOCUMENTS%")-1);
  719.   }
  720.   else
  721.     lstrcpyn(wchPath,lpszSrc,COUNTOF(wchPath));
  722.   if (bExpandEnv)
  723.     ExpandEnvironmentStringsEx(wchPath,COUNTOF(wchPath));
  724.   if (PathIsRelative(wchPath)) {
  725.     GetModuleFileName(NULL,wchResult,COUNTOF(wchResult));
  726.     PathRemoveFileSpec(wchResult);
  727.     PathAppend(wchResult,wchPath);
  728.   }
  729.   else
  730.     lstrcpyn(wchResult,wchPath,COUNTOF(wchResult));
  731.   PathCanonicalizeEx(wchResult);
  732.   if (PathGetDriveNumber(wchResult) != -1)
  733.     CharUpperBuff(wchResult,1);
  734.   if (lpszDest == NULL || lpszSrc == lpszDest)
  735.     lstrcpyn(lpszSrc,wchResult,(cchDest == 0) ? MAX_PATH : cchDest);
  736.   else
  737.     lstrcpyn(lpszDest,wchResult,(cchDest == 0) ? MAX_PATH : cchDest);
  738. }
  739. ///////////////////////////////////////////////////////////////////////////////
  740. //
  741. //
  742. //  Name: PathIsLnkFile()
  743. //
  744. //  Purpose: Determine wheter pszPath is a Windows Shell Link File by
  745. //           comparing the filename extension with L".lnk"
  746. //
  747. //  Manipulates:
  748. //
  749. BOOL PathIsLnkFile(LPCWSTR pszPath)
  750. {
  751.   //WCHAR *pszExt;
  752.   WCHAR tchResPath[256];
  753.   if (!pszPath || !*pszPath)
  754.     return FALSE;
  755. /*pszExt = StrRChr(pszPath,NULL,L'.');
  756.   if (!pszExt)
  757.     return FALSE;
  758.   if (!lstrcmpi(pszExt,L".lnk"))
  759.     return TRUE;
  760.   else
  761.     return FALSE;*/
  762.   //if (!lstrcmpi(PathFindExtension(pszPath),L".lnk"))
  763.   //  return TRUE;
  764.   //else
  765.   //  return FALSE;
  766.   if (lstrcmpi(PathFindExtension(pszPath),L".lnk"))
  767.     return FALSE;
  768.   else
  769.     return PathGetLnkPath(pszPath,tchResPath,COUNTOF(tchResPath));
  770. }
  771. ///////////////////////////////////////////////////////////////////////////////
  772. //
  773. //
  774. //  Name: PathGetLnkPath()
  775. //
  776. //  Purpose: Try to get the path to which a lnk-file is linked
  777. //
  778. //
  779. //  Manipulates: pszResPath
  780. //
  781. BOOL PathGetLnkPath(LPCWSTR pszLnkFile,LPWSTR pszResPath,int cchResPath)
  782. {
  783.   IShellLink       *psl;
  784.   WIN32_FIND_DATA  fd;
  785.   BOOL             bSucceeded = FALSE;
  786.   if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink,NULL,
  787.                                  CLSCTX_INPROC_SERVER,
  788.                                  &IID_IShellLink,&psl)))
  789.   {
  790.     IPersistFile *ppf;
  791.     if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,&ppf)))
  792.     {
  793.       WORD wsz[MAX_PATH];
  794.       /*MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,
  795.                           pszLnkFile,-1,wsz,MAX_PATH);*/
  796.       lstrcpy(wsz,pszLnkFile);
  797.       if (SUCCEEDED(ppf->lpVtbl->Load(ppf,wsz,STGM_READ)))
  798.       {
  799.         if (NOERROR == psl->lpVtbl->GetPath(psl,pszResPath,cchResPath,&fd,0))
  800.           bSucceeded = TRUE;
  801.       }
  802.       ppf->lpVtbl->Release(ppf);
  803.     }
  804.     psl->lpVtbl->Release(psl);
  805.   }
  806.   // This additional check seems reasonable
  807.   if (!lstrlen(pszResPath))
  808.     bSucceeded = FALSE;
  809.   if (bSucceeded) {
  810.     ExpandEnvironmentStringsEx(pszResPath,cchResPath);
  811.     PathCanonicalizeEx(pszResPath);
  812.   }
  813.   return(bSucceeded);
  814. }
  815. ///////////////////////////////////////////////////////////////////////////////
  816. //
  817. //
  818. //  Name: PathIsLnkToDirectory()
  819. //
  820. //  Purpose: Determine wheter pszPath is a Windows Shell Link File which
  821. //           refers to a directory
  822. //
  823. //  Manipulates: pszResPath
  824. //
  825. BOOL PathIsLnkToDirectory(LPCWSTR pszPath,LPWSTR pszResPath,int cchResPath)
  826. {
  827.   WCHAR tchResPath[MAX_PATH];
  828.   if (PathIsLnkFile(pszPath)) {
  829.     if (PathGetLnkPath(pszPath,tchResPath,sizeof(WCHAR)*COUNTOF(tchResPath))) {
  830.       if (PathIsDirectory(tchResPath)) {
  831.         lstrcpyn(pszResPath,tchResPath,cchResPath);
  832.         return (TRUE);
  833.       }
  834.       else
  835.         return FALSE;
  836.       }
  837.     else
  838.       return FALSE;
  839.     }
  840.   else
  841.     return FALSE;
  842. }
  843. ///////////////////////////////////////////////////////////////////////////////
  844. //
  845. //
  846. //  Name: PathCreateDeskLnk()
  847. //
  848. //  Purpose: Modified to create a desktop link to Notepad2
  849. //
  850. //  Manipulates:
  851. //
  852. BOOL PathCreateDeskLnk(LPCWSTR pszDocument)
  853. {
  854.   WCHAR tchExeFile[MAX_PATH];
  855.   WCHAR tchDocTemp[MAX_PATH];
  856.   WCHAR tchArguments[MAX_PATH+16];
  857.   WCHAR tchLinkDir[MAX_PATH];
  858.   WCHAR tchDescription[64];
  859.   WCHAR tchLnkFileName[MAX_PATH];
  860.   IShellLink *psl;
  861.   BOOL bSucceeded = FALSE;
  862.   BOOL fMustCopy;
  863.   if (!pszDocument || lstrlen(pszDocument) == 0)
  864.     return TRUE;
  865.   // init strings
  866.   GetModuleFileName(NULL,tchExeFile,COUNTOF(tchExeFile));
  867.   lstrcpy(tchDocTemp,pszDocument);
  868.   PathQuoteSpaces(tchDocTemp);
  869.   lstrcpy(tchArguments,L"-n ");
  870.   lstrcat(tchArguments,tchDocTemp);
  871.   SHGetSpecialFolderPath(NULL,tchLinkDir,CSIDL_DESKTOP,TRUE);
  872.   GetString(IDS_LINKDESCRIPTION,tchDescription,COUNTOF(tchDescription));
  873.   // Try to construct a valid filename...
  874.   if (!SHGetNewLinkInfo(pszDocument,tchLinkDir,tchLnkFileName,&fMustCopy,SHGNLI_PREFIXNAME))
  875.     return(FALSE);
  876.   if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink,NULL,
  877.                                  CLSCTX_INPROC_SERVER,
  878.                                  &IID_IShellLink,&psl)))
  879.   {
  880.     IPersistFile *ppf;
  881.     if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,&ppf)))
  882.     {
  883.       WORD wsz[MAX_PATH];
  884.       /*MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,
  885.                           tchLnkFileName,-1,wsz,MAX_PATH);*/
  886.       lstrcpy(wsz,tchLnkFileName);
  887.       psl->lpVtbl->SetPath(psl,tchExeFile);
  888.       psl->lpVtbl->SetArguments(psl,tchArguments);
  889.       psl->lpVtbl->SetDescription(psl,tchDescription);
  890.       if (SUCCEEDED(ppf->lpVtbl->Save(ppf,wsz,TRUE)))
  891.         bSucceeded = TRUE;
  892.       ppf->lpVtbl->Release(ppf);
  893.     }
  894.     psl->lpVtbl->Release(psl);
  895.   }
  896.   return(bSucceeded);
  897. }
  898. ///////////////////////////////////////////////////////////////////////////////
  899. //
  900. //
  901. //  Name: PathCreateFavLnk()
  902. //
  903. //  Purpose: Modified to create a Notepad2 favorites link
  904. //
  905. //  Manipulates:
  906. //
  907. BOOL PathCreateFavLnk(LPCWSTR pszName,LPCWSTR pszTarget,LPCWSTR pszDir)
  908. {
  909.   WCHAR tchLnkFileName[MAX_PATH];
  910.   IShellLink *psl;
  911.   BOOL bSucceeded = FALSE;
  912.   if (!pszName || lstrlen(pszName) == 0)
  913.     return TRUE;
  914.   lstrcpy(tchLnkFileName,pszDir);
  915.   PathAppend(tchLnkFileName,pszName);
  916.   lstrcat(tchLnkFileName,L".lnk");
  917.   if (PathFileExists(tchLnkFileName))
  918.     return FALSE;
  919.   if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink,NULL,
  920.                                  CLSCTX_INPROC_SERVER,
  921.                                  &IID_IShellLink,&psl)))
  922.   {
  923.     IPersistFile *ppf;
  924.     if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,&ppf)))
  925.     {
  926.       WORD wsz[MAX_PATH];
  927.       /*MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,
  928.                           tchLnkFileName,-1,wsz,MAX_PATH);*/
  929.       lstrcpy(wsz,tchLnkFileName);
  930.       psl->lpVtbl->SetPath(psl,pszTarget);
  931.       if (SUCCEEDED(ppf->lpVtbl->Save(ppf,wsz,TRUE)))
  932.         bSucceeded = TRUE;
  933.       ppf->lpVtbl->Release(ppf);
  934.     }
  935.     psl->lpVtbl->Release(psl);
  936.   }
  937.   return(bSucceeded);
  938. }
  939. //=============================================================================
  940. //
  941. //  TrimString()
  942. //
  943. BOOL TrimString(LPWSTR lpString)
  944. {
  945.   LPWSTR psz;
  946.   if (!lpString || !*lpString)
  947.     return FALSE;
  948.   // Trim left
  949.   psz = lpString;
  950.   while (*psz == L' ')
  951.     psz = CharNext(psz);
  952.   MoveMemory(lpString,psz,sizeof(WCHAR)*(lstrlen(psz) + 1));
  953.   // Trim right
  954.   psz = StrEnd(lpString);
  955.   while (*(psz = CharPrev(lpString,psz)) == L' ')
  956.     *psz = L'';
  957.   return TRUE;
  958. }
  959. //=============================================================================
  960. //
  961. //  ExtractFirstArgument()
  962. //
  963. BOOL ExtractFirstArgument(LPCWSTR lpArgs,LPWSTR lpArg1,LPWSTR lpArg2)
  964. {
  965.   LPWSTR psz;
  966.   BOOL bQuoted = FALSE;
  967.   lstrcpy(lpArg1,lpArgs);
  968.   if (lpArg2)
  969.     *lpArg2 = L'';
  970.   if (!TrimString(lpArg1))
  971.     return FALSE;
  972.   if (*lpArg1 == L'"')
  973.   {
  974.     *lpArg1 = L' ';
  975.     TrimString(lpArg1);
  976.     bQuoted = TRUE;
  977.   }
  978.   if (bQuoted)
  979.     psz = StrChr(lpArg1,L'"');
  980.   else
  981.     psz = StrChr(lpArg1,L' ');;
  982.   if (psz)
  983.   {
  984.     *psz = L'';
  985.     if (lpArg2)
  986.       lstrcpy(lpArg2,psz + 1);
  987.   }
  988.   TrimString(lpArg1);
  989.   if (lpArg2)
  990.     TrimString(lpArg2);
  991.   return TRUE;
  992. }
  993. //=============================================================================
  994. //
  995. //  PrepareFilterStr()
  996. //
  997. void PrepareFilterStr(LPWSTR lpFilter)
  998. {
  999.   LPWSTR psz = StrEnd(lpFilter);
  1000.   while (psz != lpFilter)
  1001.   {
  1002.     if (*(psz = CharPrev(lpFilter,psz)) == L'|')
  1003.       *psz = L'';
  1004.   }
  1005. }
  1006. //=============================================================================
  1007. //
  1008. //  StrTab2Space() - in place conversion
  1009. //
  1010. void StrTab2Space(LPWSTR lpsz)
  1011. {
  1012.   WCHAR *c;
  1013.   while (c = StrChr(lpsz,L't'))
  1014.     *c = L' ';
  1015. }
  1016. //=============================================================================
  1017. //
  1018. //  ExpandEnvironmentStringsEx()
  1019. //
  1020. //  Adjusted for Windows 95
  1021. //
  1022. void ExpandEnvironmentStringsEx(LPWSTR lpSrc,DWORD dwSrc)
  1023. {
  1024.   WCHAR szBuf[312];
  1025.   if (ExpandEnvironmentStrings(lpSrc,szBuf,COUNTOF(szBuf)))
  1026.     lstrcpyn(lpSrc,szBuf,dwSrc);
  1027. }
  1028. //=============================================================================
  1029. //
  1030. //  PathCanonicalizeEx()
  1031. //
  1032. //
  1033. void PathCanonicalizeEx(LPWSTR lpSrc)
  1034. {
  1035.   WCHAR szDst[MAX_PATH];
  1036.   if (PathCanonicalize(szDst,lpSrc))
  1037.     lstrcpy(lpSrc,szDst);
  1038. }
  1039. //=============================================================================
  1040. //
  1041. //  GetLongPathNameEx()
  1042. //
  1043. //  Works fine with Windows 95!
  1044. //
  1045. extern LPMALLOC g_lpMalloc;
  1046. DWORD GetLongPathNameEx(LPCWSTR lpszShortPath,LPWSTR lpszLongPath,DWORD cchBuffer)
  1047. {
  1048.   WCHAR wszShortPath[MAX_PATH];
  1049.   WCHAR *pwchSep;
  1050.   LPSHELLFOLDER lpsfDesktop;
  1051.   ULONG chParsed = 0;
  1052.   ULONG dwAttributes = 0;
  1053.   LPITEMIDLIST  pidl = NULL;
  1054.   BOOL fSucceeded = FALSE;
  1055.   //MessageBox(GetFocus(),lpszShortPath,L"GetLongPathNameEx(): lpszShortPath",0);
  1056.   // Convert lpszShortPath to a UNICODE string
  1057.   /*MultiByteToWideChar(
  1058.     CP_ACP,MB_PRECOMPOSED,lpszShortPath,-1,wszShortPath,MAX_PATH);*/
  1059.   lstrcpy(wszShortPath,lpszShortPath);
  1060.   // convert slashes to backlsashes
  1061.   while (pwchSep = StrChr(wszShortPath,L'/'))
  1062.     *pwchSep = L'\';
  1063.   // Get Desktop Folder
  1064.   if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
  1065.   {
  1066.     // Convert wszShortPath to a pidl
  1067.     if (NOERROR == lpsfDesktop->lpVtbl->ParseDisplayName(
  1068.                      lpsfDesktop,NULL,NULL,wszShortPath,&chParsed,&pidl,&dwAttributes))
  1069.     {
  1070.       if (SHGetPathFromIDList(pidl,lpszLongPath))
  1071.         fSucceeded = FALSE;
  1072.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,pidl);
  1073.     }
  1074.   }
  1075.   //MessageBox(GetFocus(),lpszLongPath,L"GetLongPathNameEx(): lpszLongPath",0);
  1076.   if (fSucceeded)
  1077.     return(lstrlen(lpszLongPath));
  1078.   else {
  1079.     if (lpszShortPath != lpszLongPath)
  1080.       lstrcpy(lpszLongPath,lpszShortPath);
  1081.     return(0);
  1082.   }
  1083.   cchBuffer;
  1084. }
  1085. //=============================================================================
  1086. //
  1087. //  SHGetFileInfo2() - return a default name when the file has been removed
  1088. //
  1089. DWORD_PTR SHGetFileInfo2(LPCWSTR pszPath,DWORD dwFileAttributes,
  1090.                          SHFILEINFO *psfi,UINT cbFileInfo,UINT uFlags)
  1091. {
  1092.   if (PathFileExists(pszPath))
  1093.     return SHGetFileInfo(pszPath,dwFileAttributes,psfi,cbFileInfo,uFlags);
  1094.   else
  1095.     return SHGetFileInfo(pszPath,FILE_ATTRIBUTE_NORMAL,
  1096.                          psfi,cbFileInfo,uFlags|SHGFI_USEFILEATTRIBUTES);
  1097. }
  1098. //=============================================================================
  1099. //
  1100. //  FormatNumberStr()
  1101. //
  1102. int FormatNumberStr(LPWSTR lpNumberStr)
  1103. {
  1104.   WCHAR *c;
  1105.   WCHAR szSep[8];
  1106.   int  i = 0;
  1107.   if (!lstrlen(lpNumberStr))
  1108.     return(0);
  1109.   if (!GetLocaleInfo(LOCALE_USER_DEFAULT,
  1110.                      LOCALE_STHOUSAND,
  1111.                      szSep,
  1112.                      COUNTOF(szSep)))
  1113.     szSep[0] = L''';
  1114.   c = StrEnd(lpNumberStr);
  1115.   while ((c = CharPrev(lpNumberStr,c)) != lpNumberStr)
  1116.   {
  1117.     if (++i == 3)
  1118.     {
  1119.       i = 0;
  1120.       MoveMemory(c+1,c,sizeof(WCHAR)*(lstrlen(c)+1));
  1121.       *c = szSep[0];
  1122.     }
  1123.   }
  1124.   return(lstrlen(lpNumberStr));
  1125. }
  1126. //=============================================================================
  1127. //
  1128. //  SetDlgItemIntEx()
  1129. //
  1130. BOOL SetDlgItemIntEx(HWND hwnd,int nIdItem,UINT uValue)
  1131. {
  1132.   WCHAR szBuf[64];
  1133.   wsprintf(szBuf,L"%u",uValue);
  1134.   FormatNumberStr(szBuf);
  1135.   return(SetDlgItemText(hwnd,nIdItem,szBuf));
  1136. }
  1137. //=============================================================================
  1138. //
  1139. //  A2W: Convert Dialog Item Text form Unicode to UTF-8 and vice versa
  1140. //
  1141. UINT GetDlgItemTextA2W(UINT uCP,HWND hDlg,int nIDDlgItem,LPSTR lpString,int nMaxCount)
  1142. {
  1143.   WCHAR wsz[1024] = L"";
  1144.   UINT uRet = GetDlgItemTextW(hDlg,nIDDlgItem,wsz,COUNTOF(wsz));
  1145.   ZeroMemory(lpString,nMaxCount);
  1146.   WCharToMBCS(uCP,wsz,lpString,nMaxCount-2);
  1147.   return uRet;
  1148. }
  1149. UINT SetDlgItemTextA2W(UINT uCP,HWND hDlg,int nIDDlgItem,LPSTR lpString)
  1150. {
  1151.   WCHAR wsz[1024] = L"";
  1152.   MBCSToWChar(uCP,lpString,wsz,COUNTOF(wsz));
  1153.   return SetDlgItemTextW(hDlg,nIDDlgItem,wsz);
  1154. }
  1155. LRESULT ComboBox_AddStringA2W(UINT uCP,HWND hwnd,LPCSTR lpString)
  1156. {
  1157.   WCHAR wsz[1024] = L"";
  1158.   MBCSToWChar(uCP,lpString,wsz,COUNTOF(wsz));
  1159.   return SendMessageW(hwnd,CB_ADDSTRING,0,(LPARAM)wsz);
  1160. }
  1161. //=============================================================================
  1162. //
  1163. //  CodePageFromCharSet()
  1164. //
  1165. UINT CodePageFromCharSet(UINT uCharSet)
  1166. {
  1167.   CHARSETINFO ci;
  1168.   if (TranslateCharsetInfo((DWORD*)uCharSet,&ci,TCI_SRCCHARSET))
  1169.     return(ci.ciACP);
  1170.   else
  1171.     return(GetACP());
  1172. }
  1173. //=============================================================================
  1174. //
  1175. //  MRU functions
  1176. //
  1177. LPMRULIST MRU_Create(LPCWSTR pszRegKey,int iFlags,int iSize) {
  1178.   LPMRULIST pmru = LocalAlloc(LPTR,sizeof(MRULIST));
  1179.   ZeroMemory(pmru,sizeof(MRULIST));
  1180.   lstrcpyn(pmru->szRegKey,pszRegKey,COUNTOF(pmru->szRegKey));
  1181.   pmru->iFlags = iFlags;
  1182.   pmru->iSize = min(iSize,MRU_MAXITEMS);
  1183.   return(pmru);
  1184. }
  1185. BOOL MRU_Destroy(LPMRULIST pmru) {
  1186.   int i;
  1187.   for (i = 0; i < pmru->iSize; i++) {
  1188.     if (pmru->pszItems[i])
  1189.       LocalFree(pmru->pszItems[i]);
  1190.     }
  1191.   ZeroMemory(pmru,sizeof(MRULIST));
  1192.   LocalFree(pmru);
  1193.   return(1);
  1194. }
  1195. int MRU_Compare(LPMRULIST pmru,LPCWSTR psz1,LPCWSTR psz2) {
  1196.   if (pmru->iFlags & MRU_NOCASE)
  1197.     return(lstrcmpi(psz1,psz2));
  1198.   else
  1199.     return(lstrcmp(psz1,psz2));
  1200. }
  1201. BOOL MRU_Add(LPMRULIST pmru,LPCWSTR pszNew) {
  1202.   int i;
  1203.   for (i = 0; i < pmru->iSize; i++) {
  1204.     if (MRU_Compare(pmru,pmru->pszItems[i],pszNew) == 0) {
  1205.       LocalFree(pmru->pszItems[i]);
  1206.       break;
  1207.     }
  1208.   }
  1209.   i = min(i,pmru->iSize-1);
  1210.   for (; i > 0; i--)
  1211.     pmru->pszItems[i] = pmru->pszItems[i-1];
  1212.   pmru->pszItems[0] = StrDup(pszNew);
  1213.   return(1);
  1214. }
  1215. BOOL MRU_AddFile(LPMRULIST pmru,LPCWSTR pszFile,BOOL bRelativePath,BOOL bUnexpandMyDocs) {
  1216.   int i;
  1217.   for (i = 0; i < pmru->iSize; i++) {
  1218.     if (lstrcmpi(pmru->pszItems[i],pszFile) == 0) {
  1219.       LocalFree(pmru->pszItems[i]);
  1220.       break;
  1221.     }
  1222.     else {
  1223.       WCHAR wchItem[MAX_PATH];
  1224.       PathAbsoluteFromApp(pmru->pszItems[i],wchItem,COUNTOF(wchItem),TRUE);
  1225.       if (lstrcmpi(wchItem,pszFile) == 0) {
  1226.         LocalFree(pmru->pszItems[i]);
  1227.         break;
  1228.       }
  1229.     }
  1230.   }
  1231.   i = min(i,pmru->iSize-1);
  1232.   for (; i > 0; i--)
  1233.     pmru->pszItems[i] = pmru->pszItems[i-1];
  1234.   if (bRelativePath) {
  1235.     WCHAR wchFile[MAX_PATH];
  1236.     PathRelativeToApp((LPWSTR)pszFile,wchFile,COUNTOF(wchFile),TRUE,TRUE,bUnexpandMyDocs);
  1237.     pmru->pszItems[0] = StrDup(wchFile);
  1238.   }
  1239.   else
  1240.     pmru->pszItems[0] = StrDup(pszFile);
  1241.   return(1);
  1242. }
  1243. BOOL MRU_Delete(LPMRULIST pmru,int iIndex) {
  1244.   int i;
  1245.   if (iIndex < 0 || iIndex > pmru->iSize-1)
  1246.     return(0);
  1247.   if (pmru->pszItems[iIndex])
  1248.     LocalFree(pmru->pszItems[iIndex]);
  1249.   for (i = iIndex; i < pmru->iSize-1; i++) {
  1250.     pmru->pszItems[i] = pmru->pszItems[i+1];
  1251.     pmru->pszItems[i+1] = NULL;
  1252.   }
  1253.   return(1);
  1254. }
  1255. BOOL MRU_DeleteFileFromStore(LPMRULIST pmru,LPCWSTR pszFile) {
  1256.   int i = 0;
  1257.   LPMRULIST pmruStore;
  1258.   WCHAR wchItem[256];
  1259.   pmruStore = MRU_Create(pmru->szRegKey,pmru->iFlags,pmru->iSize);
  1260.   MRU_Load(pmruStore);
  1261.   while (MRU_Enum(pmruStore,i,wchItem,COUNTOF(wchItem)) != -1) {
  1262.     PathAbsoluteFromApp(wchItem,wchItem,COUNTOF(wchItem),TRUE);
  1263.     if (lstrcmpi(wchItem,pszFile) == 0)
  1264.       MRU_Delete(pmruStore,i);
  1265.     else
  1266.       i++;
  1267.   }
  1268.   MRU_Save(pmruStore);
  1269.   MRU_Destroy(pmruStore);
  1270.   return(1);
  1271. }
  1272. BOOL MRU_Empty(LPMRULIST pmru) {
  1273.   int i;
  1274.   for (i = 0; i < pmru->iSize; i++) {
  1275.     if (pmru->pszItems[i]) {
  1276.       LocalFree(pmru->pszItems[i]);
  1277.       pmru->pszItems[i] = NULL;
  1278.     }
  1279.   }
  1280.   return(1);
  1281. }
  1282. int MRU_Enum(LPMRULIST pmru,int iIndex,LPWSTR pszItem,int cchItem) {
  1283.   if (pszItem == NULL || cchItem == 0) {
  1284.     int i = 0;
  1285.     while (pmru->pszItems[i] && i < pmru->iSize)
  1286.       i++;
  1287.     return(i);
  1288.   }
  1289.   else {
  1290.     if (iIndex < 0 || iIndex > pmru->iSize-1 || !pmru->pszItems[iIndex])
  1291.       return(-1);
  1292.     else {
  1293.       lstrcpyn(pszItem,pmru->pszItems[iIndex],cchItem);
  1294.       return(lstrlen(pszItem));
  1295.     }
  1296.   }
  1297. }
  1298. BOOL MRU_Load(LPMRULIST pmru) {
  1299.   int i,n = 0;
  1300.   WCHAR tchName[32];
  1301.   WCHAR tchItem[1024];
  1302.   WCHAR *pIniSection = LocalAlloc(LPTR,sizeof(WCHAR)*32*1024);
  1303.   MRU_Empty(pmru);
  1304.   LoadIniSection(pmru->szRegKey,pIniSection,LocalSize(pIniSection)/sizeof(WCHAR));
  1305.   for (i = 0; i < pmru->iSize; i++) {
  1306.     wsprintf(tchName,L"%.2i",i+1);
  1307.     if (IniSectionGetString(pIniSection,tchName,L"",tchItem,COUNTOF(tchItem))) {
  1308.       /*if (pmru->iFlags & MRU_UTF8) {
  1309.         WCHAR wchItem[1024];
  1310.         int cbw = MultiByteToWideChar(CP_UTF7,0,tchItem,-1,wchItem,COUNTOF(wchItem));
  1311.         WideCharToMultiByte(CP_UTF8,0,wchItem,cbw,tchItem,COUNTOF(tchItem),NULL,NULL);
  1312.         pmru->pszItems[n++] = StrDup(tchItem);
  1313.       }
  1314.       else*/
  1315.         pmru->pszItems[n++] = StrDup(tchItem);
  1316.     }
  1317.   }
  1318.   LocalFree(pIniSection);
  1319.   return(1);
  1320. }
  1321. BOOL MRU_Save(LPMRULIST pmru) {
  1322.   int i;
  1323.   WCHAR tchName[32];
  1324.   WCHAR *pIniSection = LocalAlloc(LPTR,sizeof(WCHAR)*32*1024);
  1325.   //IniDeleteSection(pmru->szRegKey);
  1326.   for (i = 0; i < pmru->iSize; i++) {
  1327.     if (pmru->pszItems[i]) {
  1328.       wsprintf(tchName,L"%.2i",i+1);
  1329.       /*if (pmru->iFlags & MRU_UTF8) {
  1330.         WCHAR  tchItem[1024];
  1331.         WCHAR wchItem[1024];
  1332.         int cbw = MultiByteToWideChar(CP_UTF8,0,pmru->pszItems[i],-1,wchItem,COUNTOF(wchItem));
  1333.         WideCharToMultiByte(CP_UTF7,0,wchItem,cbw,tchItem,COUNTOF(tchItem),NULL,NULL);
  1334.         IniSectionSetString(pIniSection,tchName,tchItem);
  1335.       }
  1336.       else*/
  1337.         IniSectionSetString(pIniSection,tchName,pmru->pszItems[i]);
  1338.     }
  1339.   }
  1340.   SaveIniSection(pmru->szRegKey,pIniSection);
  1341.   LocalFree(pIniSection);
  1342.   return(1);
  1343. }
  1344. BOOL MRU_MergeSave(LPMRULIST pmru,BOOL bAddFiles,BOOL bRelativePath,BOOL bUnexpandMyDocs) {
  1345.   int i;
  1346.   LPMRULIST pmruBase;
  1347.   pmruBase = MRU_Create(pmru->szRegKey,pmru->iFlags,pmru->iSize);
  1348.   MRU_Load(pmruBase);
  1349.   if (bAddFiles) {
  1350.     for (i = pmru->iSize-1; i >= 0; i--) {
  1351.       if (pmru->pszItems[i]) {
  1352.         WCHAR wchItem[MAX_PATH];
  1353.         PathAbsoluteFromApp(pmru->pszItems[i],wchItem,COUNTOF(wchItem),TRUE);
  1354.         MRU_AddFile(pmruBase,wchItem,bRelativePath,bUnexpandMyDocs);
  1355.       }
  1356.     }
  1357.   }
  1358.   else {
  1359.     for (i = pmru->iSize-1; i >= 0; i--) {
  1360.       if (pmru->pszItems[i])
  1361.         MRU_Add(pmruBase,pmru->pszItems[i]);
  1362.     }
  1363.   }
  1364.   MRU_Save(pmruBase);
  1365.   MRU_Destroy(pmruBase);
  1366.   return(1);
  1367. }
  1368. /*
  1369.   Themed Dialogs
  1370.   Modify dialog templates to use current theme font
  1371.   Based on code of MFC helper class CDialogTemplate
  1372. */
  1373. BOOL GetThemedDialogFont(LPWSTR lpFaceName,WORD* wSize)
  1374. {
  1375.   HDC hDC;
  1376.   int iLogPixelsY;
  1377.   HMODULE hModUxTheme;
  1378.   HTHEME hTheme;
  1379.   LOGFONT lf;
  1380.   BOOL bSucceed = FALSE;
  1381.   hDC = GetDC(NULL);
  1382.   iLogPixelsY = GetDeviceCaps(hDC,LOGPIXELSY);
  1383.   ReleaseDC(NULL,hDC);
  1384.   if (hModUxTheme = GetModuleHandle(L"uxtheme.dll")) {
  1385.     if ((BOOL)(GetProcAddress(hModUxTheme,"IsAppThemed"))()) {
  1386.       hTheme = (HTHEME)(GetProcAddress(hModUxTheme,"OpenThemeData"))(NULL,L"WINDOWSTYLE;WINDOW");
  1387.       if (hTheme) {
  1388.         if (S_OK == (HRESULT)(GetProcAddress(hModUxTheme,"GetThemeSysFont"))(hTheme,/*TMT_MSGBOXFONT*/805,&lf)) {
  1389.           if (lf.lfHeight < 0)
  1390.             lf.lfHeight = -lf.lfHeight;
  1391.           *wSize = (WORD)MulDiv(lf.lfHeight,72,iLogPixelsY);
  1392.           if (*wSize == 0)
  1393.             *wSize = 8;
  1394.           StrCpyN(lpFaceName,lf.lfFaceName,LF_FACESIZE);
  1395.           bSucceed = TRUE;
  1396.         }
  1397.         (GetProcAddress(hModUxTheme,"CloseThemeData"))(hTheme);
  1398.       }
  1399.     }
  1400.   }
  1401.   /*
  1402.   if (!bSucceed) {
  1403.     NONCLIENTMETRICS ncm;
  1404.     ncm.cbSize = sizeof(NONCLIENTMETRICS);
  1405.     SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&ncm,0);
  1406.     if (ncm.lfMessageFont.lfHeight < 0)
  1407.       ncm.lfMessageFont.lfHeight = -ncm.lfMessageFont.lfHeight;
  1408.     *wSize = (WORD)MulDiv(ncm.lfMessageFont.lfHeight,72,iLogPixelsY);
  1409.     if (*wSize == 0)
  1410.       *wSize = 8;
  1411.     StrCpyN(lpFaceName,ncm.lfMessageFont.lfFaceName,LF_FACESIZE);
  1412.   }*/
  1413.   return(bSucceed);
  1414. }
  1415. __inline BOOL DialogTemplate_IsDialogEx(const DLGTEMPLATE* pTemplate) {
  1416.   return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
  1417. }
  1418. __inline BOOL DialogTemplate_HasFont(const DLGTEMPLATE* pTemplate) {
  1419.   return (DS_SETFONT &
  1420.     (DialogTemplate_IsDialogEx(pTemplate) ? ((DLGTEMPLATEEX*)pTemplate)->style : pTemplate->style));
  1421. }
  1422. __inline int DialogTemplate_FontAttrSize(BOOL bDialogEx) {
  1423.   return (int)sizeof(WORD) * (bDialogEx ? 3 : 1);
  1424. }
  1425. __inline BYTE* DialogTemplate_GetFontSizeField(const DLGTEMPLATE* pTemplate) {
  1426.   BOOL bDialogEx = DialogTemplate_IsDialogEx(pTemplate);
  1427.   WORD* pw;
  1428.   if (bDialogEx)
  1429.     pw = (WORD*)((DLGTEMPLATEEX*)pTemplate + 1);
  1430.   else
  1431.     pw = (WORD*)(pTemplate + 1);
  1432.   if (*pw == (WORD)-1)
  1433.     pw += 2;
  1434.   else
  1435.     while(*pw++);
  1436.   if (*pw == (WORD)-1)
  1437.     pw += 2;
  1438.   else
  1439.     while(*pw++);
  1440.   while (*pw++);
  1441.   return (BYTE*)pw;
  1442. }
  1443. DLGTEMPLATE* LoadThemedDialogTemplate(LPCTSTR lpDialogTemplateID,HINSTANCE hInstance) {
  1444.   HRSRC hRsrc;
  1445.   HGLOBAL hRsrcMem;
  1446.   DLGTEMPLATE *pRsrcMem;
  1447.   DLGTEMPLATE *pTemplate;
  1448.   UINT dwTemplateSize = 0;
  1449.   WCHAR wchFaceName[LF_FACESIZE];
  1450.   WORD wFontSize;
  1451.   BOOL bDialogEx;
  1452.   BOOL bHasFont;
  1453.   int cbFontAttr;
  1454.   int cbNew;
  1455.   int cbOld;
  1456.   BYTE* pbNew;
  1457.   BYTE* pb;
  1458.   BYTE* pOldControls;
  1459.   BYTE* pNewControls;
  1460.   WORD nCtrl;
  1461.   hRsrc = FindResource(hInstance,lpDialogTemplateID,RT_DIALOG);
  1462.   if (hRsrc == NULL)
  1463.     return(NULL);
  1464.   hRsrcMem = LoadResource(hInstance,hRsrc);
  1465.   pRsrcMem = (DLGTEMPLATE*)LockResource(hRsrcMem);
  1466.   dwTemplateSize = (UINT)SizeofResource(hInstance,hRsrc);
  1467.   if ((dwTemplateSize == 0) ||
  1468.       (pTemplate = LocalAlloc(LPTR,dwTemplateSize+LF_FACESIZE*2)) == NULL) {
  1469.     UnlockResource(hRsrcMem);
  1470.     FreeResource(hRsrcMem);
  1471.     return(NULL);
  1472.   }
  1473.   CopyMemory((BYTE*)pTemplate,pRsrcMem,(size_t)dwTemplateSize);
  1474.   UnlockResource(hRsrcMem);
  1475.   FreeResource(hRsrcMem);
  1476.   if (!GetThemedDialogFont(wchFaceName,&wFontSize))
  1477.     return(pTemplate);
  1478.   bDialogEx  = DialogTemplate_IsDialogEx(pTemplate);
  1479.   bHasFont   = DialogTemplate_HasFont(pTemplate);
  1480.   cbFontAttr = DialogTemplate_FontAttrSize(bDialogEx);
  1481.   if (bDialogEx)
  1482.     ((DLGTEMPLATEEX*)pTemplate)->style |= DS_SHELLFONT;
  1483.   else
  1484.     pTemplate->style |= DS_SHELLFONT;
  1485.   cbNew = cbFontAttr + ((lstrlen(wchFaceName) + 1) * sizeof(WCHAR));
  1486.   pbNew = (BYTE*)wchFaceName;
  1487.   pb = DialogTemplate_GetFontSizeField(pTemplate);
  1488.   cbOld = (int)(bHasFont ? cbFontAttr + 2 * (lstrlen((WCHAR*)(pb + cbFontAttr)) + 1) : 0);
  1489.   pOldControls = (BYTE*)(((DWORD_PTR)pb + cbOld + 3) & ~(DWORD_PTR)3);
  1490.   pNewControls = (BYTE*)(((DWORD_PTR)pb + cbNew + 3) & ~(DWORD_PTR)3);
  1491.   nCtrl = bDialogEx ?
  1492.     (WORD)((DLGTEMPLATEEX*)pTemplate)->cDlgItems :
  1493.     (WORD)pTemplate->cdit;
  1494.   if (cbNew != cbOld && nCtrl > 0)
  1495.     MoveMemory(pNewControls,pOldControls,(size_t)(dwTemplateSize - (pOldControls - (BYTE*)pTemplate)));
  1496.   *(WORD*)pb = wFontSize;
  1497.   MoveMemory(pb + cbFontAttr,pbNew,(size_t)(cbNew - cbFontAttr));
  1498.   return(pTemplate);
  1499. }
  1500. INT_PTR ThemedDialogBoxParam(
  1501.   HINSTANCE hInstance,
  1502.   LPCTSTR lpTemplate,
  1503.   HWND hWndParent,
  1504.   DLGPROC lpDialogFunc,
  1505.   LPARAM dwInitParam) {
  1506.   INT ret;
  1507.   DLGTEMPLATE *pDlgTemplate;
  1508.   pDlgTemplate = LoadThemedDialogTemplate(lpTemplate,hInstance);
  1509.   ret = DialogBoxIndirectParam(hInstance,pDlgTemplate,hWndParent,lpDialogFunc,dwInitParam);
  1510.   if (pDlgTemplate)
  1511.     LocalFree(pDlgTemplate);
  1512.   return(ret);
  1513. }
  1514. HWND CreateThemedDialogParam(
  1515.   HINSTANCE hInstance,
  1516.   LPCTSTR lpTemplate,
  1517.   HWND hWndParent,
  1518.   DLGPROC lpDialogFunc,
  1519.   LPARAM dwInitParam) {
  1520.   HWND hwnd;
  1521.   DLGTEMPLATE *pDlgTemplate;
  1522.   pDlgTemplate = LoadThemedDialogTemplate(lpTemplate,hInstance);
  1523.   hwnd = CreateDialogIndirectParam(hInstance,pDlgTemplate,hWndParent,lpDialogFunc,dwInitParam);
  1524.   if (pDlgTemplate)
  1525.     LocalFree(pDlgTemplate);
  1526.   return(hwnd);
  1527. }
  1528. /******************************************************************************
  1529. *
  1530. *  UnSlash functions
  1531. *  Mostly taken from SciTE, (c) Neil Hodgson, http://www.scintilla.org
  1532. *
  1533. /
  1534. /**
  1535.  * Is the character an octal digit?
  1536.  */
  1537. static BOOL IsOctalDigit(char ch) {
  1538.   return ch >= '0' && ch <= '7';
  1539. }
  1540. /**
  1541.  * If the character is an hexa digit, get its value.
  1542.  */
  1543. static int GetHexaDigit(char ch) {
  1544.   if (ch >= '0' && ch <= '9') {
  1545.     return ch - '0';
  1546.   }
  1547.   if (ch >= 'A' && ch <= 'F') {
  1548.     return ch - 'A' + 10;
  1549.   }
  1550.   if (ch >= 'a' && ch <= 'f') {
  1551.     return ch - 'a' + 10;
  1552.   }
  1553.   return -1;
  1554. }
  1555. /**
  1556.  * Convert C style a, b, f, n, r, t, v, ooo and xhh into their indicated characters.
  1557.  */
  1558. unsigned int UnSlash(char *s) {
  1559.   char *sStart = s;
  1560.   char *o = s;
  1561.   while (*s) {
  1562.     if (*s == '\') {
  1563.       s++;
  1564.       if (*s == 'a') {
  1565.         *o = 'a';
  1566.       } else if (*s == 'b') {
  1567.         *o = 'b';
  1568.       } else if (*s == 'f') {
  1569.         *o = 'f';
  1570.       } else if (*s == 'n') {
  1571.         *o = 'n';
  1572.       } else if (*s == 'r') {
  1573.         *o = 'r';
  1574.       } else if (*s == 't') {
  1575.         *o = 't';
  1576.       } else if (*s == 'v') {
  1577.         *o = 'v';
  1578.       } else if (IsOctalDigit(*s)) {
  1579.         int val = *s - '0';
  1580.         if (IsOctalDigit(*(s + 1))) {
  1581.           s++;
  1582.           val *= 8;
  1583.           val += *s - '0';
  1584.           if (IsOctalDigit(*(s + 1))) {
  1585.             s++;
  1586.             val *= 8;
  1587.             val += *s - '0';
  1588.           }
  1589.         }
  1590.         *o = (char)(val);
  1591.       } else if (*s == 'x') {
  1592.         int val, ghd;
  1593.         s++;
  1594.         val = 0;
  1595.         ghd = GetHexaDigit(*s);
  1596.         if (ghd >= 0) {
  1597.           s++;
  1598.           val = ghd;
  1599.           ghd = GetHexaDigit(*s);
  1600.           if (ghd >= 0) {
  1601.             s++;
  1602.             val *= 16;
  1603.             val += ghd;
  1604.           }
  1605.         }
  1606.         *o = (char)(val);
  1607.       } else {
  1608.         *o = *s;
  1609.       }
  1610.     } else {
  1611.       *o = *s;
  1612.     }
  1613.     o++;
  1614.     if (*s) {
  1615.       s++;
  1616.     }
  1617.   }
  1618.   *o = '';
  1619.   return o - sStart;
  1620. }
  1621. /**
  1622.  * Convert C style oo into their indicated characters.
  1623.  * This is used to get control characters into the regular expresion engine.
  1624.  */
  1625. unsigned int UnSlashLowOctal(char *s) {
  1626.   char *sStart = s;
  1627.   char *o = s;
  1628.   while (*s) {
  1629.     if ((s[0] == '\') && (s[1] == '0') && IsOctalDigit(s[2]) && IsOctalDigit(s[3])) {
  1630.       *o = (char)(8 * (s[2] - '0') + (s[3] - '0'));
  1631.       s += 3;
  1632.     } else {
  1633.       *o = *s;
  1634.     }
  1635.     o++;
  1636.     if (*s)
  1637.       s++;
  1638.   }
  1639.   *o = '';
  1640.   return o - sStart;
  1641. }
  1642. void TransformBackslashes(char* pszInput,BOOL bRegEx)
  1643. {
  1644.   if (bRegEx)
  1645.     UnSlashLowOctal(pszInput);
  1646.   else
  1647.     UnSlash(pszInput);
  1648. }
  1649. /*
  1650.   MinimizeToTray - Copyright 2000 Matthew Ellis <m.t.ellis@bigfoot.com>
  1651.   Changes made by flo:
  1652.    - Commented out: #include "stdafx.h"
  1653.    - Moved variable declaration: APPBARDATA appBarData;
  1654. */
  1655. // MinimizeToTray
  1656. //
  1657. // A couple of routines to show how to make it produce a custom caption
  1658. // animation to make it look like we are minimizing to and maximizing
  1659. // from the system tray
  1660. //
  1661. // These routines are public domain, but it would be nice if you dropped
  1662. // me a line if you use them!
  1663. //
  1664. // 1.0 29.06.2000 Initial version
  1665. // 1.1 01.07.2000 The window retains it's place in the Z-order of windows
  1666. //     when minimized/hidden. This means that when restored/shown, it doen't
  1667. //     always appear as the foreground window unless we call SetForegroundWindow
  1668. //
  1669. // Copyright 2000 Matthew Ellis <m.t.ellis@bigfoot.com>
  1670. /*#include "stdafx.h"*/
  1671. // Odd. VC++6 winuser.h has IDANI_CAPTION defined (as well as IDANI_OPEN and
  1672. // IDANI_CLOSE), but the Platform SDK only has IDANI_OPEN...
  1673. // I don't know what IDANI_OPEN or IDANI_CLOSE do. Trying them in this code
  1674. // produces nothing. Perhaps they were intended for window opening and closing
  1675. // like the MAC provides...
  1676. #ifndef IDANI_OPEN
  1677. #define IDANI_OPEN 1
  1678. #endif
  1679. #ifndef IDANI_CLOSE
  1680. #define IDANI_CLOSE 2
  1681. #endif
  1682. #ifndef IDANI_CAPTION
  1683. #define IDANI_CAPTION 3
  1684. #endif
  1685. #define DEFAULT_RECT_WIDTH 150
  1686. #define DEFAULT_RECT_HEIGHT 30
  1687. // Returns the rect of where we think the system tray is. This will work for
  1688. // all current versions of the shell. If explorer isn't running, we try our
  1689. // best to work with a 3rd party shell. If we still can't find anything, we
  1690. // return a rect in the lower right hand corner of the screen
  1691. static VOID GetTrayWndRect(LPRECT lpTrayRect)
  1692. {
  1693.   APPBARDATA appBarData;
  1694.   // First, we'll use a quick hack method. We know that the taskbar is a window
  1695.   // of class Shell_TrayWnd, and the status tray is a child of this of class
  1696.   // TrayNotifyWnd. This provides us a window rect to minimize to. Note, however,
  1697.   // that this is not guaranteed to work on future versions of the shell. If we
  1698.   // use this method, make sure we have a backup!
  1699.   HWND hShellTrayWnd=FindWindowEx(NULL,NULL,TEXT("Shell_TrayWnd"),NULL);
  1700.   if(hShellTrayWnd)
  1701.   {
  1702.     HWND hTrayNotifyWnd=FindWindowEx(hShellTrayWnd,NULL,TEXT("TrayNotifyWnd"),NULL);
  1703.     if(hTrayNotifyWnd)
  1704.     {
  1705.       GetWindowRect(hTrayNotifyWnd,lpTrayRect);
  1706.       return;
  1707.     }
  1708.   }
  1709.   // OK, we failed to get the rect from the quick hack. Either explorer isn't
  1710.   // running or it's a new version of the shell with the window class names
  1711.   // changed (how dare Microsoft change these undocumented class names!) So, we
  1712.   // try to find out what side of the screen the taskbar is connected to. We
  1713.   // know that the system tray is either on the right or the bottom of the
  1714.   // taskbar, so we can make a good guess at where to minimize to
  1715.   /*APPBARDATA appBarData;*/
  1716.   appBarData.cbSize=sizeof(appBarData);
  1717.   if(SHAppBarMessage(ABM_GETTASKBARPOS,&appBarData))
  1718.   {
  1719.     // We know the edge the taskbar is connected to, so guess the rect of the
  1720.     // system tray. Use various fudge factor to make it look good
  1721.     switch(appBarData.uEdge)
  1722.     {
  1723.       case ABE_LEFT:
  1724.       case ABE_RIGHT:
  1725.   // We want to minimize to the bottom of the taskbar
  1726.   lpTrayRect->top=appBarData.rc.bottom-100;
  1727.   lpTrayRect->bottom=appBarData.rc.bottom-16;
  1728.   lpTrayRect->left=appBarData.rc.left;
  1729.   lpTrayRect->right=appBarData.rc.right;
  1730.   break;
  1731.       case ABE_TOP:
  1732.       case ABE_BOTTOM:
  1733.   // We want to minimize to the right of the taskbar
  1734.   lpTrayRect->top=appBarData.rc.top;
  1735.   lpTrayRect->bottom=appBarData.rc.bottom;
  1736.   lpTrayRect->left=appBarData.rc.right-100;
  1737.   lpTrayRect->right=appBarData.rc.right-16;
  1738.   break;
  1739.     }
  1740.     return;
  1741.   }
  1742.   // Blimey, we really aren't in luck. It's possible that a third party shell
  1743.   // is running instead of explorer. This shell might provide support for the
  1744.   // system tray, by providing a Shell_TrayWnd window (which receives the
  1745.   // messages for the icons) So, look for a Shell_TrayWnd window and work out
  1746.   // the rect from that. Remember that explorer's taskbar is the Shell_TrayWnd,
  1747.   // and stretches either the width or the height of the screen. We can't rely
  1748.   // on the 3rd party shell's Shell_TrayWnd doing the same, in fact, we can't
  1749.   // rely on it being any size. The best we can do is just blindly use the
  1750.   // window rect, perhaps limiting the width and height to, say 150 square.
  1751.   // Note that if the 3rd party shell supports the same configuraion as
  1752.   // explorer (the icons hosted in NotifyTrayWnd, which is a child window of
  1753.   // Shell_TrayWnd), we would already have caught it above
  1754.   hShellTrayWnd=FindWindowEx(NULL,NULL,TEXT("Shell_TrayWnd"),NULL);
  1755.   if(hShellTrayWnd)
  1756.   {
  1757.     GetWindowRect(hShellTrayWnd,lpTrayRect);
  1758.     if(lpTrayRect->right-lpTrayRect->left>DEFAULT_RECT_WIDTH)
  1759.       lpTrayRect->left=lpTrayRect->right-DEFAULT_RECT_WIDTH;
  1760.     if(lpTrayRect->bottom-lpTrayRect->top>DEFAULT_RECT_HEIGHT)
  1761.       lpTrayRect->top=lpTrayRect->bottom-DEFAULT_RECT_HEIGHT;
  1762.     return;
  1763.   }
  1764.   // OK. Haven't found a thing. Provide a default rect based on the current work
  1765.   // area
  1766.   SystemParametersInfo(SPI_GETWORKAREA,0,lpTrayRect,0);
  1767.   lpTrayRect->left=lpTrayRect->right-DEFAULT_RECT_WIDTH;
  1768.   lpTrayRect->top=lpTrayRect->bottom-DEFAULT_RECT_HEIGHT;
  1769. }
  1770. // Check to see if the animation has been disabled
  1771. static BOOL GetDoAnimateMinimize(VOID)
  1772. {
  1773.   ANIMATIONINFO ai;
  1774.   ai.cbSize=sizeof(ai);
  1775.   SystemParametersInfo(SPI_GETANIMATION,sizeof(ai),&ai,0);
  1776.   return ai.iMinAnimate?TRUE:FALSE;
  1777. }
  1778. VOID MinimizeWndToTray(HWND hWnd)
  1779. {
  1780.   if(GetDoAnimateMinimize())
  1781.   {
  1782.     RECT rcFrom,rcTo;
  1783.     // Get the rect of the window. It is safe to use the rect of the whole
  1784.     // window - DrawAnimatedRects will only draw the caption
  1785.     GetWindowRect(hWnd,&rcFrom);
  1786.     GetTrayWndRect(&rcTo);
  1787.     // Get the system to draw our animation for us
  1788.     DrawAnimatedRects(hWnd,IDANI_CAPTION,&rcFrom,&rcTo);
  1789.   }
  1790.   // Add the tray icon. If we add it before the call to DrawAnimatedRects,
  1791.   // the taskbar gets erased, but doesn't get redrawn until DAR finishes.
  1792.   // This looks untidy, so call the functions in this order
  1793.   // Hide the window
  1794.   ShowWindow(hWnd,SW_HIDE);
  1795. }
  1796. VOID RestoreWndFromTray(HWND hWnd)
  1797. {
  1798.   if(GetDoAnimateMinimize())
  1799.   {
  1800.     // Get the rect of the tray and the window. Note that the window rect
  1801.     // is still valid even though the window is hidden
  1802.     RECT rcFrom,rcTo;
  1803.     GetTrayWndRect(&rcFrom);
  1804.     GetWindowRect(hWnd,&rcTo);
  1805.     // Get the system to draw our animation for us
  1806.     DrawAnimatedRects(hWnd,IDANI_CAPTION,&rcFrom,&rcTo);
  1807.   }
  1808.   // Show the window, and make sure we're the foreground window
  1809.   ShowWindow(hWnd,SW_SHOW);
  1810.   SetActiveWindow(hWnd);
  1811.   SetForegroundWindow(hWnd);
  1812.   // Remove the tray icon. As described above, remove the icon after the
  1813.   // call to DrawAnimatedRects, or the taskbar will not refresh itself
  1814.   // properly until DAR finished
  1815. }
  1816. ///   End of Helpers.c   \