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.
1770 lines
67 KiB
1770 lines
67 KiB
/* |
|
* Copyright (C) 2003 Ulf Erikson <ulferikson@fastmail.fm> |
|
* |
|
* 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. |
|
*/ |
|
|
|
#ifdef __MINGW32__ |
|
# define _WIN32_IE 0x0500 |
|
# include <windows.h> |
|
# include <commctrl.h> |
|
# include "../missing.h" |
|
#endif |
|
|
|
#include "op_hotlist.h" |
|
#include "kmeleon_plugin.h" |
|
#include "../rebar_menu/hot_tracking.h" |
|
#include "../../app/KMeleonConst.h" |
|
#include "LocalesUtils.h" |
|
extern Locale* gLoc; |
|
#include "Utils.h" |
|
|
|
#define VK_OEM_MINUS 0xBD |
|
#define VK_OEM_PERIOD 0xBE |
|
#define VK_MINUS VK_OEM_MINUS |
|
#define VK_PERIOD VK_OEM_PERIOD |
|
|
|
extern kmeleonPlugin kPlugin; |
|
extern void * KMeleonWndProc; |
|
|
|
static CBookmarkNode workingBookmarks; |
|
static CBookmarkNode *freeNode, *freeParentNode; |
|
static BOOL bookmarksEdited; |
|
static HWND hEditWnd; |
|
static BOOL bDragging; |
|
static BOOL bTracking; |
|
static HCURSOR hCursorDrag; |
|
|
|
#define SEARCH_LEN 256 |
|
static char str[SEARCH_LEN]; |
|
static int len; |
|
static int pos; |
|
static int circling; |
|
|
|
static HTREEITEM hTBitem; // current toolbar folder treeview item |
|
static HTREEITEM hNBitem; // current new bookmark folder treeview item |
|
static HTREEITEM hBMitem; // current bookmark menu folder treeview item |
|
static BOOL zoom; |
|
static BOOL maximized; |
|
|
|
#define CUT 1 |
|
#define KILL 1 |
|
#define PASTE 1 |
|
|
|
static void FillTree(HWND hTree, HTREEITEM parent, CBookmarkNode &node); |
|
static void CreateNewObject(HWND hTree, HTREEITEM fromItem, int type, int mode=0); |
|
static void DeleteItem(HWND hTree, HTREEITEM item, int mode=0); |
|
static void CopyItem(HWND hTree, HTREEITEM item); |
|
static void OnSize(int height, int width); |
|
static void OnRClick(HWND hTree); |
|
static void MoveItem(HWND hTree, HTREEITEM item, int mode); |
|
|
|
|
|
static inline CBookmarkNode *GetBookmarkNode(HWND hTree, HTREEITEM htItem) { |
|
TVITEMEX tvItem; |
|
tvItem.mask = TVIF_PARAM; |
|
tvItem.hItem = htItem; |
|
TreeView_GetItem(hTree, &tvItem); |
|
|
|
return (CBookmarkNode *)tvItem.lParam; |
|
} |
|
|
|
static inline void UnixTimeToSystemTime(time_t t, LPSYSTEMTIME pst) { |
|
// Note that LONGLONG is a 64-bit value |
|
LONGLONG ll; |
|
FILETIME ft1; |
|
FILETIME ft2; |
|
|
|
#ifdef __MINGW32__ |
|
ll = Int32x32To64(t, 10000000) + 116444736000000000LL; |
|
#else |
|
ll = Int32x32To64(t, 10000000) + 116444736000000000; |
|
#endif |
|
ft1.dwLowDateTime = (DWORD)ll; |
|
ft1.dwHighDateTime = ll >> 32; |
|
|
|
FileTimeToLocalFileTime(&ft1, &ft2); |
|
FileTimeToSystemTime(&ft2, pst); |
|
} |
|
|
|
|
|
// Hook function for keyboard hook |
|
// I have to use the hook to capture SHIFT-UP, SHIFT-DOWN, ENTER and other "system"-type keypresses |
|
// And to keep things consistent, I just threw all keypress handling in here |
|
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { |
|
if ( (nCode != HC_ACTION) || (lParam & 0x80000000) ) { // highest bit of lParam high == key being released |
|
return CallNextHookEx(NULL, nCode, wParam, lParam); |
|
} |
|
|
|
BOOL fEatKeystroke = false; |
|
BOOL fakedKey = false; |
|
HWND hasFocus = GetFocus(); |
|
HWND hTree = GetDlgItem(hEditWnd, IDC_TREE_HOTLIST); |
|
|
|
if (!(hasFocus == hTree || |
|
hasFocus == GetDlgItem(hEditWnd, IDC_NAME) || |
|
hasFocus == GetDlgItem(hEditWnd, IDC_URL) || |
|
hasFocus == GetDlgItem(hEditWnd, IDC_ORDER) || |
|
hasFocus == GetDlgItem(hEditWnd, IDC_DESCRIPTION) || |
|
hasFocus == GetDlgItem(hEditWnd, IDC_SHORT_NAME) || |
|
hasFocus == GetDlgItem(hEditWnd, IDOK) || |
|
hasFocus == GetDlgItem(hEditWnd, IDCANCEL))) |
|
return CallNextHookEx(NULL, nCode, wParam, lParam); |
|
|
|
int searching = 0; |
|
|
|
if (wParam == VK_ESCAPE && !bTracking) { |
|
fEatKeystroke = true; |
|
if (len == 0) |
|
SendMessage(GetDlgItem(hEditWnd, IDCANCEL), BM_CLICK, 0, 0); |
|
else |
|
len = 0; |
|
} |
|
else if (hasFocus == hTree) { |
|
HTREEITEM hItem = TreeView_GetSelection(hTree); |
|
if (hItem) { |
|
switch (wParam) { |
|
case VK_UP: |
|
if (GetKeyState(VK_SHIFT) & 0x80) { |
|
fEatKeystroke = true; |
|
MoveItem(hTree, hItem, 1); |
|
} |
|
else if (GetKeyState(VK_MENU) & 0x80) { // what genius decided to call ALT "VK_MENU"??? |
|
fEatKeystroke = true; |
|
HTREEITEM hItemSelect = TreeView_GetPrevSibling(hTree, hItem); |
|
if (!hItemSelect) hItemSelect = TreeView_GetPrevVisible(hTree, hItem); |
|
if (!hItemSelect) break; |
|
TreeView_SelectItem(hTree, hItemSelect); |
|
} |
|
break; |
|
case VK_DOWN: |
|
if (GetKeyState(VK_SHIFT) & 0x80) { |
|
fEatKeystroke = true; |
|
MoveItem(hTree, hItem, 2); |
|
} |
|
else if (GetKeyState(VK_MENU) & 0x80) { |
|
fEatKeystroke = true; |
|
HTREEITEM hItemSelect = TreeView_GetNextSibling(hTree, hItem); |
|
if (!hItemSelect) hItemSelect = TreeView_GetNextSibling(hTree, TreeView_GetParent(hTree, hItem)); |
|
if (!hItemSelect) hItemSelect = TreeView_GetNextVisible(hTree, hItem); |
|
if (!hItemSelect) break; |
|
TreeView_SelectItem(hTree, hItemSelect); |
|
} |
|
break; |
|
case VK_RETURN: |
|
{ |
|
fEatKeystroke = true; |
|
CBookmarkNode *node = GetBookmarkNode(hTree, hItem); |
|
if (node->type == BOOKMARK_BOOKMARK) { |
|
node->lastVisit = time(NULL); |
|
bookmarksEdited = true; |
|
if (GetKeyState(VK_CONTROL) & 0x80) { |
|
kPlugin.kFuncs->NavigateTo(node->url.c_str(), OPEN_BACKGROUND, NULL); |
|
TreeView_SelectItem(hTree, hItem); // just to fire off a SELCHANGED notifier to update the status (last visited!) |
|
} |
|
else { |
|
kPlugin.kFuncs->NavigateTo(node->url.c_str(), OPEN_NORMAL, NULL); |
|
TreeView_SelectItem(hTree, hItem); // just to fire off a SELCHANGED notifier to update the status (last visited!) |
|
PostMessage(hWndFront, WM_COMMAND, wm_deferbringtotop, (LPARAM)NULL); |
|
} |
|
} |
|
else if (node->type == BOOKMARK_FOLDER) { |
|
TreeView_Expand(hTree, hItem, TVE_TOGGLE); |
|
} |
|
} |
|
break; |
|
case VK_TAB: |
|
{ |
|
if (len > 0) { |
|
wParam = str[len-1]; |
|
wParam = toupper(wParam); |
|
if (wParam == '-') wParam = VK_MINUS; |
|
if (wParam == '.') wParam = VK_PERIOD; |
|
fakedKey = true; |
|
goto search_again; |
|
} |
|
int idc_next = IDC_NAME; |
|
fEatKeystroke = true; |
|
if (zoom) |
|
break; |
|
if (GetKeyState(VK_SHIFT) & 0x80) { |
|
idc_next = IDCANCEL; |
|
SendMessage(GetDlgItem(hEditWnd, idc_next), BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); |
|
} |
|
else if (!IsWindowEnabled(GetDlgItem(hEditWnd, IDC_NAME))) { |
|
idc_next = IDOK; |
|
SendMessage(GetDlgItem(hEditWnd, idc_next), BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); |
|
} |
|
SetFocus(GetDlgItem(hEditWnd, idc_next)); |
|
if (idc_next == IDC_NAME) |
|
SendDlgItemMessage(hEditWnd, idc_next, EM_SETSEL, 0, -1); // select all |
|
} |
|
break; |
|
case VK_DELETE: |
|
fEatKeystroke = true; |
|
if (GetKeyState(VK_SHIFT) & 0x80) { |
|
// Shift delete == Cut |
|
DeleteItem(hTree, hItem, CUT); |
|
} else if (GetKeyState(VK_CONTROL) & 0x80) { |
|
// Ctrl delete == Kill |
|
DeleteItem(hTree, hItem, KILL); |
|
} else { |
|
// Delete == Kill |
|
DeleteItem(hTree, hItem); |
|
} |
|
break; |
|
case VK_INSERT: |
|
fEatKeystroke = true; |
|
if (GetKeyState(VK_SHIFT) & 0x80) { |
|
// Shift insert == Paste |
|
if (freeNode) |
|
CreateNewObject(hTree, hItem, freeNode->type, PASTE); |
|
} else if (GetKeyState(VK_CONTROL) & 0x80) { |
|
// Ctrl insert == Copy |
|
CopyItem(hTree, hItem); |
|
} else { |
|
CBookmarkNode *node = GetBookmarkNode(hTree, hItem); |
|
if (node) |
|
CreateNewObject(hTree, hItem, node->type); |
|
else |
|
CreateNewObject(hTree, hItem, BOOKMARK_FOLDER); |
|
if (!zoom) { |
|
SetFocus(GetDlgItem(hEditWnd, IDC_NAME)); |
|
SendDlgItemMessage(hEditWnd, IDC_NAME, EM_SETSEL, 0, -1); |
|
} |
|
} |
|
break; |
|
case ' ': |
|
{ |
|
CBookmarkNode *node = GetBookmarkNode(hTree, hItem); |
|
if (node->type == BOOKMARK_FOLDER && len == 0) { |
|
fEatKeystroke = true; |
|
TreeView_Expand(hTree, hItem, TVE_TOGGLE); |
|
break; |
|
} |
|
} |
|
// Fall through! |
|
default: |
|
{ |
|
if (GetKeyState(VK_CONTROL) & 0x80) { |
|
switch (wParam) { |
|
case 'X': |
|
// Ctrl X == Cut |
|
DeleteItem(hTree, hItem, CUT); |
|
fEatKeystroke = true; |
|
break; |
|
case 'C': |
|
// Ctrl C == Copy |
|
CopyItem(hTree, hItem); |
|
fEatKeystroke = true; |
|
break; |
|
case 'V': |
|
// Ctrl V == Paste |
|
if (freeNode) |
|
CreateNewObject(hTree, hItem, freeNode->type, PASTE); |
|
fEatKeystroke = true; |
|
break; |
|
case 'G': |
|
if (len > 0) { |
|
wParam = str[len-1]; |
|
wParam = toupper(wParam); |
|
if (wParam == '-') wParam = VK_MINUS; |
|
if (wParam == '.') wParam = VK_PERIOD; |
|
fakedKey = true; |
|
goto search_again; |
|
} |
|
break; |
|
} |
|
break; |
|
} |
|
else if (GetKeyState(VK_MENU) & 0x80) { |
|
break; |
|
} |
|
else { |
|
switch (wParam) { |
|
case VK_F3: |
|
if (len > 0) { |
|
wParam = str[len-1]; |
|
wParam = toupper(wParam); |
|
if (wParam == '-') wParam = VK_MINUS; |
|
if (wParam == '.') wParam = VK_PERIOD; |
|
fakedKey = true; |
|
goto search_again; |
|
} |
|
break; |
|
} |
|
} |
|
|
|
if (wParam == VK_BACK && len > 0) { |
|
circling = 0; |
|
len--; |
|
} |
|
else if ( (wParam == ' ' || |
|
(wParam >= '0' && wParam <= '9') || |
|
(wParam >= 'A' && wParam <= 'Z')) && |
|
len < (SEARCH_LEN-1) ) { |
|
str[len] = tolower(wParam); |
|
len++; |
|
} |
|
else if ( (wParam == VK_MINUS) && |
|
len < (SEARCH_LEN-1) ) { |
|
str[len] = '-'; |
|
len++; |
|
} |
|
else if ( wParam == VK_PERIOD && |
|
len < (SEARCH_LEN-1) ) { |
|
str[len] = '.'; |
|
len++; |
|
} |
|
else |
|
break; |
|
|
|
search_again: |
|
fEatKeystroke = true; |
|
searching = 1; |
|
str[len] = 0; |
|
if (len > 0) { |
|
CBookmarkNode *node; |
|
|
|
int mypos = 0; |
|
int firstpos = -1; |
|
int searchfrom = pos; |
|
|
|
if (len == 1 && !fakedKey) { |
|
HTREEITEM hItem = TreeView_GetSelection(hTree); |
|
node = GetBookmarkNode(hTree, hItem); |
|
if (workingBookmarks.Index(searchfrom, node) == -1) |
|
searchfrom = pos; |
|
else |
|
pos = searchfrom; |
|
} |
|
|
|
int newpos = workingBookmarks.Search(str, searchfrom, mypos, firstpos, &node); |
|
|
|
if (fakedKey || newpos == -1 || |
|
(circling && len > 1 && str[len-1] == str[len-2])) { |
|
if (fakedKey || (len > 1 && str[len-1] == str[len-2])) |
|
searchfrom++; |
|
if (!fakedKey) |
|
len--; |
|
str[len] = 0; |
|
mypos = 0; |
|
firstpos = -1; |
|
if (len > 0) { |
|
newpos = workingBookmarks.Search(str, searchfrom, mypos, firstpos, &node); |
|
if (!fakedKey && (newpos == pos || (len > 1 && str[len-1] == str[len-2]))) { |
|
circling = 1; |
|
while (len > 1 && str[len-1] == str[len-2]) |
|
len--; |
|
str[len] = 0; |
|
mypos = 0; |
|
firstpos = -1; |
|
newpos = workingBookmarks.Search(str, searchfrom, mypos, firstpos, &node); |
|
} |
|
} |
|
} |
|
else |
|
circling = 0; |
|
|
|
if (newpos == -1 || len == 0) { |
|
pos = 0; |
|
len = 0; |
|
str[len] = 0; |
|
searching = 0; |
|
} |
|
else { |
|
SetWindowText( hEditWnd, gLoc->GetStringFormat(IDS_FIND, str) ); |
|
|
|
HTREEITEM hItem = TreeView_GetRoot(hTree); |
|
int i = 0; |
|
while (hItem && i < newpos) { |
|
HTREEITEM hTmp = TreeView_GetChild(hTree, hItem); |
|
if (!hTmp) |
|
hTmp = TreeView_GetNextSibling(hTree, hItem); |
|
if (!hTmp) { |
|
HTREEITEM hTmp2 = TreeView_GetParent(hTree, hItem); |
|
while (!hTmp && hTmp2) { |
|
hTmp = TreeView_GetNextSibling(hTree, hTmp2); |
|
hTmp2 = TreeView_GetParent(hTree, hTmp2); |
|
} |
|
} |
|
hItem = hTmp; |
|
i++; |
|
} |
|
|
|
if (hItem) { |
|
TreeView_SelectItem(hTree, hItem); |
|
TreeView_EnsureVisible(hTree, hItem); |
|
} |
|
|
|
pos = newpos; |
|
} |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
else if (hasFocus == GetDlgItem(hEditWnd, IDC_NAME) && wParam == VK_RETURN) { |
|
fEatKeystroke = true; |
|
if (IsWindowEnabled(GetDlgItem(hEditWnd, IDC_URL))) { |
|
SetFocus(GetDlgItem(hEditWnd, IDC_URL)); |
|
SendDlgItemMessage(hEditWnd, IDC_URL, EM_SETSEL, 0, -1); // select all |
|
} |
|
else { |
|
SetFocus(GetDlgItem(hEditWnd, IDC_TREE_HOTLIST)); |
|
} |
|
} |
|
else if (hasFocus == GetDlgItem(hEditWnd, IDOK) && wParam == VK_RETURN) { |
|
SendMessage(GetDlgItem(hEditWnd, IDOK), BM_CLICK, 0, 0); |
|
} |
|
else if (hasFocus == GetDlgItem(hEditWnd, IDCANCEL) && wParam == VK_RETURN) { |
|
SendMessage(GetDlgItem(hEditWnd, IDCANCEL), BM_CLICK, 0, 0); |
|
} |
|
else if ((hasFocus == GetDlgItem(hEditWnd, IDC_URL) || |
|
hasFocus == GetDlgItem(hEditWnd, IDC_ORDER) || |
|
hasFocus == GetDlgItem(hEditWnd, IDC_DESCRIPTION) || |
|
hasFocus == GetDlgItem(hEditWnd, IDC_SHORT_NAME)) && |
|
wParam == VK_RETURN) { |
|
fEatKeystroke = true; |
|
SetFocus(GetDlgItem(hEditWnd, IDC_TREE_HOTLIST)); |
|
} |
|
else if (wParam == VK_TAB) { |
|
int fields[] = {IDC_TREE_HOTLIST, IDC_NAME, IDC_URL, |
|
IDC_ORDER, IDC_DESCRIPTION, IDC_SHORT_NAME, |
|
IDOK, IDCANCEL, IDC_TREE_HOTLIST}; |
|
for (int i=1; fields[i]!=IDC_TREE_HOTLIST; i++) { |
|
if (GetDlgItem(hEditWnd, fields[i]) == hasFocus) { |
|
int idc_next = fields[i + ((GetKeyState(VK_SHIFT) & 0x80) ? -1 : 1)]; |
|
if (idc_next == IDC_TREE_HOTLIST || |
|
idc_next == IDOK || idc_next == IDCANCEL || |
|
IsWindowEnabled(GetDlgItem(hEditWnd, idc_next))) { |
|
fEatKeystroke = true; |
|
if (fields[i] == IDOK || fields[i] == IDCANCEL) |
|
SendMessage(hasFocus, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); |
|
if (idc_next == IDOK || idc_next == IDCANCEL) |
|
SendMessage(GetDlgItem(hEditWnd, idc_next), BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); |
|
SetFocus(GetDlgItem(hEditWnd, idc_next)); |
|
if (idc_next != IDC_TREE_HOTLIST && |
|
idc_next != IDOK && idc_next != IDCANCEL) |
|
SendDlgItemMessage(hEditWnd, idc_next, EM_SETSEL, 0, -1); // select all |
|
break; |
|
} |
|
else { |
|
hasFocus = GetDlgItem(hEditWnd, idc_next); |
|
i = 0; |
|
continue; |
|
} |
|
} |
|
} |
|
} |
|
|
|
if ((searching == 0 || len==0) && |
|
wParam != VK_SHIFT && wParam != VK_MENU && wParam != VK_CONTROL) { |
|
len = 0; |
|
pos = 0; |
|
str[len] = 0; |
|
SetWindowText( hEditWnd, "Hotlist" ); |
|
circling = 0; |
|
} |
|
|
|
return(fEatKeystroke ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam)); |
|
} |
|
|
|
|
|
int CALLBACK EditProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
static HHOOK hHook; |
|
static HWND hTree; |
|
static bool bTimer = false; // semi-crude hack to make scrolling smoother |
|
static HTREEITEM htCurHover = NULL; |
|
static HTREEITEM htDummyItem = NULL; |
|
|
|
switch (uMsg){ |
|
case WM_INITDIALOG: |
|
{ |
|
if (gHotlistModified) |
|
op_writeFile(lpszHotlistFile); |
|
|
|
hEditWnd = hDlg; |
|
len = 0; |
|
str[len] = 0; |
|
pos = 0; |
|
circling = 0; |
|
|
|
HICON hIcon; |
|
wchar_t szFullPath[MAX_PATH]; |
|
kPlugin.kFuncs->FindSkinFile(L"hotlist-edit.ico", szFullPath, MAX_PATH); |
|
|
|
if (*szFullPath==0 || (hIcon = (HICON)LoadImageW( NULL, szFullPath, IMAGE_ICON, 0,0, LR_DEFAULTSIZE | LR_LOADFROMFILE ))==NULL) |
|
hIcon = (HICON)LoadImage( kPlugin.hDllInstance, MAKEINTRESOURCE(IDB_ICON), IMAGE_ICON, 0,0, LR_DEFAULTSIZE ); |
|
if (hIcon) |
|
SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon); |
|
|
|
if (*szFullPath==0 || (hIcon = (HICON)LoadImageW( NULL, szFullPath, IMAGE_ICON, 16,16, LR_LOADFROMFILE ))==NULL) |
|
hIcon = (HICON)LoadImage( kPlugin.hDllInstance, MAKEINTRESOURCE(IDB_ICON), IMAGE_ICON, 16,16, 0 ); |
|
if (hIcon) |
|
SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon); |
|
|
|
hTree = GetDlgItem(hDlg, IDC_TREE_HOTLIST); |
|
TreeView_SetImageList(hTree, gImagelist, TVSIL_NORMAL); |
|
|
|
workingBookmarks = gHotlistRoot; |
|
bookmarksEdited = false; |
|
|
|
CResString all = gLoc->GetString(IDS_ALL_BOOKMARKS); |
|
TVINSERTSTRUCT tvis; |
|
tvis.hParent = NULL; |
|
tvis.hInsertAfter = NULL; |
|
tvis.itemex.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; |
|
tvis.itemex.iImage = IMAGE_FOLDER_SPECIAL_CLOSED; |
|
tvis.itemex.iSelectedImage = IMAGE_FOLDER_SPECIAL_OPEN; |
|
tvis.itemex.pszText = (char*)(const char*)all; |
|
tvis.itemex.lParam = (long)&workingBookmarks; |
|
|
|
HTREEITEM newItem = TreeView_InsertItem(hTree, &tvis); |
|
|
|
// root starts out with all specials set to it - FillTree will unset any that are set elsewhere with ChangeSpecialFolders |
|
hTBitem = hNBitem = hBMitem = newItem; |
|
workingBookmarks.flags = BOOKMARK_FLAG_TB | BOOKMARK_FLAG_BM | BOOKMARK_FLAG_NB; |
|
|
|
FillTree(hTree, newItem, workingBookmarks); |
|
|
|
TreeView_Expand(hTree, newItem, TVE_EXPAND); |
|
|
|
int dialogleft = 50, dialogtop = 50, dialogwidth = 500, dialogheight = 500; |
|
kPlugin.kFuncs->GetPreference(PREF_INT, PREFERENCE_EDIT_DLG_LEFT, &dialogleft, &dialogleft); |
|
kPlugin.kFuncs->GetPreference(PREF_INT, PREFERENCE_EDIT_DLG_TOP, &dialogtop, &dialogtop); |
|
kPlugin.kFuncs->GetPreference(PREF_INT, PREFERENCE_EDIT_DLG_WIDTH, &dialogwidth, &dialogwidth); |
|
kPlugin.kFuncs->GetPreference(PREF_INT, PREFERENCE_EDIT_DLG_HEIGHT, &dialogheight, &dialogheight); |
|
kPlugin.kFuncs->GetPreference(PREF_BOOL, PREFERENCE_EDIT_ZOOM, &zoom, &zoom); |
|
kPlugin.kFuncs->GetPreference(PREF_BOOL, PREFERENCE_EDIT_MAX, &maximized, &maximized); |
|
SetWindowPos(hDlg, 0, dialogleft, dialogtop, dialogwidth, dialogheight, 0); |
|
if (maximized) |
|
ShowWindow(hDlg, SW_MAXIMIZE); |
|
else |
|
ShowWindow(hDlg, SW_NORMAL); |
|
|
|
hCursorDrag = LoadCursor(kPlugin.hDllInstance, MAKEINTRESOURCE(IDC_DRAG_CURSOR)); |
|
bDragging = false; |
|
|
|
hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, GetCurrentThreadId()); |
|
} |
|
return false; |
|
|
|
case WM_NOTIFY: |
|
{ |
|
NMTREEVIEW *nmtv = (NMTREEVIEW *)lParam; |
|
|
|
// Selection changed |
|
if (nmtv->hdr.code == (UINT) TVN_SELCHANGED){ |
|
// Put the new url/title into the box |
|
CBookmarkNode *newNode = (CBookmarkNode *)nmtv->itemNew.lParam; |
|
|
|
if (newNode == &workingBookmarks) { |
|
// root and separators have nothing |
|
SetDlgItemText(hDlg, IDC_NAME, ""); |
|
SetDlgItemText(hDlg, IDC_URL, ""); |
|
SetDlgItemText(hDlg, IDC_CREATED, ""); |
|
SetDlgItemText(hDlg, IDC_LAST_VISIT, ""); |
|
SetDlgItemText(hDlg, IDC_ORDER, ""); |
|
SetDlgItemText(hDlg, IDC_DESCRIPTION, ""); |
|
SetDlgItemText(hDlg, IDC_SHORT_NAME, ""); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_NAME), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_NAME), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_URL), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_URL), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CREATED), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_VISITED), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_ORDER), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_ORDER), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DESC), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_DESCRIPTION), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_SHORT), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_SHORT_NAME), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_PROPERTIES), false); |
|
return true; // a lazy-man's "else" |
|
} |
|
|
|
// everything else has at least title, added date, and properties in general |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_PROPERTIES), true); |
|
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_NAME), true); |
|
EnableWindow(GetDlgItem(hDlg, IDC_NAME), true); |
|
SetDlgItemText(hDlg, IDC_NAME, newNode->text.c_str()); |
|
|
|
SYSTEMTIME st; |
|
char pszTmp[1024]; |
|
char pszDate[900]; |
|
|
|
if (newNode->type == BOOKMARK_BOOKMARK) { |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_URL), true); |
|
EnableWindow(GetDlgItem(hDlg, IDC_URL), true); |
|
SetDlgItemText(hDlg, IDC_URL, newNode->url.c_str()); |
|
} |
|
else { |
|
SetDlgItemText(hDlg, IDC_URL, ""); |
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_URL), false); |
|
EnableWindow(GetDlgItem(hDlg, IDC_URL), false); |
|
} |
|
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CREATED), true); |
|
UnixTimeToSystemTime(newNode->addDate, &st); |
|
GetDateFormat(GetThreadLocale(), DATE_SHORTDATE, &st, NULL, pszDate, 899); |
|
strcpy(pszTmp, pszDate); |
|
strcat(pszTmp, " "); |
|
GetTimeFormat(GetThreadLocale(), (DWORD) NULL, &st, NULL, pszDate, 899); |
|
strcat(pszTmp, pszDate); |
|
SetDlgItemText(hDlg, IDC_CREATED, pszTmp); |
|
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_VISITED), true); |
|
if (newNode->lastVisit) { |
|
UnixTimeToSystemTime(newNode->lastVisit, &st); |
|
GetDateFormat(GetThreadLocale(), DATE_SHORTDATE, &st, NULL, pszDate, 899); |
|
strcpy(pszTmp, pszDate); |
|
strcat(pszTmp, " "); |
|
GetTimeFormat(GetThreadLocale(), (DWORD) NULL, &st, NULL, pszDate, 899); |
|
strcat(pszTmp, pszDate); |
|
SetDlgItemText(hDlg, IDC_LAST_VISIT, pszTmp); |
|
} |
|
else { |
|
SetDlgItemText(hDlg, IDC_LAST_VISIT, gLoc->GetString(IDS_NEVER)); |
|
} |
|
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_ORDER), true); |
|
EnableWindow(GetDlgItem(hDlg, IDC_ORDER), true); |
|
SetDlgItemInt(hDlg, IDC_ORDER, (UINT)newNode->order, true); |
|
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DESC), true); |
|
EnableWindow(GetDlgItem(hDlg, IDC_DESCRIPTION), true); |
|
SetDlgItemText(hDlg, IDC_DESCRIPTION, newNode->desc.c_str()); |
|
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_SHORT), true); |
|
EnableWindow(GetDlgItem(hDlg, IDC_SHORT_NAME), true); |
|
SetDlgItemText(hDlg, IDC_SHORT_NAME, newNode->nick.c_str()); |
|
|
|
} |
|
// start a drag operation |
|
else if (nmtv->hdr.code == (UINT) TVN_BEGINDRAG){ |
|
TreeView_SelectItem(hTree, nmtv->itemNew.hItem); |
|
// don't move the root folder (thus, only move something if it has a parent) |
|
if (TreeView_GetParent(hTree, nmtv->itemNew.hItem)) { |
|
SetCursor(hCursorDrag); |
|
bDragging = true; |
|
SetCapture(hDlg); |
|
} |
|
} |
|
else if (nmtv->hdr.code == (UINT) NM_DBLCLK){ |
|
TVHITTESTINFO hti; |
|
GetCursorPos(&hti.pt); |
|
ScreenToClient(hTree, &hti.pt); |
|
|
|
HTREEITEM hItem = TreeView_HitTest(hTree, &hti); |
|
if (hItem){ |
|
CBookmarkNode *node = GetBookmarkNode(hTree, hItem); |
|
|
|
if (node->type == BOOKMARK_BOOKMARK) { |
|
node->lastVisit = time(NULL); |
|
bookmarksEdited = true; |
|
kPlugin.kFuncs->NavigateTo(node->url.c_str(), OPEN_NORMAL, NULL); |
|
TreeView_SelectItem(hTree, hItem); // just to fire off a SELCHANGED notifier to update the status (last visited!) |
|
PostMessage(hWndFront, WM_COMMAND, wm_deferbringtotop, (LPARAM)NULL); |
|
|
|
return true; |
|
} |
|
} |
|
} |
|
// right click... |
|
else if (nmtv->hdr.code == (UINT) NM_RCLICK){ |
|
OnRClick(hTree); |
|
} |
|
return true; |
|
} |
|
break; |
|
|
|
case WM_TIMER: |
|
{ |
|
// only one-time timers - will reset selves if necessary |
|
KillTimer(hDlg, wParam); |
|
|
|
if (wParam < 2) { |
|
// scrolling, and wParam conveniently holds the direction |
|
bTimer = false; |
|
HWND hTree = GetDlgItem(hDlg, IDC_TREE_HOTLIST); |
|
SendMessage(hTree, WM_VSCROLL, wParam, (LPARAM) NULL); |
|
} |
|
else if (wParam == 2) { |
|
// need to expand folder |
|
HWND hTree = GetDlgItem(hDlg, IDC_TREE_HOTLIST); |
|
|
|
// the folder might be empty, in which case we add an empty dummy item to allow it to expand |
|
if (!TreeView_GetChild(hTree, htCurHover)) { |
|
TVINSERTSTRUCT tvis; |
|
tvis.hParent = htCurHover; |
|
tvis.hInsertAfter = TVI_FIRST; |
|
tvis.itemex.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; |
|
tvis.itemex.iImage = IMAGE_BLANK; |
|
tvis.itemex.iSelectedImage = IMAGE_BLANK; |
|
htDummyItem = TreeView_InsertItem(hTree, &tvis); |
|
} |
|
|
|
TreeView_SetInsertMark(hTree, NULL, false); // clean up insertion mark before expand messes it up |
|
TreeView_Expand(hTree, htCurHover, TVE_EXPAND); |
|
} |
|
} |
|
// no break, because we want to update the insertion mark and set timers again if needed |
|
|
|
case WM_MOUSEMOVE: |
|
// update the insertion mark if we're dragging |
|
if (bDragging){ |
|
HWND hTree = GetDlgItem(hDlg, IDC_TREE_HOTLIST); |
|
|
|
// find current coordinates |
|
TVHITTESTINFO hti; |
|
GetCursorPos(&hti.pt); |
|
ScreenToClient(hTree, &hti.pt); |
|
|
|
RECT tvRect; |
|
|
|
// set timers to scroll, if dragging to top/bottom |
|
GetClientRect(hTree, &tvRect); |
|
if (!bTimer && hti.pt.y >= 0 && hti.pt.y < 25) { |
|
SetTimer(hDlg, |
|
0, // timer id - passed as wParam through WM_TIMER to WM_VSCROLL (thus, 0=up, 1=down) |
|
50, // 0.05-second interval |
|
(TIMERPROC) NULL); // no timer callback |
|
bTimer = true; |
|
} |
|
else if (!bTimer && tvRect.bottom - hti.pt.y >= 0 && tvRect.bottom - hti.pt.y < 25) { |
|
SetTimer(hDlg, 1, 50, (TIMERPROC) NULL); |
|
bTimer = true; |
|
} |
|
|
|
HTREEITEM item = TreeView_HitTest(hTree, &hti); |
|
if (item) { |
|
|
|
if (item != htCurHover) { |
|
// it might be an empty folder, so we unfortunately have to check the node type itself |
|
// we also need to check if it's expanded or not |
|
TVITEMEX tvItem; |
|
tvItem.mask = TVIF_PARAM | TVIF_STATE; |
|
tvItem.hItem = item; |
|
TreeView_GetItem(hTree, &tvItem); |
|
|
|
// delete any old dummyitem we have lying around |
|
if (htDummyItem) { |
|
TreeView_Expand(hTree, htCurHover, TVE_COLLAPSE); |
|
TreeView_DeleteItem(hTree, htDummyItem); |
|
htDummyItem = NULL; |
|
|
|
// resend the message, to avoid crashing on our dummyitem |
|
// (only necessary if item==htDummyItem, but can't hurt to do it either way...) |
|
SendMessage(hDlg, uMsg, wParam, lParam); |
|
break; |
|
} |
|
|
|
if (((CBookmarkNode *)(tvItem.lParam))->type == BOOKMARK_FOLDER) { |
|
// folder - expand it after hovering for 1 second |
|
SetTimer(hDlg, 2, 1000, (TIMERPROC) NULL); |
|
} |
|
else { |
|
KillTimer(hDlg, 2); |
|
} |
|
|
|
htCurHover = item; |
|
} |
|
|
|
if (!TreeView_GetParent(hTree, item)) { |
|
// item is the root - crudely fake being below it (no moving stuff above root) |
|
hti.pt.y += 100; |
|
} |
|
|
|
TreeView_GetItemRect(hTree, item, &tvRect, false); |
|
if (hti.pt.y < tvRect.top + (tvRect.bottom - tvRect.top)/2) { |
|
// top half of item - place insertion mark before item |
|
TreeView_SetInsertMark(hTree, item, false); |
|
} |
|
else { |
|
// bottom half of item |
|
TVITEMEX tvItem; |
|
tvItem.mask = TVIF_STATE; |
|
tvItem.hItem = item; |
|
TreeView_GetItem(hTree, &tvItem); |
|
if (tvItem.state & TVIS_EXPANDED) { |
|
// expanded folder - place insertion mark before first child |
|
TreeView_SetInsertMark(hTree, TreeView_GetChild(hTree, item), false); |
|
} |
|
else { |
|
// bookmark, separator, or collapsed folder - place insertion mark after item |
|
TreeView_SetInsertMark(hTree, item, true); |
|
} |
|
} |
|
} |
|
else { |
|
// over no item, default to end of entire list |
|
item = TreeView_GetLastVisible(hTree); |
|
TreeView_SetInsertMark(hTree, item, true); |
|
} |
|
return true; |
|
} |
|
break; |
|
|
|
case WM_LBUTTONUP: |
|
if (bDragging){ |
|
HWND hTree = GetDlgItem(hDlg, IDC_TREE_HOTLIST); |
|
HTREEITEM hSelection = TreeView_GetSelection(hTree); |
|
if (hSelection) MoveItem(hTree, hSelection, 3); |
|
|
|
// cleanup |
|
TreeView_SetInsertMark(hTree, NULL, false); |
|
SetCursor(LoadCursor(NULL, IDC_ARROW)); |
|
bDragging = false; |
|
ReleaseCapture(); |
|
KillTimer(hDlg, 2); |
|
if (htDummyItem) { |
|
// if there's a dummy item, we must be over it's parent |
|
// so we can collapse the curhover if it only has the one child (the dummy item) |
|
if (!TreeView_GetNextSibling(hTree, TreeView_GetChild(hTree, htCurHover))) { |
|
TreeView_Expand(hTree, htCurHover, TVE_COLLAPSE); |
|
} |
|
TreeView_DeleteItem(hTree, htDummyItem); |
|
htDummyItem = NULL; |
|
} |
|
} |
|
break; |
|
|
|
case WM_SIZE: |
|
{ |
|
if(wParam != SIZE_MINIMIZED) { |
|
RECT rect; |
|
GetClientRect(hDlg, &rect); |
|
OnSize(rect.bottom, rect.right); |
|
} |
|
} |
|
break; |
|
|
|
case WM_GETMINMAXINFO: |
|
LPMINMAXINFO lpminmaxinfo; |
|
lpminmaxinfo=(LPMINMAXINFO)lParam; |
|
lpminmaxinfo->ptMinTrackSize.x = 195; |
|
lpminmaxinfo->ptMinTrackSize.y = 300; |
|
break; |
|
|
|
case WM_COMMAND: |
|
{ |
|
if (LOWORD(wParam) == nAddCommand) { |
|
gHotlistRoot = workingBookmarks; |
|
|
|
CBookmarkNode *newNode = (CBookmarkNode *)lParam; |
|
|
|
TVINSERTSTRUCT tvis; |
|
tvis.itemex.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; |
|
tvis.itemex.pszText = (TCHAR*)newNode->text.c_str(); |
|
tvis.itemex.iImage = IMAGE_BOOKMARK; |
|
tvis.itemex.iSelectedImage = IMAGE_BOOKMARK; |
|
tvis.itemex.lParam = (long)newNode; |
|
tvis.hParent = hNBitem; |
|
tvis.hInsertAfter = TVI_LAST; |
|
|
|
HTREEITEM newItem = TreeView_InsertItem(hTree, &tvis); |
|
|
|
bookmarksEdited = false; |
|
} |
|
else if (HIWORD(wParam) == EN_CHANGE) { |
|
int id = LOWORD(wParam); |
|
|
|
if (id == IDC_NAME || id == IDC_URL || |
|
id == IDC_ORDER || id == IDC_DESCRIPTION || id == IDC_SHORT_NAME) { |
|
if (SendDlgItemMessage(hDlg, id, EM_GETMODIFY, 0, 0)) { |
|
SendDlgItemMessage(hDlg, id, EM_SETMODIFY, FALSE, 0); |
|
HTREEITEM hSelection = TreeView_GetSelection(hTree); |
|
if (hSelection) { |
|
CBookmarkNode *node = GetBookmarkNode(hTree, hSelection); |
|
|
|
if (node->type == BOOKMARK_BOOKMARK || node->type == BOOKMARK_FOLDER) { |
|
if (id == IDC_ORDER && node->order != GetDlgItemInt(hDlg, id, NULL, true)) { |
|
node->order = GetDlgItemInt(hDlg, id, NULL, true); |
|
bookmarksEdited = true; |
|
} |
|
else { |
|
char buffer[1024]; |
|
GetDlgItemText(hDlg, id, buffer, 1023); |
|
if (id == IDC_NAME && node->text.compare(buffer) != 0) { |
|
node->text = buffer; |
|
bookmarksEdited = true; |
|
|
|
// and update the title in the treeview |
|
TVITEMEX itemData; |
|
itemData.hItem = hSelection; |
|
itemData.mask = TVIF_TEXT; |
|
itemData.pszText = buffer; |
|
TreeView_SetItem(hTree, &itemData); |
|
} |
|
else if (id == IDC_URL && node->url.compare(buffer) != 0) { |
|
node->url = buffer; |
|
bookmarksEdited = true; |
|
} |
|
else if (id == IDC_DESCRIPTION && node->desc.compare(buffer) != 0) { |
|
node->desc = buffer; |
|
bookmarksEdited = true; |
|
} |
|
else if (id == IDC_SHORT_NAME && node->nick.compare(buffer) != 0) { |
|
node->nick = buffer; |
|
bookmarksEdited = true; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else if (HIWORD(wParam) == BN_CLICKED) { |
|
WORD id = LOWORD(wParam); |
|
switch(id){ |
|
|
|
case IDCANCEL: |
|
if (!zoom) { |
|
if (bookmarksEdited) { |
|
|
|
if (MessageBox(hDlg, gLoc->GetString(IDS_WARN_CLOSE), gLoc->GetString(IDS_CLOSE_TITLE), MB_OKCANCEL) == IDCANCEL) |
|
return 0; |
|
|
|
delete gHotlistRoot.child; |
|
delete gHotlistRoot.next; |
|
gHotlistRoot.child = NULL; |
|
gHotlistRoot.next = NULL; |
|
if (op_readFile(lpszHotlistFile) > 0) { |
|
RebuildMenu(); |
|
} |
|
} |
|
|
|
UnhookWindowsHookEx(hHook); |
|
if (hWndFront) |
|
PostMessage(hWndFront, WM_COMMAND, wm_deferbringtotop, (LPARAM) NULL); |
|
ghWndEdit = NULL; |
|
TreeView_DeleteAllItems(hTree); |
|
DestroyIcon((HICON)SendMessage(hDlg, WM_GETICON, ICON_SMALL, 0)); |
|
DestroyIcon((HICON)SendMessage(hDlg, WM_GETICON, ICON_BIG, 0)); |
|
DestroyWindow(hDlg); |
|
break; |
|
} |
|
// fall through! |
|
|
|
case IDOK: |
|
if (bookmarksEdited) { |
|
gHotlistRoot = workingBookmarks; |
|
op_writeFile(lpszHotlistFile); |
|
|
|
CBookmarkNode *node = GetBookmarkNode(hTree, hTBitem); |
|
if (node && (node->flags & BOOKMARK_FLAG_TB)) { |
|
strcpy(gToolbarFolder, (char*)node->text.c_str()); |
|
kPlugin.kFuncs->SetPreference(PREF_STRING, PREFERENCE_TOOLBAR_FOLDER, gToolbarFolder, FALSE); |
|
} |
|
node = GetBookmarkNode(hTree, hBMitem); |
|
if (node && (node->flags & BOOKMARK_FLAG_BM)) { |
|
strcpy(gMenuFolder, (char*)node->text.c_str()); |
|
kPlugin.kFuncs->SetPreference(PREF_STRING, PREFERENCE_MENU_FOLDER, gMenuFolder, FALSE); |
|
} |
|
node = GetBookmarkNode(hTree, hNBitem); |
|
if (node && (node->flags & BOOKMARK_FLAG_NB)) { |
|
strcpy(gNewitemFolder, (char*)node->text.c_str()); |
|
kPlugin.kFuncs->SetPreference(PREF_STRING, PREFERENCE_NEWITEM_FOLDER, gNewitemFolder, FALSE); |
|
} |
|
|
|
RebuildMenu(); |
|
} |
|
|
|
WINDOWPLACEMENT wp; |
|
wp.length = sizeof(wp); |
|
GetWindowPlacement(hDlg, &wp); |
|
|
|
kPlugin.kFuncs->SetPreference(PREF_INT, PREFERENCE_EDIT_DLG_LEFT, &wp.rcNormalPosition.left, FALSE); |
|
kPlugin.kFuncs->SetPreference(PREF_INT, PREFERENCE_EDIT_DLG_TOP, &wp.rcNormalPosition.top, FALSE); |
|
int temp; |
|
temp = wp.rcNormalPosition.right - wp.rcNormalPosition.left; |
|
kPlugin.kFuncs->SetPreference(PREF_INT, PREFERENCE_EDIT_DLG_WIDTH, &temp, FALSE); |
|
temp = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; |
|
kPlugin.kFuncs->SetPreference(PREF_INT, PREFERENCE_EDIT_DLG_HEIGHT, &temp, FALSE); |
|
kPlugin.kFuncs->SetPreference(PREF_BOOL, PREFERENCE_EDIT_ZOOM, &zoom, FALSE); |
|
temp = (wp.showCmd == SW_SHOWMAXIMIZED); |
|
kPlugin.kFuncs->SetPreference(PREF_BOOL, PREFERENCE_EDIT_MAX, &temp, FALSE); |
|
|
|
UnhookWindowsHookEx(hHook); |
|
if (hWndFront) |
|
PostMessage(hWndFront, WM_COMMAND, wm_deferbringtotop, (LPARAM) NULL); |
|
ghWndEdit = NULL; |
|
TreeView_DeleteAllItems(hTree); |
|
DestroyIcon((HICON)SendMessage(hDlg, WM_GETICON, ICON_SMALL, 0)); |
|
DestroyIcon((HICON)SendMessage(hDlg, WM_GETICON, ICON_BIG, 0)); |
|
DestroyWindow(hDlg); |
|
break; |
|
} |
|
} |
|
} |
|
break; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
static void ChangeSpecialFolder(HWND hTree, HTREEITEM *htiOld, HTREEITEM htiNew, int flag) { |
|
TVITEMEX itemData; |
|
|
|
CBookmarkNode *node = GetBookmarkNode(hTree, htiNew); |
|
|
|
if (node->type != BOOKMARK_FOLDER){ |
|
htiNew = TreeView_GetParent(hTree, htiNew); |
|
if (!htiNew){ |
|
// something screwy is going on... just bail out |
|
return; |
|
} |
|
} |
|
|
|
if (htiNew == *htiOld) return; |
|
|
|
// old item - might not exist |
|
if (*htiOld) { |
|
itemData.mask = TVIF_PARAM; |
|
itemData.hItem = *htiOld; |
|
if (!TreeView_GetItem(hTree, &itemData)) |
|
return; |
|
|
|
node = (CBookmarkNode *)itemData.lParam; |
|
|
|
node->flags &= ~flag; |
|
|
|
if (!node->flags) { |
|
// if not special anymore, set back to normal folder icons |
|
itemData.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; |
|
itemData.iImage = IMAGE_FOLDER_CLOSED; |
|
itemData.iSelectedImage = IMAGE_FOLDER_OPEN; |
|
TreeView_SetItem(hTree, &itemData); |
|
} |
|
} |
|
|
|
// new item |
|
itemData.mask = TVIF_PARAM; |
|
itemData.hItem = htiNew; |
|
TreeView_GetItem(hTree, &itemData); |
|
|
|
node = (CBookmarkNode *)itemData.lParam; |
|
node->flags |= flag; |
|
|
|
itemData.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; |
|
itemData.iImage = IMAGE_FOLDER_SPECIAL_CLOSED; |
|
itemData.iSelectedImage = IMAGE_FOLDER_SPECIAL_OPEN; |
|
TreeView_SetItem(hTree, &itemData); |
|
|
|
// set our stored HTREEITEM |
|
*htiOld = htiNew; |
|
} |
|
|
|
|
|
static void FillTree(HWND hTree, HTREEITEM parent, CBookmarkNode &node) |
|
{ |
|
TVINSERTSTRUCT tvis; |
|
tvis.hParent = parent; |
|
tvis.hInsertAfter = NULL; |
|
tvis.itemex.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; |
|
tvis.itemex.iImage = IMAGE_BLANK; |
|
tvis.itemex.iSelectedImage = IMAGE_BLANK; |
|
|
|
int type; |
|
CBookmarkNode *child; |
|
for (child=node.child; child; child=child->next) { |
|
tvis.itemex.lParam = (long)child; |
|
|
|
type = child->type; |
|
if (type == BOOKMARK_FOLDER) { |
|
tvis.itemex.iImage = IMAGE_FOLDER_CLOSED; |
|
tvis.itemex.iSelectedImage = IMAGE_FOLDER_OPEN; |
|
tvis.itemex.pszText = (char *)child->text.c_str(); |
|
|
|
HTREEITEM thisItem = TreeView_InsertItem(hTree, &tvis); |
|
|
|
if (child->flags & BOOKMARK_FLAG_TB) { |
|
ChangeSpecialFolder(hTree, &hTBitem, thisItem, BOOKMARK_FLAG_TB); |
|
} |
|
if (child->flags & BOOKMARK_FLAG_BM) { |
|
ChangeSpecialFolder(hTree, &hBMitem, thisItem, BOOKMARK_FLAG_BM); |
|
} |
|
if (child->flags & BOOKMARK_FLAG_NB) { |
|
ChangeSpecialFolder(hTree, &hNBitem, thisItem, BOOKMARK_FLAG_NB); |
|
} |
|
|
|
FillTree(hTree, thisItem, *child); |
|
} |
|
else if (type == BOOKMARK_SEPARATOR) { |
|
tvis.itemex.iImage = IMAGE_BLANK; |
|
tvis.itemex.iSelectedImage = IMAGE_BLANK; |
|
tvis.itemex.pszText = "---"; |
|
TreeView_InsertItem(hTree, &tvis); |
|
} |
|
else { |
|
tvis.itemex.iImage = IMAGE_BOOKMARK; |
|
tvis.itemex.iSelectedImage = IMAGE_BOOKMARK; |
|
tvis.itemex.pszText = (char *)child->text.c_str(); |
|
TreeView_InsertItem(hTree, &tvis); |
|
} |
|
} |
|
} |
|
|
|
|
|
static void CopyItem(HWND hTree, HTREEITEM item) { |
|
CBookmarkNode *node = GetBookmarkNode(hTree, item); |
|
HTREEITEM parent = TreeView_GetParent(hTree, item); |
|
if (parent) { |
|
if (freeNode && freeParentNode) |
|
freeParentNode->DeleteNode(freeNode); |
|
|
|
freeNode = new CBookmarkNode(); |
|
*freeNode = *node; |
|
freeNode->id = kPlugin.kFuncs->GetCommandIDs(1); |
|
freeParentNode = GetBookmarkNode(hTree, parent); |
|
} |
|
} |
|
|
|
static void DeleteItem(HWND hTree, HTREEITEM item, int mode) { |
|
CBookmarkNode *node, *parentNode; |
|
|
|
node = GetBookmarkNode(hTree, item); |
|
|
|
HTREEITEM parent = TreeView_GetParent(hTree, item); |
|
if (parent){ |
|
parentNode = GetBookmarkNode(hTree, parent); |
|
} |
|
else{ |
|
// no deleting the root node |
|
return; |
|
} |
|
|
|
if (mode == CUT) { |
|
parentNode->UnlinkNode(node); |
|
freeNode = node; |
|
freeParentNode = parentNode; |
|
} else |
|
parentNode->DeleteNode(node); |
|
|
|
// select a new item |
|
HTREEITEM hSelect = TreeView_GetNextSibling(hTree, item); |
|
if (!hSelect) hSelect = TreeView_GetPrevSibling(hTree, item); |
|
if (!hSelect) hSelect = TreeView_GetParent(hTree, item); |
|
|
|
TreeView_DeleteItem(hTree, item); |
|
|
|
// must call selectitem after deleteitem, otherwise the SELCHANGED handler will try to update the deleted node! |
|
TreeView_SelectItem(hTree, hSelect); |
|
|
|
bookmarksEdited = true; |
|
} |
|
|
|
static void CopyBranch(HWND hTree, HTREEITEM item, HTREEITEM newParent) |
|
{ |
|
char buffer[MAX_PATH]; |
|
|
|
TVINSERTSTRUCT tvis; |
|
tvis.hParent = newParent; |
|
tvis.hInsertAfter = TVI_LAST; |
|
tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; |
|
tvis.item.pszText = buffer; |
|
tvis.item.cchTextMax = MAX_PATH; |
|
|
|
HTREEITEM newItem; |
|
|
|
tvis.item.hItem = TreeView_GetChild(hTree, item); |
|
while(tvis.item.hItem) { |
|
TreeView_GetItem(hTree, &tvis.item); |
|
newItem = TreeView_InsertItem(hTree, &tvis); |
|
|
|
if (tvis.item.cChildren) { |
|
CopyBranch(hTree, tvis.item.hItem, newItem); |
|
} |
|
|
|
tvis.item.hItem = TreeView_GetNextSibling(hTree, tvis.item.hItem); |
|
} |
|
} |
|
|
|
|
|
static void MoveItem(HWND hTree, HTREEITEM item, int mode) { |
|
if (item == TreeView_GetRoot(hTree)) return; |
|
|
|
CBookmarkNode *moveNode, *oldPreviousNode, *oldParentNode, *newPreviousNode, *newParentNode; |
|
char buffer[MAX_PATH]; |
|
|
|
// setup the insert item |
|
TVINSERTSTRUCT tvis; |
|
tvis.item.hItem = item; |
|
tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; |
|
tvis.item.pszText = buffer; |
|
tvis.item.cchTextMax = MAX_PATH; |
|
TreeView_GetItem(hTree, &tvis.item); |
|
|
|
// get the current item's bookmarknode |
|
moveNode = (CBookmarkNode *)tvis.item.lParam; |
|
|
|
// setup the old parent |
|
HTREEITEM oldParentItem = TreeView_GetParent(hTree, item); |
|
if (oldParentItem) { |
|
oldParentNode = GetBookmarkNode(hTree, oldParentItem); |
|
} |
|
else { |
|
oldParentNode = &workingBookmarks; |
|
} |
|
|
|
// determine the new location in the treeview |
|
HTREEITEM itemDrop; |
|
switch (mode) { |
|
case 1: // move up one |
|
// if we're at the top, do nothing |
|
if (TreeView_GetPrevVisible(hTree, item) == TreeView_GetRoot(hTree)) return; |
|
|
|
itemDrop = TreeView_GetPrevSibling(hTree, item); |
|
|
|
if (!itemDrop) { // we are first child of parent - move above parent, |
|
itemDrop = TreeView_GetPrevSibling(hTree, TreeView_GetParent(hTree, item)); |
|
tvis.hInsertAfter = itemDrop; |
|
if (!itemDrop) { // parent is first child of parent's parent - place after parent's parent |
|
itemDrop = TreeView_GetParent(hTree, item); |
|
tvis.hInsertAfter = TVI_FIRST; |
|
} |
|
|
|
PostMessage(hTree, WM_VSCROLL, SB_LINEUP, (LPARAM) NULL); |
|
} |
|
else { |
|
TVITEMEX tvItem; |
|
tvItem.mask = TVIF_STATE; |
|
tvItem.hItem = itemDrop; |
|
TreeView_GetItem(hTree, &tvItem); |
|
if (tvItem.state & TVIS_EXPANDED) { // we're below an expanded folder - move to last child of folder |
|
itemDrop = TreeView_GetPrevVisible(hTree, item); |
|
tvis.hInsertAfter = itemDrop; |
|
} |
|
else { // otherwise, just place after prev siblings's prev sibling |
|
itemDrop = TreeView_GetPrevSibling(hTree, itemDrop); |
|
tvis.hInsertAfter = itemDrop; |
|
if (!itemDrop) { // item is the second child |
|
itemDrop = item; |
|
tvis.hInsertAfter = TVI_FIRST; |
|
} |
|
|
|
PostMessage(hTree, WM_VSCROLL, SB_LINEUP, (LPARAM) NULL); |
|
} |
|
} |
|
|
|
if (tvis.hInsertAfter == TVI_FIRST) { |
|
newPreviousNode = NULL; |
|
} |
|
else { |
|
newPreviousNode = GetBookmarkNode(hTree, tvis.hInsertAfter); |
|
} |
|
|
|
break; |
|
case 2: // move down one |
|
if (!TreeView_GetNextVisible(hTree, item)) return; // do nothing if we're at the very end |
|
itemDrop = TreeView_GetNextSibling(hTree, item); |
|
if (itemDrop) { |
|
TVITEMEX tvItem; |
|
tvItem.mask = TVIF_STATE; |
|
tvItem.hItem = itemDrop; |
|
TreeView_GetItem(hTree, &tvItem); |
|
if (tvItem.state & TVIS_EXPANDED) { |
|
// expanded folder - insert before first child |
|
tvis.hInsertAfter = NULL; |
|
itemDrop = TreeView_GetChild(hTree, itemDrop); |
|
} |
|
else { |
|
// bookmark or collapsed folder - insert after item |
|
tvis.hInsertAfter = itemDrop; |
|
} |
|
|
|
if (tvis.hInsertAfter) { |
|
newPreviousNode = GetBookmarkNode(hTree, tvis.hInsertAfter); |
|
} |
|
else { |
|
newPreviousNode = NULL; |
|
tvis.hInsertAfter = TVI_FIRST; |
|
} |
|
|
|
PostMessage(hTree, WM_VSCROLL, SB_LINEDOWN, (LPARAM) NULL); |
|
} |
|
else { |
|
// if there is no next sibling, try moving it down a level (place it after its parent) |
|
itemDrop = TreeView_GetParent(hTree, item); |
|
|
|
// if we're at the end of the list, we'll be trying to place after the root - just return |
|
if (itemDrop == TreeView_GetRoot(hTree)) return; |
|
|
|
tvis.hInsertAfter = itemDrop; |
|
newPreviousNode = GetBookmarkNode(hTree, tvis.hInsertAfter); |
|
} |
|
|
|
break; |
|
case 3: // move to drag'n'drop location |
|
TVHITTESTINFO hti; |
|
GetCursorPos(&hti.pt); |
|
ScreenToClient(hTree, &hti.pt); |
|
|
|
itemDrop = TreeView_HitTest(hTree, &hti); |
|
if (itemDrop) { |
|
if (!TreeView_GetParent(hTree, itemDrop)) { |
|
// item is the root - crudely fake being below it (no moving stuff above root) |
|
hti.pt.y += 100; |
|
} |
|
RECT tvRect; |
|
TreeView_GetItemRect(hTree, itemDrop, &tvRect, false); |
|
if (hti.pt.y < tvRect.top + (tvRect.bottom - tvRect.top)/2) { |
|
// top half of item - insert before item |
|
tvis.hInsertAfter = TreeView_GetPrevSibling(hTree, itemDrop); |
|
} |
|
else { |
|
// bottom half of item |
|
TVITEMEX tvItem; |
|
tvItem.mask = TVIF_STATE; |
|
tvItem.hItem = itemDrop; |
|
TreeView_GetItem(hTree, &tvItem); |
|
if (tvItem.state & TVIS_EXPANDED) { |
|
// expanded folder - insert before first child |
|
tvis.hInsertAfter = NULL; |
|
itemDrop = TreeView_GetChild(hTree, itemDrop); |
|
} |
|
else { |
|
// bookmark or collapsed folder - insert after item |
|
tvis.hInsertAfter = itemDrop; |
|
} |
|
} |
|
|
|
if (tvis.hInsertAfter) { |
|
newPreviousNode = GetBookmarkNode(hTree, tvis.hInsertAfter); |
|
} |
|
else { |
|
newPreviousNode = NULL; |
|
tvis.hInsertAfter = TVI_FIRST; |
|
} |
|
} |
|
else { |
|
// default to end of entire tree... is this desirable? e.g., what if the user drags it out of the treeview area, we just throw it on the end??? |
|
tvis.hInsertAfter = TVI_LAST; |
|
|
|
itemDrop = TreeView_GetLastVisible(hTree); |
|
|
|
newPreviousNode = GetBookmarkNode(hTree, itemDrop); |
|
} |
|
|
|
break; |
|
} |
|
|
|
// check to see if we're dropping something in itself |
|
for (HTREEITEM temp = TreeView_GetParent(hTree, itemDrop); temp != NULL ; temp = TreeView_GetParent(hTree, temp)) { |
|
if (temp == item) {return;} |
|
} |
|
|
|
// setup the new parent |
|
tvis.hParent = TreeView_GetParent(hTree, itemDrop); |
|
if (tvis.hParent){ |
|
newParentNode = GetBookmarkNode(hTree, tvis.hParent); |
|
} |
|
else{ |
|
newParentNode = &workingBookmarks; |
|
} |
|
|
|
// This conditional only works because we check newPreviousNode's existence before checking its nexts, which will crash if the node is NULL) |
|
// And maybe this could be somewhat simpler? But it works well, so hey. |
|
if ((newPreviousNode && moveNode != newPreviousNode && moveNode != newPreviousNode->next) || (!newPreviousNode && moveNode != newParentNode && moveNode != newParentNode->child)) { |
|
|
|
// remove node from the bookmark structure |
|
if (oldParentNode->child == moveNode) { |
|
oldParentNode->child = moveNode->next; |
|
if (!moveNode->next) |
|
oldParentNode->lastChild = NULL; |
|
} |
|
else { |
|
// find the old previous node (only necessary to find it if it exists) |
|
if (oldParentNode->child) |
|
for (oldPreviousNode = oldParentNode->child ; oldPreviousNode->next != moveNode ; oldPreviousNode = oldPreviousNode->next); |
|
oldPreviousNode->next = moveNode->next; |
|
if (!moveNode->next) |
|
oldParentNode->lastChild = oldPreviousNode; |
|
} |
|
|
|
// insert node in its new location in the bookmark structure |
|
if (newPreviousNode) { |
|
moveNode->next = newPreviousNode->next; |
|
newPreviousNode->next = moveNode; |
|
} |
|
else { |
|
moveNode->next = newParentNode->child; |
|
newParentNode->child = moveNode; |
|
} |
|
|
|
// collapse its parent if it's going to be empty (doesn't work if we collapse after deletion, for some reason) |
|
if (!TreeView_GetNextSibling(hTree, TreeView_GetChild(hTree, oldParentItem))) { |
|
TreeView_Expand(hTree, oldParentItem, TVE_COLLAPSE); |
|
} |
|
|
|
// create a new copy of the treeview item |
|
HTREEITEM newParent = TreeView_InsertItem(hTree, &tvis); |
|
|
|
// copy its children |
|
CopyBranch(hTree, item, newParent); |
|
|
|
// select it |
|
TreeView_SelectItem(hTree, newParent); |
|
|
|
// delete it |
|
TreeView_DeleteItem(hTree, item); |
|
|
|
bookmarksEdited = true; |
|
} |
|
} |
|
|
|
|
|
static void CreateNewObject(HWND hTree, HTREEITEM fromItem, int type, int mode) { |
|
CBookmarkNode *newNode; |
|
|
|
TVINSERTSTRUCT tvis; |
|
tvis.itemex.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; |
|
|
|
switch (type) { |
|
case BOOKMARK_BOOKMARK: |
|
if (mode == PASTE && freeNode) { |
|
newNode = freeNode; |
|
freeNode = NULL; |
|
} else |
|
newNode = new CBookmarkNode(kPlugin.kFuncs->GetCommandIDs(1), gLoc->GetString(IDS_NEW_BOOKMARK), "http://kmeleon.sourceforge.net/", "", "", BOOKMARK_BOOKMARK, time(NULL)); |
|
tvis.itemex.pszText = (TCHAR*)newNode->text.c_str(); |
|
tvis.itemex.iImage = IMAGE_BOOKMARK; |
|
tvis.itemex.iSelectedImage = IMAGE_BOOKMARK; |
|
break; |
|
case BOOKMARK_FOLDER: |
|
if (mode == PASTE && freeNode) { |
|
newNode = freeNode; |
|
freeNode = NULL; |
|
} else |
|
newNode = new CBookmarkNode(0, gLoc->GetString(IDS_NEW_FOLDER), "", "", "", BOOKMARK_FOLDER, time(NULL)); |
|
tvis.itemex.pszText = (TCHAR*)newNode->text.c_str(); |
|
tvis.itemex.iImage = IMAGE_FOLDER_CLOSED; |
|
tvis.itemex.iSelectedImage = IMAGE_FOLDER_OPEN; |
|
break; |
|
} |
|
|
|
tvis.itemex.lParam = (long)newNode; |
|
|
|
TVITEMEX itemData; |
|
itemData.mask = TVIF_PARAM; |
|
itemData.hItem = fromItem; |
|
TreeView_GetItem(hTree, &itemData); |
|
CBookmarkNode *fromNode = (CBookmarkNode *)itemData.lParam; |
|
|
|
if (fromNode->type == BOOKMARK_FOLDER && mode == PASTE) { |
|
// if we're adding to a folder, make it the first child |
|
newNode->next = fromNode->child; |
|
fromNode->child = newNode; |
|
|
|
tvis.hParent = fromItem; |
|
tvis.hInsertAfter = TVI_FIRST; |
|
} |
|
else { |
|
// otherwise just put it directly after |
|
newNode->next = fromNode->next; |
|
fromNode->next = newNode; |
|
|
|
tvis.hParent = TreeView_GetParent(hTree, fromItem); |
|
tvis.hInsertAfter = fromItem; |
|
} |
|
|
|
HTREEITEM newItem = TreeView_InsertItem(hTree, &tvis); |
|
if (type == BOOKMARK_FOLDER && newNode->child) |
|
FillTree(hTree, newItem, *newNode); |
|
|
|
TreeView_SelectItem(hTree, newItem); |
|
|
|
bookmarksEdited = true; |
|
} |
|
|
|
|
|
|
|
static void OnRClick(HWND hTree) |
|
{ |
|
POINT mouse; |
|
GetCursorPos(&mouse); |
|
|
|
TVHITTESTINFO hti; |
|
hti.pt.x = mouse.x; |
|
hti.pt.y = mouse.y; |
|
ScreenToClient(hTree, &hti.pt); |
|
|
|
HTREEITEM hItem = TreeView_HitTest(hTree, &hti); |
|
if (hItem) { |
|
TreeView_SelectItem(hTree, hItem); |
|
|
|
HMENU topMenu = gLoc->LoadMenu(IDR_CONTEXTMENU); |
|
HMENU contextMenu = GetSubMenu(topMenu, 0); |
|
|
|
CBookmarkNode *node = GetBookmarkNode(hTree, hItem); |
|
if (node && node->type != BOOKMARK_FOLDER) { |
|
EnableMenuItem(contextMenu, ID__OPEN, MF_BYCOMMAND | MF_ENABLED); |
|
EnableMenuItem(contextMenu, ID__OPEN_BACKGROUND, MF_BYCOMMAND | MF_ENABLED); |
|
EnableMenuItem(contextMenu, ID__SETAS_TOOLBARFOLDER, MF_BYCOMMAND | MF_GRAYED); |
|
EnableMenuItem(contextMenu, ID__SETAS_BOOKMARKMENU, MF_BYCOMMAND | MF_GRAYED); |
|
EnableMenuItem(contextMenu, ID__SETAS_NEWBOOKMARKFOLDER, MF_BYCOMMAND | MF_GRAYED); |
|
} |
|
else { |
|
EnableMenuItem(contextMenu, ID__OPEN, MF_BYCOMMAND | MF_GRAYED); |
|
EnableMenuItem(contextMenu, ID__OPEN_BACKGROUND, MF_BYCOMMAND | MF_GRAYED); |
|
EnableMenuItem(contextMenu, ID__SETAS_TOOLBARFOLDER, MF_BYCOMMAND | MF_ENABLED); |
|
EnableMenuItem(contextMenu, ID__SETAS_BOOKMARKMENU, MF_BYCOMMAND | MF_ENABLED); |
|
EnableMenuItem(contextMenu, ID__SETAS_NEWBOOKMARKFOLDER, MF_BYCOMMAND | MF_ENABLED); |
|
} |
|
|
|
if (node && (node->flags & BOOKMARK_FLAG_TB)) |
|
CheckMenuItem(contextMenu, ID__SETAS_TOOLBARFOLDER, MF_BYCOMMAND | MF_CHECKED); |
|
else |
|
CheckMenuItem(contextMenu, ID__SETAS_TOOLBARFOLDER, MF_BYCOMMAND | MF_UNCHECKED); |
|
if (node && (node->flags & BOOKMARK_FLAG_BM)) |
|
CheckMenuItem(contextMenu, ID__SETAS_BOOKMARKMENU, MF_BYCOMMAND | MF_CHECKED); |
|
else |
|
CheckMenuItem(contextMenu, ID__SETAS_BOOKMARKMENU, MF_BYCOMMAND | MF_UNCHECKED); |
|
if (node && (node->flags & BOOKMARK_FLAG_NB)) |
|
CheckMenuItem(contextMenu, ID__SETAS_NEWBOOKMARKFOLDER, MF_BYCOMMAND | MF_CHECKED); |
|
else |
|
CheckMenuItem(contextMenu, ID__SETAS_NEWBOOKMARKFOLDER, MF_BYCOMMAND | MF_UNCHECKED); |
|
|
|
if (zoom) |
|
CheckMenuItem(contextMenu, ID__ZOOM, MF_BYCOMMAND | MF_UNCHECKED); |
|
else |
|
CheckMenuItem(contextMenu, ID__ZOOM, MF_BYCOMMAND | MF_CHECKED); |
|
|
|
bTracking = TRUE; |
|
int command = TrackPopupMenu(contextMenu, TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_RETURNCMD, mouse.x, mouse.y, 0, hTree, NULL); |
|
bTracking = FALSE; |
|
|
|
DestroyMenu(topMenu); |
|
|
|
switch (command) { |
|
case ID__OPEN: |
|
{ |
|
CBookmarkNode *node = GetBookmarkNode(hTree, hItem); |
|
if (node->type == BOOKMARK_BOOKMARK) { |
|
node->lastVisit = time(NULL); |
|
bookmarksEdited = true; |
|
kPlugin.kFuncs->NavigateTo(node->url.c_str(), OPEN_NORMAL, NULL); |
|
TreeView_SelectItem(hTree, hItem); // just to fire off a SELCHANGED notifier to update the status (last visited!) |
|
PostMessage(hWndFront, WM_COMMAND, wm_deferbringtotop, (LPARAM)NULL); |
|
} |
|
} |
|
break; |
|
case ID__OPEN_BACKGROUND: |
|
{ |
|
CBookmarkNode *node = GetBookmarkNode(hTree, hItem); |
|
if (node->type == BOOKMARK_BOOKMARK) { |
|
node->lastVisit = time(NULL); |
|
bookmarksEdited = true; |
|
kPlugin.kFuncs->NavigateTo(node->url.c_str(), OPEN_BACKGROUND, NULL); |
|
TreeView_SelectItem(hTree, hItem); // just to fire off a SELCHANGED notifier to update the status (last visited!) |
|
} |
|
} |
|
break; |
|
case ID__NEW_FOLDER: |
|
CreateNewObject(hTree, hItem, BOOKMARK_FOLDER); |
|
if (!zoom) { |
|
SetFocus(GetDlgItem(hEditWnd, IDC_NAME)); |
|
SendDlgItemMessage(hEditWnd, IDC_NAME, EM_SETSEL, 0, -1); |
|
} |
|
break; |
|
case ID__NEW_BOOKMARK: |
|
CreateNewObject(hTree, hItem, BOOKMARK_BOOKMARK); |
|
if (!zoom) { |
|
SetFocus(GetDlgItem(hEditWnd, IDC_NAME)); |
|
SendDlgItemMessage(hEditWnd, IDC_NAME, EM_SETSEL, 0, -1); |
|
} |
|
break; |
|
case ID__SETAS_TOOLBARFOLDER: |
|
ChangeSpecialFolder(hTree, &hTBitem, hItem, BOOKMARK_FLAG_TB); |
|
bookmarksEdited = true; // ChangeSpecialFolder is used when filling the tree initially, as well, so we don't want it to set bookmarksModified itself |
|
break; |
|
case ID__SETAS_NEWBOOKMARKFOLDER: |
|
ChangeSpecialFolder(hTree, &hNBitem, hItem, BOOKMARK_FLAG_NB); |
|
bookmarksEdited = true; |
|
break; |
|
case ID__SETAS_BOOKMARKMENU: |
|
ChangeSpecialFolder(hTree, &hBMitem, hItem, BOOKMARK_FLAG_BM); |
|
bookmarksEdited = true; |
|
break; |
|
case ID__BOOKMARK_DELETE: |
|
DeleteItem(hTree, hItem); |
|
break; |
|
case ID__BOOKMARK_CUT: |
|
DeleteItem(hTree, hItem, CUT); |
|
break; |
|
case ID__BOOKMARK_COPY: |
|
CopyItem(hTree, hItem); |
|
break; |
|
case ID__BOOKMARK_PASTE: |
|
if (freeNode) |
|
CreateNewObject(hTree, hItem, freeNode->type, PASTE); |
|
break; |
|
case ID__ZOOM: |
|
{ |
|
zoom = !zoom; |
|
|
|
RECT rect; |
|
GetClientRect(hEditWnd, &rect); |
|
OnSize(rect.bottom, rect.right); |
|
|
|
TreeView_SelectItem(hTree, hItem); // just to fire off a SELCHANGED notifier |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
|
|
|
|
// this is ugly, see... all this need to be changed each time the dialog is re-arranged... |
|
#define BORDER 8 // this one is pixels, the rest are DLUs |
|
#define BUTTON_HEIGHT 15 |
|
#define OK_WIDTH 45 |
|
#define CANCEL_WIDTH 45 |
|
#define PROPERTIES_HEIGHT 88 |
|
#define EDITBOXES_LEFT 36 |
|
#define EDITBOXES_TOP (276-174) |
|
#define EDITBOXES_HEIGHT 12 |
|
#define DATES_WIDTH 78 |
|
#define OTHER_WIDTH 35 |
|
|
|
#define convX(x) MulDiv((int)(x), buX, 4) |
|
#define convY(y) MulDiv((int)(y), buY, 8) |
|
|
|
static void OnSize(int height, int width) { |
|
int buX, buY; |
|
RECT rc; // GetDialogBaseUnits returns incorrect values...? |
|
SetRect(&rc, 0, 0, 4, 8); |
|
MapDialogRect(hEditWnd, &rc); |
|
buY = rc.bottom; |
|
buX = rc.right; |
|
|
|
// resize tree |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_TREE_HOTLIST), 0, |
|
zoom ? 0 : BORDER, |
|
zoom ? 0 : BORDER, |
|
zoom ? width : width-(BORDER*2), |
|
zoom ? height : height-BORDER*4-convY(BUTTON_HEIGHT+(1-zoom)*PROPERTIES_HEIGHT), |
|
0); |
|
|
|
// move cancel button |
|
SetWindowPos(GetDlgItem(hEditWnd, IDCANCEL), 0, |
|
width-BORDER-convX(CANCEL_WIDTH), |
|
zoom ? height + BORDER : height-BORDER-convY(BUTTON_HEIGHT), |
|
0, 0, SWP_NOSIZE); |
|
|
|
// move ok button |
|
SetWindowPos(GetDlgItem(hEditWnd, IDOK), 0, |
|
width-BORDER*2-convX(CANCEL_WIDTH+OK_WIDTH), |
|
zoom ? height + BORDER : height-BORDER-convY(BUTTON_HEIGHT), |
|
0, 0, SWP_NOSIZE); |
|
|
|
// move/resize properties box |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_STATIC_PROPERTIES), 0, |
|
BORDER, |
|
zoom ? height + BORDER : height-BORDER*2-convY(BUTTON_HEIGHT+PROPERTIES_HEIGHT), |
|
width-BORDER*2, |
|
convY(PROPERTIES_HEIGHT), |
|
0); |
|
|
|
// move/resize properties widgets |
|
int x_max = convX(EDITBOXES_LEFT+DATES_WIDTH)+BORDER; |
|
int x_half = width/2 + BORDER/2; |
|
int x2 = min(x_max, x_half); |
|
int w1 = x2 - convX(EDITBOXES_LEFT) - BORDER; |
|
int w2 = width - x2 - 2*BORDER; |
|
|
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_STATIC_CREATED), 0, |
|
BORDER*2, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*2.5), |
|
0, |
|
0, SWP_NOSIZE); |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_CREATED), 0, |
|
convX(EDITBOXES_LEFT)+5, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*2.5), |
|
w1, // convX(DATES_WIDTH), |
|
convY(EDITBOXES_HEIGHT), |
|
0); |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_STATIC_VISITED), 0, |
|
x2, // convX(EDITBOXES_LEFT+DATES_WIDTH)+BORDER, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*2.5), |
|
0, 0, SWP_NOSIZE); |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_LAST_VISIT), 0, |
|
x2 + OTHER_WIDTH+5, // convX(EDITBOXES_LEFT+DATES_WIDTH+OTHER_WIDTH)+BORDER+5, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*2.5), |
|
w2 - OTHER_WIDTH-5, // width-convX(EDITBOXES_LEFT+DATES_WIDTH+OTHER_WIDTH)-BORDER*3, |
|
convY(EDITBOXES_HEIGHT), 0); |
|
|
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_STATIC_SHORT), 0, |
|
2*BORDER, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*5.0), |
|
0, 0, SWP_NOSIZE); |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_SHORT_NAME), 0, |
|
convX(EDITBOXES_LEFT), |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*5.0)-2, |
|
convX(DATES_WIDTH), |
|
convY(EDITBOXES_HEIGHT), |
|
0); |
|
|
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_STATIC_DESC), 0, |
|
x2, // convX(EDITBOXES_LEFT+DATES_WIDTH)+BORDER, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*3.75), |
|
0, 0, SWP_NOSIZE); |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_DESCRIPTION), 0, |
|
x2 + OTHER_WIDTH, // convX(EDITBOXES_LEFT+DATES_WIDTH+OTHER_WIDTH)+BORDER, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*3.75)-2, |
|
w2 - OTHER_WIDTH, // width-convX(EDITBOXES_LEFT+DATES_WIDTH+OTHER_WIDTH)-BORDER*3, |
|
convY(EDITBOXES_HEIGHT), |
|
0); |
|
|
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_STATIC_ORDER), 0, |
|
2*BORDER, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*3.75), |
|
0, 0, SWP_NOSIZE); |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_ORDER), 0, |
|
convX(EDITBOXES_LEFT), |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*3.75)-2, |
|
w1, // convX(DATES_WIDTH), |
|
convY(EDITBOXES_HEIGHT), |
|
0); |
|
|
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_STATIC_URL), 0, |
|
BORDER*2, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*1.25), |
|
0, 0, SWP_NOSIZE); |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_URL), 0, |
|
convX(EDITBOXES_LEFT), |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP-EDITBOXES_HEIGHT*1.25)-2, |
|
width-convX(EDITBOXES_LEFT)-BORDER*2, |
|
convY(EDITBOXES_HEIGHT), |
|
0); |
|
|
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_STATIC_NAME), 0, |
|
BORDER*2, |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP), |
|
0, 0, SWP_NOSIZE); |
|
SetWindowPos(GetDlgItem(hEditWnd, IDC_NAME), 0, |
|
convX(EDITBOXES_LEFT), |
|
zoom ? height + BORDER : height-convY(EDITBOXES_TOP)-2, |
|
width-convX(EDITBOXES_LEFT)-BORDER*2, |
|
convY(EDITBOXES_HEIGHT), |
|
0); |
|
|
|
InvalidateRgn(hEditWnd, NULL, FALSE); |
|
UpdateWindow(hEditWnd); |
|
}
|
|
|