mirror of https://github.com/roytam1/kmeleon.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
812 lines
25 KiB
812 lines
25 KiB
/* |
|
* Copyright (C) 2000 Brian Harris |
|
* |
|
* 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, or (at your option) |
|
* any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
*/ |
|
// ie_favorites.cpp : Plugin that supports ie-style boomarks |
|
// |
|
|
|
#include "stdafx.h" |
|
#include "resource.h" |
|
#include "wininet.h" // for INTERNET_MAX_URL_LENGTH |
|
|
|
#include <vector> |
|
|
|
#define KMELEON_PLUGIN_EXPORTS |
|
#include "../kmeleon_plugin.h" |
|
#include "../Utils.h" |
|
|
|
#include "../rebar_menu/hot_tracking.h" |
|
|
|
#define PLUGIN_NAME "IE Favorites Plugin" |
|
#define TOOLBAND_LABEL "Links" |
|
|
|
#define PREFERENCE_REBAR_ENABLED _T("kmeleon.plugins.favorites.rebar") |
|
|
|
#define REG_USER_SHELL_FOLDERS _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders") |
|
#define REG_SHELL_FOLDERS _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders") |
|
#define REG_FAVORITES_KEY _T("Favorites") |
|
|
|
#define MAX_FAVORITES 4096 |
|
|
|
#define ERROR_TOO_MANY_FAVORITES "Error! You have too many favorites!\n\n" \ |
|
"Right now, only 4096 favorites are supported" |
|
|
|
static CStringArray gFavorites; // this one contains the display filename (Really...vorite) |
|
static CStringArray gFavoritesFiles; // this one contains the full filename (SomeFolder\Stuff\Really Long Favorite) |
|
static CArray<UINT, int> gIcons; |
|
|
|
static UINT gNumFavorites; |
|
|
|
static int gInternetShortcutIcon; |
|
static int gFolderIcon; |
|
static HIMAGELIST gSystemImages; |
|
static CSize gSysImageSize; |
|
|
|
static HMENU gFavoritesMenu; |
|
|
|
static UINT nConfigCommand; |
|
static UINT nAddCommand; |
|
static UINT nEditCommand; |
|
static UINT nFirstFavoriteCommand; |
|
static BOOL bRebarEnabled; |
|
static HINSTANCE ghInstance; |
|
|
|
static TCHAR gFavoritesPath[MAX_PATH]; |
|
static int gFavoritesPathLen; |
|
|
|
static WNDPROC KMeleonWndProc; |
|
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); |
|
int BuildFavoritesMenu(char * strPath, HMENU mainMenu); |
|
|
|
BOOL CALLBACK DlgProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); |
|
|
|
int Load(); |
|
void Create(HWND parent); |
|
void Config(HWND parent); |
|
void Quit(); |
|
void DoMenu(HMENU menu, char *param); |
|
int DoAccel(char *param); |
|
void DoRebar(HWND rebarWnd); |
|
|
|
long DoMessage(const char *to, const char *from, const char *subject, long data1, long data2); |
|
|
|
kmeleonPlugin kPlugin = { |
|
KMEL_PLUGIN_VER, |
|
PLUGIN_NAME, |
|
DoMessage |
|
}; |
|
|
|
/* End K-Meleon Plugin Header */ |
|
|
|
long DoMessage(const char *to, const char *from, const char *subject, long data1, long data2) |
|
{ |
|
if (to[0] == '*' || stricmp(to, kPlugin.dllname) == 0) { |
|
if (stricmp(subject, "Load") == 0) { |
|
Load(); |
|
} |
|
else if (stricmp(subject, "Create") == 0) { |
|
Create((HWND)data1); |
|
} |
|
else if (stricmp(subject, "Config") == 0) { |
|
Config((HWND)data1); |
|
} |
|
else if (stricmp(subject, "Quit") == 0) { |
|
Quit(); |
|
} |
|
else if (stricmp(subject, "DoRebar") == 0) { |
|
DoRebar((HWND)data1); |
|
} |
|
else if (stricmp(subject, "DoMenu") == 0) { |
|
DoMenu((HMENU)data1, (char *)data2); |
|
} |
|
else if (stricmp(subject, "DoAccel") == 0) { |
|
*(int *)data2 = DoAccel((char *)data1); |
|
} |
|
else return 0; |
|
|
|
return 1; |
|
} |
|
return 0; |
|
} |
|
|
|
|
|
int Load() |
|
{ |
|
nConfigCommand = kPlugin.kFuncs->GetCommandIDs(1); |
|
nAddCommand = kPlugin.kFuncs->GetCommandIDs(1); |
|
nEditCommand = kPlugin.kFuncs->GetCommandIDs(1); |
|
|
|
nFirstFavoriteCommand = kPlugin.kFuncs->GetCommandIDs(MAX_FAVORITES); |
|
|
|
TCHAR sz[MAX_PATH]; |
|
HKEY hKey; |
|
DWORD dwSize; |
|
ITEMIDLIST *idl; |
|
|
|
long rslt = ERROR_SUCCESS; |
|
|
|
// first try the correct way |
|
if (SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &idl) == NOERROR) { |
|
IMalloc *malloc; |
|
SHGetPathFromIDList(idl, sz); |
|
SHGetMalloc(&malloc); |
|
malloc->Free(idl); |
|
malloc->Release(); |
|
} |
|
else { |
|
// if the correct way failed, find out from the registry where the favorites are located. |
|
if(RegOpenKey(HKEY_CURRENT_USER, REG_USER_SHELL_FOLDERS, &hKey) == ERROR_SUCCESS) { |
|
dwSize = MAX_PATH; |
|
rslt = RegQueryValueEx(hKey, REG_FAVORITES_KEY, NULL, NULL, (LPBYTE)sz, &dwSize); |
|
RegCloseKey(hKey); |
|
|
|
if (rslt != ERROR_SUCCESS) { |
|
if (RegOpenKey(HKEY_CURRENT_USER, REG_SHELL_FOLDERS, &hKey) == ERROR_SUCCESS) { |
|
rslt = RegQueryValueEx(hKey, REG_FAVORITES_KEY, NULL, NULL, (LPBYTE)sz, &dwSize); |
|
RegCloseKey(hKey); |
|
} |
|
else { |
|
TRACE0("Favorites folder not found\n"); |
|
rslt = -1; |
|
} |
|
} |
|
} |
|
else { |
|
TRACE0("Favorites folder not found\n"); |
|
rslt = -1; |
|
} |
|
} |
|
if (rslt == ERROR_SUCCESS) { |
|
ExpandEnvironmentStrings(sz, gFavoritesPath, MAX_PATH); |
|
|
|
strcat(gFavoritesPath, "\\"); |
|
gFavoritesPathLen = strlen(gFavoritesPath); |
|
} |
|
else { |
|
gFavoritesPath[0] = 0; |
|
gFavoritesPathLen = 0; |
|
} |
|
|
|
|
|
// Get the rebar status |
|
int pref = 0; |
|
kPlugin.kFuncs->GetPreference(PREF_BOOL, PREFERENCE_REBAR_ENABLED, &bRebarEnabled, &pref); |
|
|
|
return true; |
|
} |
|
|
|
void Create(HWND parent) |
|
{ |
|
KMeleonWndProc = (WNDPROC) GetWindowLong(parent, GWL_WNDPROC); |
|
SetWindowLong(parent, GWL_WNDPROC, (LONG)WndProc); |
|
} |
|
|
|
void Config(HWND hWndParent) |
|
{ |
|
gLoc->DialogBoxParam(MAKEINTRESOURCE(IDD_CONFIG), hWndParent, (DLGPROC)DlgProc, NULL); |
|
} |
|
|
|
void Quit() |
|
{ |
|
DestroyMenu(gFavoritesMenu); |
|
} |
|
|
|
void DoMenu(HMENU menu, char *param) |
|
{ |
|
// there are no favorites |
|
if (!*gFavoritesPath) |
|
return; |
|
|
|
if (*param != 0) { |
|
|
|
char *comma = strchr(param, ','); |
|
char *action = param; |
|
char *string = strchr(param, ','); |
|
if (string) { |
|
*string = 0; |
|
string = SkipWhiteSpace(string+1); |
|
} |
|
else |
|
string = action; |
|
|
|
int command = 0; |
|
if (stricmp(action, "Config") == 0){ |
|
command = nConfigCommand; |
|
} |
|
if (stricmp(action, "Add") == 0){ |
|
command = nAddCommand; |
|
} |
|
if (stricmp(action, "Edit") == 0){ |
|
command = nEditCommand; |
|
} |
|
if (command) { |
|
AppendMenu(menu, MF_STRING, command, string); |
|
} |
|
} |
|
else { |
|
gInternetShortcutIcon = -1; |
|
|
|
gFavoritesMenu = menu; |
|
BuildFavoritesMenu("", gFavoritesMenu); |
|
|
|
SHFILEINFO sfi; |
|
gSystemImages = (HIMAGELIST)SHGetFileInfo( gFavoritesPath, |
|
0, |
|
&sfi, |
|
sizeof(SHFILEINFO), |
|
SHGFI_SYSICONINDEX | SHGFI_SMALLICON); |
|
|
|
if (gSystemImages != NULL) { |
|
int cx, cy; |
|
|
|
ImageList_GetIconSize (gSystemImages, &cx, &cy); |
|
gSysImageSize = CSize (cx, cy); |
|
|
|
gFolderIcon = sfi.iIcon; |
|
} |
|
} |
|
} |
|
|
|
int DoAccel(char *param) |
|
{ |
|
if (stricmp(param, "Config") == 0){ |
|
return nConfigCommand; |
|
} |
|
if (stricmp(param, "Add") == 0){ |
|
return nAddCommand; |
|
} |
|
if (stricmp(param, "Edit") == 0){ |
|
return nEditCommand; |
|
} |
|
return nAddCommand; |
|
} |
|
|
|
|
|
void DoRebar(HWND rebarWnd){ |
|
|
|
if (!bRebarEnabled) |
|
return; |
|
|
|
DWORD dwStyle = 0x40 | /*the 40 gets rid of an ugly border on top. I have no idea what flag it corresponds to...*/ |
|
CCS_NOPARENTALIGN | CCS_NORESIZE | //CCS_ADJUSTABLE | |
|
TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_LIST | TBSTYLE_TOOLTIPS; |
|
|
|
// Create the toolbar control to be added. |
|
#if 1 |
|
HWND hwndTB = CreateWindowEx(0, TOOLBARCLASSNAME, "Links:", |
|
WS_CHILD | dwStyle, |
|
0,0,0,0, |
|
rebarWnd, (HMENU)/*id*/200, |
|
kPlugin.hDllInstance, NULL |
|
); |
|
#else |
|
HWND hwndTB = CreateToolbarEx(rebarWnd, dwStyle, |
|
/*id*/ 200, |
|
/*nBitmaps*/ 0, |
|
/*hBMInst*/ kPlugin.hDllInstance, |
|
/*wBMID*/ 0, |
|
/*lpButtons*/ NULL, |
|
/*iNumButtons*/ 0, |
|
/*dxButton*/ 16, |
|
/*dyButton*/ 16, |
|
/*dxBitmap*/ 16, |
|
/*dyBitmap*/ 16, |
|
/*uStructSize*/ sizeof(TBBUTTON) |
|
); |
|
#endif |
|
|
|
if (!hwndTB){ |
|
MessageBox(NULL, "Failed to create ie toolbar", NULL, 0); |
|
return; |
|
} |
|
|
|
// Register the band name and child hwnd |
|
kPlugin.kFuncs->RegisterBand(hwndTB, "Favorites", true); |
|
|
|
SetWindowText(hwndTB, TOOLBAND_LABEL); |
|
|
|
//SendMessage(hwndTB, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS); |
|
|
|
SendMessage(hwndTB, TB_SETIMAGELIST, 0, (LPARAM)gSystemImages); |
|
|
|
SendMessage(hwndTB, TB_SETBUTTONWIDTH, 0, MAKELONG(0, 100)); |
|
|
|
int stringID; |
|
int index; |
|
|
|
MENUITEMINFO mInfo; |
|
mInfo.cbSize = sizeof(MENUITEMINFO); |
|
|
|
int i; |
|
|
|
int count = GetMenuItemCount(gFavoritesMenu); |
|
HMENU hLinksMenu = NULL; |
|
for (i=0; i<count; i++){ |
|
if (GetMenuState(gFavoritesMenu, i, MF_BYPOSITION) & MF_POPUP){ |
|
bool isLinksMenu = false; |
|
|
|
mInfo.fMask = MIIM_TYPE; |
|
GetMenuItemInfo(gFavoritesMenu, i, MF_BYPOSITION, &mInfo); |
|
|
|
if (mInfo.fType == MFT_STRING) { |
|
char temp[128]; |
|
mInfo.cch = 127; |
|
mInfo.dwTypeData = temp; |
|
GetMenuItemInfo(gFavoritesMenu, i, MF_BYPOSITION, &mInfo); |
|
isLinksMenu = (mInfo.dwTypeData && stricmp(mInfo.dwTypeData, "Links") == 0); |
|
} |
|
else { |
|
// if it's ownerdrawn, we get at the string another way (damn, this is ugly...) |
|
mInfo.fMask = MIIM_DATA; |
|
GetMenuItemInfo(gFavoritesMenu, i, MF_BYPOSITION, &mInfo); |
|
isLinksMenu = (stricmp((char*)mInfo.dwItemData, "Links") == 0); |
|
} |
|
|
|
if (isLinksMenu) { |
|
hLinksMenu = GetSubMenu(gFavoritesMenu, i); |
|
break; |
|
} |
|
} |
|
} |
|
if (hLinksMenu == NULL) |
|
hLinksMenu = gFavoritesMenu; |
|
|
|
count = GetMenuItemCount(hLinksMenu); |
|
for (i=0; i<count; i++){ |
|
if (GetMenuState(hLinksMenu, i, MF_BYPOSITION) & MF_POPUP){ |
|
mInfo.fMask = MIIM_TYPE | MIIM_SUBMENU; |
|
GetMenuItemInfo(hLinksMenu, i, MF_BYPOSITION, &mInfo); |
|
|
|
if (mInfo.fType == MFT_STRING) { |
|
char temp[128]; |
|
mInfo.cch = 127; |
|
mInfo.dwTypeData = temp; |
|
GetMenuItemInfo(hLinksMenu, i, MF_BYPOSITION, &mInfo); |
|
stringID = SendMessage(hwndTB, TB_ADDSTRING, (WPARAM)NULL, (LPARAM)(LPCTSTR)mInfo.dwTypeData); |
|
} |
|
else { |
|
// if it's ownerdrawn, we get at the string another way (damn, this is ugly...) |
|
mInfo.fMask = MIIM_DATA | MIIM_SUBMENU; |
|
GetMenuItemInfo(hLinksMenu, i, MF_BYPOSITION, &mInfo); |
|
stringID = SendMessage(hwndTB, TB_ADDSTRING, (WPARAM)NULL, (LPARAM)(LPCTSTR)mInfo.dwItemData); |
|
} |
|
|
|
TBBUTTON button; |
|
button.iBitmap = gFolderIcon; |
|
button.idCommand = (int)mInfo.hSubMenu+SUBMENU_OFFSET; |
|
button.fsState = TBSTATE_ENABLED; |
|
button.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE | TBSTYLE_DROPDOWN; |
|
//button.bReserved = NULL; |
|
button.iString = stringID; |
|
|
|
SendMessage(hwndTB, TB_INSERTBUTTON, (WPARAM)-1, (LPARAM)&button); |
|
} |
|
else{ |
|
index = GetMenuItemID(hLinksMenu, i) - nFirstFavoriteCommand; |
|
|
|
if (index >= 0 && index < MAX_FAVORITES){ |
|
stringID = SendMessage(hwndTB, TB_ADDSTRING, (WPARAM)NULL, (LPARAM)(LPCTSTR)gFavorites[index]); |
|
|
|
TBBUTTON button; |
|
button.iBitmap = gIcons[index]; |
|
button.idCommand = index + nFirstFavoriteCommand; |
|
button.fsState = TBSTATE_ENABLED; |
|
button.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE; |
|
//button.bReserved = NULL; |
|
button.iString = stringID; |
|
|
|
SendMessage(hwndTB, TB_INSERTBUTTON, (WPARAM)-1, (LPARAM)&button); |
|
} |
|
} |
|
} |
|
|
|
// Get the width & height of the toolbar. |
|
SIZE size; |
|
SendMessage(hwndTB, TB_GETMAXSIZE, 0, (LPARAM)&size); |
|
|
|
REBARBANDINFO rbBand; |
|
rbBand.cbSize = sizeof(REBARBANDINFO); // Required |
|
rbBand.fMask = RBBIM_TEXT | |
|
RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | |
|
RBBIM_SIZE | RBBIM_IDEALSIZE; |
|
|
|
rbBand.fStyle = RBBS_CHILDEDGE | RBBS_FIXEDBMP | RBBS_VARIABLEHEIGHT; |
|
rbBand.lpText = "Links"; |
|
rbBand.hwndChild = hwndTB; |
|
rbBand.cxMinChild = 0; |
|
rbBand.cyMinChild = size.cy; |
|
rbBand.cyIntegral = 1; |
|
rbBand.cyMaxChild = rbBand.cyMinChild; |
|
rbBand.cxIdeal = size.cx + 16; |
|
rbBand.cx = rbBand.cxIdeal; |
|
|
|
// Add the band that has the toolbar. |
|
SendMessage(rebarWnd, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); |
|
} |
|
|
|
int BuildFavoritesMenu(char * strPath, HMENU mainMenu) |
|
{ |
|
// screen height |
|
int cy = GetSystemMetrics(SM_CYSCREEN); |
|
// menu line height |
|
// int cmenu = GetSystemMetrics(SM_CYMENU); |
|
// if bmp_menu is enabled, the menu items will actually be at least 18 pixels... but this system call won't reflect that |
|
// in any case, SM_CYMENU gets the height of the menu bar, not a menu item |
|
// for now we'll just assume bmp_menu is enabled and they're 18 pixels... |
|
#define cmenu 18 |
|
// space to allow above menu for title bar, menu bar (assuming maximized window), and extra frame junk |
|
#define MENUPADDING 50 |
|
int maxLength = (int)((cy-MENUPADDING)/cmenu); |
|
|
|
const int nStart = gNumFavorites; |
|
int nPos; |
|
|
|
int pathLen = strlen(strPath); |
|
|
|
char * searchString = new char[gFavoritesPathLen + pathLen + 2]; |
|
strcpy(searchString, gFavoritesPath); |
|
strcat(searchString, strPath); |
|
strcat(searchString, "*"); |
|
|
|
char * urlFile; |
|
char * subPath; |
|
|
|
// now scan the directory, first for .URL files and then for subdirectories |
|
// that may also contain .URL files |
|
WIN32_FIND_DATA wfd; |
|
HANDLE h = FindFirstFile(searchString, &wfd); |
|
|
|
delete [] searchString; |
|
|
|
if(h == INVALID_HANDLE_VALUE) { |
|
return gNumFavorites; |
|
} |
|
|
|
int tooMany = false; |
|
|
|
int count = GetMenuItemCount(mainMenu); |
|
|
|
do { |
|
if (count++ == maxLength) { |
|
HMENU childMenu = CreatePopupMenu(); |
|
AppendMenu(mainMenu, MF_STRING|MF_POPUP, (UINT)childMenu, "[more]"); |
|
mainMenu = childMenu; // and continue on, populating the new menu |
|
count = 0; |
|
} |
|
if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { |
|
// ignore the current and parent directory entries |
|
if(lstrcmp(wfd.cFileName, _T(".")) == 0 || lstrcmp(wfd.cFileName, _T("..")) == 0) |
|
continue; |
|
|
|
subPath = new char[pathLen + strlen(wfd.cFileName) + 2]; |
|
strcpy(subPath, strPath); |
|
strcat(subPath, wfd.cFileName); |
|
strcat(subPath, "/"); |
|
|
|
HMENU subMenu = CreatePopupMenu(); |
|
|
|
// call this function recursively. |
|
if(gNumFavorites < MAX_FAVORITES && BuildFavoritesMenu(subPath, subMenu)) { |
|
// only insert a submenu if there are in fact .URL files in the subdirectory |
|
char *pszTemp = fixString(wfd.cFileName, 40); |
|
AppendMenu(mainMenu, MF_BYCOMMAND | MF_POPUP | MF_STRING, (UINT)subMenu, pszTemp); |
|
delete pszTemp; |
|
} else{ |
|
DestroyMenu(subMenu); |
|
} |
|
|
|
delete [] subPath; |
|
|
|
} else if ((wfd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))==0) { |
|
// if it's not a hidden or system file |
|
|
|
char *dot = strrchr(wfd.cFileName, '.'); |
|
if(dot && stricmp(dot, ".url") == 0) { |
|
|
|
// scan through the array and perform an insertion sort |
|
// to make sure the menu ends up in alphabetic order |
|
// for(nPos = nStart; nPos < gNumFavorites; nPos++) { |
|
// if(stricmp(wfd.cFileName, gFavorites[nPos]) < 0) |
|
// break; |
|
// } |
|
nPos = gNumFavorites; // no alphabetization for now - isn't the order in which they were inserted better anyway? |
|
|
|
int filenameLen = (dot - wfd.cFileName) + 4; |
|
urlFile = new char[pathLen + filenameLen + 1]; |
|
strcpy(urlFile, strPath); |
|
strcat(urlFile, wfd.cFileName); |
|
|
|
gFavoritesFiles.InsertAt(nPos, urlFile); |
|
|
|
// format for display in the menu |
|
// chop off the .url |
|
*dot = 0; |
|
// condense the string and escape ampersands |
|
char *pszTemp = fixString(wfd.cFileName, 40); |
|
|
|
gFavorites.InsertAt(nPos, pszTemp); |
|
AppendMenu(mainMenu, MF_STRING | MF_ENABLED, nFirstFavoriteCommand + nPos, pszTemp); |
|
delete pszTemp; |
|
|
|
/* |
|
HACK HACK HACK |
|
We append the filename to gFavoritesPath, get the icon, then chop the file off again |
|
this is a really lame way of doing this... |
|
*/ |
|
strcpy(gFavoritesPath + gFavoritesPathLen, urlFile); |
|
// Retrieve icon |
|
SHFILEINFO sfi; |
|
if (SHGetFileInfo (gFavoritesPath, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_SYSICONINDEX) && sfi.iIcon >= 0) { |
|
gIcons.InsertAt(nPos, sfi.iIcon); |
|
|
|
if (gInternetShortcutIcon == -1) { |
|
gInternetShortcutIcon = sfi.iIcon; |
|
} |
|
}else{ |
|
gIcons.InsertAt(nPos, 0); |
|
} |
|
gFavoritesPath[gFavoritesPathLen] = 0; |
|
|
|
delete [] urlFile; |
|
|
|
gNumFavorites++; |
|
if (gNumFavorites >= MAX_FAVORITES) { |
|
tooMany = true; |
|
break; |
|
} |
|
} |
|
} |
|
} while(FindNextFile(h, &wfd)); |
|
|
|
FindClose(h); |
|
|
|
if (tooMany) MessageBox(NULL, ERROR_TOO_MANY_FAVORITES, PLUGIN_NAME, 0); |
|
|
|
return gNumFavorites - nStart; |
|
} |
|
|
|
char *GetURL(int index){ |
|
// this is static so that we can return it |
|
static char url[INTERNET_MAX_URL_LENGTH]; |
|
|
|
char path[MAX_PATH]; |
|
strcpy(path, gFavoritesPath); |
|
strcpy(path+gFavoritesPathLen, gFavoritesFiles.GetAt(index)); |
|
|
|
// a .URL file is formatted just like an .INI file, so we can |
|
// use GetPrivateProfileString() to get the information we want |
|
GetPrivateProfileString(_T("InternetShortcut"), _T("URL"), _T(""), url, INTERNET_MAX_URL_LENGTH, path); |
|
|
|
return url; |
|
} |
|
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ |
|
// store these in static vars so that the BeginHotTrack call can access them |
|
static NMTOOLBAR tbhdr; |
|
static NMHDR hdr; |
|
|
|
if (message == WM_COMMAND){ |
|
WORD command = LOWORD(wParam); |
|
if (command == nConfigCommand){ |
|
Config(hWnd); |
|
return true; |
|
} |
|
if (command == nAddCommand){ |
|
kmeleonDocInfo *dInfo = kPlugin.kFuncs->GetDocInfo(hWnd); |
|
|
|
// remove any characters the filesystem won't like |
|
char *c; |
|
while ((c = strpbrk(dInfo->title, "\\/:*?\"<>|")) != NULL) *c = ' '; |
|
|
|
CString filename = dInfo->title; |
|
filename += _T(".url"); |
|
gFavoritesFiles.Add(filename); |
|
filename = gFavoritesPath + filename; |
|
::WritePrivateProfileString(_T("InternetShortcut"), _T("URL"), dInfo->url, filename); |
|
|
|
int nPos = gFavorites.GetSize(); |
|
|
|
char *pszTemp = fixString(dInfo->title, 40); |
|
AppendMenu(gFavoritesMenu, MF_STRING, nFirstFavoriteCommand+nPos, pszTemp); |
|
gFavorites.Add(pszTemp); |
|
gIcons.Add(0); |
|
delete pszTemp; |
|
|
|
DrawMenuBar(hWnd); |
|
|
|
return true; |
|
} |
|
if (command == nEditCommand){ |
|
ShellExecute(hWnd, "explore", gFavoritesPath, NULL, gFavoritesPath, SW_SHOWNORMAL); |
|
return true; |
|
} |
|
if (command >= nFirstFavoriteCommand && command < (nFirstFavoriteCommand + MAX_FAVORITES)){ |
|
kPlugin.kFuncs->NavigateTo(GetURL(command-nFirstFavoriteCommand), OPEN_NORMAL, NULL); |
|
return true; |
|
} |
|
} |
|
else if (message == WM_MENUSELECT) { |
|
WORD command = LOWORD(wParam); |
|
if (command >= nFirstFavoriteCommand && command < (nFirstFavoriteCommand + MAX_FAVORITES)){ |
|
kPlugin.kFuncs->SetStatusBarText(GetURL(command-nFirstFavoriteCommand)); |
|
return true; |
|
} |
|
} |
|
else if (message == WM_NOTIFY) { |
|
hdr = *((LPNMHDR)lParam); |
|
if (hdr.code == TBN_DROPDOWN) { |
|
tbhdr = *((LPNMTOOLBAR)lParam); |
|
if (IsMenu((HMENU)(tbhdr.iItem-SUBMENU_OFFSET))){ |
|
char toolbarName[11]; |
|
GetWindowText(tbhdr.hdr.hwndFrom, toolbarName, 10); |
|
if (strcmp(toolbarName, TOOLBAND_LABEL) != 0) { |
|
// oops, this isn't our toolbar |
|
return CallWindowProc(KMeleonWndProc, hWnd, message, wParam, lParam); |
|
} |
|
|
|
// post a message to defer exceution of BeginHotTrack |
|
PostMessage(hWnd, WM_DEFERHOTTRACK, NULL, NULL); |
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam); |
|
} |
|
} |
|
} |
|
else if (message == WM_DEFERHOTTRACK) { |
|
BeginHotTrack(&tbhdr, kPlugin.hDllInstance, hWnd); |
|
return true; |
|
} |
|
|
|
return CallWindowProc(KMeleonWndProc, hWnd, message, wParam, lParam); |
|
} |
|
|
|
// Preferences Dialog function |
|
BOOL CALLBACK DlgProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { |
|
|
|
switch (uMsg) { |
|
case WM_INITDIALOG: |
|
SendDlgItemMessage(hWnd, IDC_REBARENABLED, BM_SETCHECK, bRebarEnabled, 0); |
|
break; |
|
case WM_COMMAND: |
|
switch(HIWORD(wParam)) { |
|
case BN_CLICKED: |
|
switch (LOWORD(wParam)) { |
|
case IDOK: |
|
bRebarEnabled = SendDlgItemMessage(hWnd, IDC_REBARENABLED, BM_GETCHECK, 0, 0); |
|
kPlugin.kFuncs->SetPreference(PREF_BOOL, _T("kmeleon.plugins.favorites.rebar"), &bRebarEnabled, FALSE); |
|
case IDCANCEL: |
|
SendMessage(hWnd, WM_CLOSE, 0, 0); |
|
} |
|
} |
|
break; |
|
case WM_CLOSE: |
|
EndDialog(hWnd, NULL); |
|
break; |
|
default: |
|
return FALSE; |
|
} |
|
return TRUE; |
|
} |
|
|
|
// so it doesn't munge the function name |
|
extern "C" { |
|
|
|
KMELEON_PLUGIN kmeleonPlugin *GetKmeleonPlugin() { |
|
return &kPlugin; |
|
} |
|
|
|
KMELEON_PLUGIN int DrawBitmap(DRAWITEMSTRUCT *dis) { |
|
int top = (dis->rcItem.bottom - dis->rcItem.top - 16) / 2; |
|
top += dis->rcItem.top; |
|
|
|
if (GetMenuState((HMENU)dis->hwndItem, dis->itemID, MF_BYCOMMAND) & MF_POPUP){ |
|
if (dis->itemState & ODS_SELECTED){ |
|
ImageList_Draw(gSystemImages, gFolderIcon, dis->hDC, dis->rcItem.left, top, ILD_TRANSPARENT | ILD_FOCUS ); |
|
}else{ |
|
ImageList_Draw(gSystemImages, gFolderIcon, dis->hDC, dis->rcItem.left, top, ILD_TRANSPARENT); |
|
} |
|
return 18; |
|
} |
|
if (dis->itemID >= nFirstFavoriteCommand && dis->itemID < (nFirstFavoriteCommand + MAX_FAVORITES)){ |
|
if (dis->itemState & ODS_SELECTED){ |
|
ImageList_Draw(gSystemImages, gIcons[dis->itemID - nFirstFavoriteCommand], dis->hDC, dis->rcItem.left, top, ILD_TRANSPARENT | ILD_FOCUS); |
|
}else{ |
|
ImageList_Draw(gSystemImages, gIcons[dis->itemID - nFirstFavoriteCommand], dis->hDC, dis->rcItem.left, top, ILD_TRANSPARENT); |
|
} |
|
|
|
return 18; |
|
} |
|
return 0; |
|
} |
|
} |
|
|
|
|
|
/* |
|
|
|
From: "Nathan Fredrickson" <8nrf@qlink.queensu.ca> |
|
To: <kmeleon-dev@lists.sourceforge.net> |
|
Subject: [Kmeleon-dev] favorites plugin |
|
Date: Fri, 2 Nov 2001 11:17:40 -0500 |
|
|
|
Hello, |
|
|
|
I like how favorites can be shared between IE and Kmeleon, but I miss the |
|
ability to custom order my favorites in IE. While I would ideally like to |
|
re-order favorites in Kmeleon, a good first step would be just using the IE |
|
ordering when displaying the favorites. |
|
|
|
I have done some investigating of how IE stores the menu order of favorites. |
|
The favorites directory and each subdirectory has a corresponding key in the |
|
registry: |
|
|
|
HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MenuOrder\\Favorites |
|
|
|
HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MenuOrder\\Favorites\\subdir |
|
|
|
These keys contain a binary value named "Order". If the key does not exist |
|
for a specified directory, alphabetical order should be used. I have not |
|
found the format of the binary data specified anywhere, so this is what I |
|
have discovered so far: |
|
|
|
Order = { |
|
4 0x08 0x00 0x00 0x00 |
|
4 0x02 0x00 0x00 0x00 |
|
4 (total size of data) - (first 8 bytes) - (last byte) |
|
4 0x01 0x00 0x00 0x00 |
|
4 N (number of records) |
|
record 1 |
|
record 2 |
|
... |
|
record N |
|
1 terminating byte 0x00 |
|
} |
|
|
|
record = { |
|
4 size of record in bytes |
|
4 position of item in menu |
|
range: [0, recordcount-1] or negative if no order is defined |
|
14 unknown ??? |
|
X null-terminated string of full filename: "Yahoo!.url" |
|
X null-terminated string of 8.3 filename: "YAHOO!.URL__" |
|
6 unknown ??? |
|
} |
|
|
|
The above is enough info to extract the positions and the filenames (I have |
|
written bits of code to do that while experimenting). If I have time, I may |
|
try to add this to the favorites plugin. Not sure what is the best approach |
|
to correlate this data with the URL files read from the directory... |
|
|
|
*/ |
|
|
|
/* |
|
|
|
Brian's Notes: |
|
|
|
Implementation: |
|
Build a list of menu items in order from the registry keys (ordered favorites) |
|
Build a list of menu items in alphabetical order from the directories (actual favorites) |
|
|
|
Loop through ordered favorites. |
|
If the ordered favorite is in actual favorites |
|
Remove it from actual favorites |
|
Add it to merged favorites |
|
If the ordered favorite is not found in actual favorites |
|
Remove it from ordered favorites |
|
Append all remaining actual favorites to merged favorites |
|
|
|
We should store the favorites lists as a linked tree list thing (like the bookmarks) |
|
|
|
*/
|
|
|