Compare commits

..
Author SHA1 Message Date
agrynco 2f5ae373a1 fix(settings): preserve unset files shortcut in options 2026-11-14 15:14:16 +02:00
agrynco b978361180 chore(release): package kswitcher v0.6.78 with files 2026-11-14 15:11:26 +02:00
agrynco 93b8055085 fix(files): synchronize settings across windows
Reload shared preferences in open windows and apply only fields changed in Options.
2026-11-14 15:09:17 +02:00
agrynco 70ee338fc3 Merge pull request 'Add searchable command history to KSwitcher Files' (#19) from codex/files-command-history into main 2026-11-14 14:43:10 +02:00
13 changed files with 254 additions and 102 deletions

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.24)
project(KSwitcher VERSION 0.6.77 LANGUAGES CXX RC)
project(KSwitcher VERSION 0.6.78 LANGUAGES CXX RC)
if(NOT WIN32)
message(FATAL_ERROR "KSwitcher uses native Windows APIs")
endif()
+4
View File
@@ -65,6 +65,10 @@ Far Manager є зразком для оформлення файлового м
## Панелі
- Застосовані налаштування Files одразу підхоплюють інші відкриті вікна.
Apply зберігає поля, змінені в поточній чернетці. Якщо два вікна одночасно
редагували набір стилів файлів, відкрий Options заново, щоб побачити свіжі правила.
- Типовий колір тексту для ZIP-архівів — світлий коралово-рожевий.
- Меню Change drive показує літеру, тип, загальний обсяг і вільне місце. Відкриття меню запускає нове LAN-виявлення. Секція KSwitcher LAN показує збережені пари, зокрема офлайн. Після кожного відкриття меню асинхронно запитує диски й показує їх під назвою відповідного ПК. Поки триває запит, видно стан завантаження. Якщо запит не вдався, видно помилку. Повторне відкриття запускає новий запит. Кожна панель має власний диск і шлях, а в заголовку віддаленої панелі перед шляхом показано назву ПК.
Binary file not shown.
+12
View File
@@ -1,5 +1,17 @@
# Latest Windows release
## v0.6.78 — 2026-11-14
The Windows package includes KSwitcher Files, a two-panel file manager with
local and paired LAN drives, folder shortcuts, an embedded PowerShell terminal,
and searchable command history. Applied Files settings update other open
instances immediately.
**Українською.** До пакета для Windows входить KSwitcher Files, двопанельний
файловий менеджер із локальними дисками й дисками спарених ПК, ярликами папок,
вбудованим PowerShell та пошуком в історії команд. Застосовані налаштування
Files одразу підхоплюють інші відкриті вікна.
## v0.6.77 — 2026-11-13
The screenshot editor remembers the local pencil smoothing default across
+1 -1
View File
@@ -1 +1 @@
51d95639527590b36453a5ef485532a7d2135950222fa197eb431a5309f1a45c KSwitcher-win-x64.zip
e51829479fa7fa372c0d87a5065716af56d5f0e62b2d9562040f7288e1600ce7 KSwitcher-win-x64.zip
+70 -25
View File
@@ -1,86 +1,131 @@
{
"version": "0.6.77",
"schema": 1,
"version": "0.6.78",
"files": [
{
"size": 2340864,
"path": "KSwitcher.exe",
"size": 2249216,
"sha256": "f1c79d337d746efcda03946cc833b7b5588ef4e739f1dff7d3afa15d0465469f"
"sha256": "1e67e8e15eada80c902764f14a12a0bd370080709a94d454cc3c565dd3de1136"
},
{
"size": 2341376,
"path": "KSwitcher.Config.exe",
"size": 2251776,
"sha256": "016edc389007e0d15ee365fff7115fc91a820b46080cb39a3fb362f3b463bae7"
"sha256": "64f83dcc31d785d17832380371379a6f7f30ed52eff79b7fcd29b95b94a7d5b3"
},
{
"size": 3319296,
"path": "KSwitcher.Screenshot.exe",
"size": 3247616,
"sha256": "c8ef070ad01acc410802c62e0df6a96cb299fe036fe8e99f0cf6a398b7324ec6"
"sha256": "d9593c6ff103070f1f72b93c0f350ba4782d9df814090565f48bd0aa34125059"
},
{
"size": 1815552,
"path": "KSwitcher.Files.exe",
"sha256": "22f897cfdc3207350e3edb63f33747d71a0f9d60c7a8d3771f642ee589ed6ce1"
},
{
"size": 194912,
"path": "WebView2Loader.dll",
"sha256": "d3fce90bdeecb08596e377dea6a316354dd8949e32ff09b89d51be00c14e21b6"
},
{
"size": 1103,
"path": "terminal/addon-fit-LICENSE.txt",
"sha256": "e256f01188af527e4d06d21d06fbf785ae9c50d4b328bf03cbe0ba7f0aa4228f"
},
{
"size": 1521,
"path": "terminal/addon-fit.js",
"sha256": "ba3ea256ce0620a0992a197d6c9baea64823fc93d8da07a9e366ca9943c18527"
},
{
"size": 527,
"path": "terminal/index.html",
"sha256": "084d97a727b778fb10d31adcd557ee7840a38377ed60e0ef0f3ece93b349b1ef"
},
{
"size": 3174,
"path": "terminal/terminal.js",
"sha256": "142624d166314c4539dd14f922c17dca3d2bc7203f84aff2df03a196602c4b09"
},
{
"size": 1261,
"path": "terminal/xterm-LICENSE.txt",
"sha256": "b569f629d00f2626a8100df2a1798210535621e42164dfd426a6fe5aac7b0ccd"
},
{
"size": 7112,
"path": "terminal/xterm.css",
"sha256": "854a7c0fb70e8b1a083c16797ab827299fb18744f5ad34f227b48337e33293c6"
},
{
"size": 488663,
"path": "terminal/xterm.js",
"sha256": "14903579ff54664cd72f8e8699e6961a6272c21863ec1c3b118cdc8af5d4a972"
},
{
"path": "LICENSE",
"size": 4401,
"path": "LICENSE",
"sha256": "d3c81140cce01c26bf6cbf52aa40e0825e1fa35b9a91d1387170a65d2597082c"
},
{
"path": "json-LICENSE.txt",
"size": 1075,
"path": "json-LICENSE.txt",
"sha256": "c0d068392ea65358b798b8c165103560f06e9e3b38c4ab4e2d8810a7b931af86"
},
{
"path": "README.md",
"size": 93885,
"path": "README.md",
"sha256": "df6d40d0eb66ad7da8db1cffe6bd211de70dfee474cc228e041c821b3940718b"
},
{
"path": "LAN-PREVIEW.md",
"size": 11418,
"path": "LAN-PREVIEW.md",
"sha256": "2c13d3ed4761e679c352fb1ade24a1ec3060ad2862376ede801cdee5fcc3bada"
},
{
"path": "dictionaries/en.txt",
"size": 682867,
"path": "dictionaries/en.txt",
"sha256": "5f267c141c3d6837870e1c098f86b89a113ba300343119432644ead88f720c21"
},
{
"path": "dictionaries/LICENSE-CC-BY-SA-4.0.txt",
"size": 20138,
"path": "dictionaries/LICENSE-CC-BY-SA-4.0.txt",
"sha256": "28a9529c7d0bb4dc51f4bf5c116a3d16ef247a052f7591466768ddf563fd1cf5"
},
{
"size": 2265,
"path": "dictionaries/README.md",
"size": 2230,
"sha256": "2df17fe4e17d527c67ab57269b07dce59a49c1fb128c429a1408decbb47109ec"
"sha256": "3017bf44d3be9d9dfab21bd6778aa52b7947e61acf9ce2bc86b41d6e949ac311"
},
{
"path": "dictionaries/ru.txt",
"size": 1060364,
"path": "dictionaries/ru.txt",
"sha256": "9ef922c7699569304a428f6aba0fd13a21341c0d0cb9561f37ef83c41577a28b"
},
{
"size": 1280,
"path": "dictionaries/sources.json",
"size": 1279,
"sha256": "d6e11a3aaba22a8a7eaba19f778d8a5bd66653ff306810e85a1b0e7fff3a6b86"
"sha256": "98e5b3fe7304e37705c9e5ff48b0b399ccb16e806736d21f09921b99e5f2a408"
},
{
"size": 940799,
"path": "dictionaries/uk.txt",
"size": 898248,
"sha256": "caeb097749d4afc84b68ad96b3d7dfb6a6569561cd32ccce0bee94a13b43ba86"
"sha256": "d30e990d6ec2983c04f3644a3c61c6c668e8c542323f5931916fdd55b916eebf"
},
{
"path": "tools/README.txt",
"size": 993,
"path": "tools/README.txt",
"sha256": "a34b5161a8315af037e1ec71d816bfc688f7c364141d4ee2347cf0515ef0c82a"
},
{
"path": "tools/StayHere.exe",
"size": 134656,
"path": "tools/StayHere.exe",
"sha256": "6ef5cf64708d62b7fc63c3c793cc99188a513433ff4774cae01dc014f6664376"
},
{
"path": "tools/StayHere-README.md",
"size": 2796,
"path": "tools/StayHere-README.md",
"sha256": "ba214e2aca7405e698b3ab21ceb1f41ce088edd996b3e30e4a9d58ff496f9413"
}
],
"schema": 1
]
}
+3 -3
View File
@@ -9,8 +9,8 @@ IDC_SCREENSHOT_PENCIL CURSOR "icons/lucide/pencil.cur"
1 RT_MANIFEST "app.manifest"
201 RCDATA "update.ps1"
1 VERSIONINFO
FILEVERSION 0,6,77,0
PRODUCTVERSION 0,6,77,0
FILEVERSION 0,6,78,0
PRODUCTVERSION 0,6,78,0
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
BEGIN
@@ -20,7 +20,7 @@ BEGIN
BEGIN
VALUE "FileDescription", "KSwitcher — native keyboard and clipboard utility"
VALUE "ProductName", "KSwitcher"
VALUE "FileVersion", "0.6.77"
VALUE "FileVersion", "0.6.78"
END
END
BLOCK "VarFileInfo"
+6 -2
View File
@@ -29,11 +29,15 @@ void setOptionHistoryKeys(HWND dialog,const std::array<WORD,2> &keys)
SendDlgItemMessageW(dialog,323,HKM_SETHOTKEY,keys[1],0);
}
void loadCommandHistory()
void loadCommandHistoryKeys()
{
const std::array<WORD,2> keys{static_cast<WORD>(preference(L"PreviousCommandKey",defaultHistoryKeys[0])),
static_cast<WORD>(preference(L"CommandHistoryKey",defaultHistoryKeys[1]))};
if(validHistoryKeys(keys)) commandHistoryKeys=keys;
commandHistoryKeys=validHistoryKeys(keys)?keys:defaultHistoryKeys;
}
void loadCommandHistory()
{
DWORD bytes{};
if(RegGetValueW(HKEY_CURRENT_USER,schemeKey,L"CommandHistory",RRF_RT_REG_BINARY,nullptr,nullptr,&bytes)
+3
View File
@@ -139,6 +139,7 @@ INT_PTR CALLBACK folderShortcutEditDialog(HWND dialog,UINT message,WPARAM wp,LPA
return TRUE;
}
folderShortcuts=std::move(updated);
notifyFilesPreferences(GetAncestor(dialog,GA_ROOTOWNER));
finishFilesDialog(dialog,IDOK);
return TRUE;
}
@@ -362,6 +363,7 @@ INT_PTR CALLBACK quickFolderDialog(HWND dialog,UINT message,WPARAM wp,LPARAM lp)
else
{
folderShortcuts=std::move(updated);
notifyFilesPreferences(GetAncestor(dialog,GA_ROOTOWNER));
layoutQuickFolders(dialog,*view,static_cast<int>(target));
}
return TRUE;
@@ -383,6 +385,7 @@ INT_PTR CALLBACK quickFolderDialog(HWND dialog,UINT message,WPARAM wp,LPARAM lp)
return TRUE;
}
folderShortcuts=std::move(updated);
notifyFilesPreferences(GetAncestor(dialog,GA_ROOTOWNER));
if(folderShortcuts[view->digit].empty()) finishFilesDialog(dialog,IDCANCEL);
else layoutQuickFolders(dialog,*view,static_cast<int>(row));
return TRUE;
+50 -23
View File
@@ -364,6 +364,13 @@ DWORD preference(const wchar_t *name, DWORD fallback)
== ERROR_SUCCESS ? value : fallback;
}
const UINT filesPreferencesChanged=RegisterWindowMessageW(L"KSwitcher.Files.PreferencesChanged");
void notifyFilesPreferences(HWND source)
{
SendNotifyMessageW(HWND_BROADCAST,filesPreferencesChanged,reinterpret_cast<WPARAM>(source),0);
}
void savePreference(const wchar_t *name, DWORD value)
{
RegSetKeyValueW(HKEY_CURRENT_USER,schemeKey,name,REG_DWORD,&value,sizeof(value));
@@ -393,6 +400,7 @@ void setMode(int index, bool wide)
{
panels[index].wide=wide;
savePreference(index ? L"RightWide" : L"LeftWide",wide);
notifyFilesPreferences(GetParent(panels[index].list));
layout(GetParent(panels[index].list));
InvalidateRect(panels[index].list,nullptr,TRUE);
showFileDetails(panels[active]);
@@ -3144,6 +3152,35 @@ LRESULT CALLBACK panelKeys(HWND window, UINT message, WPARAM wp, LPARAM lp, UINT
#include "files_folder_shortcuts.inl"
#include "files_command_history_dialog.inl"
bool loadFilesPreferences(HWND window)
{
LOGFONTW font{};
DWORD bytes=sizeof(font);
if(RegGetValueW(HKEY_CURRENT_USER,schemeKey,L"DisplayFont",RRF_RT_REG_BINARY,nullptr,&font,&bytes)
!=ERROR_SUCCESS || bytes!=sizeof(font))
{
font=defaultFilesFont();
}
font.lfFaceName[LF_FACESIZE-1]=0;
if(!applyFont(window,font,static_cast<int>(std::clamp(preference(L"FontPoints",defaultFontPoints),80UL,240UL)))) return false;
loadColors();
dialogFramePadding={
std::min(preference(dialogFrameOuterKey,defaultDialogFramePadding.outer),maxDialogFramePadding),
std::min(preference(dialogFrameInnerKey,defaultDialogFramePadding.inner),maxDialogFramePadding),
std::min(preference(dialogRowTextKey,defaultDialogFramePadding.rowText),maxDialogRowTextPadding)};
loadFileStyles();
loadFolderShortcuts();
panels[0].wide=preference(L"LeftWide",defaultWide)!=0;
panels[1].wide=preference(L"RightWide",defaultWide)!=0;
sizeWidth=static_cast<int>(std::clamp(preference(L"SizeWidth",defaultSizeWidth),6UL,16UL));
alignExtensions=preference(L"AlignExtensions",defaultAlignExtensions)!=0;
showDetails=preference(L"ShowDetails",defaultShowDetails)!=0;
alignFolders=preference(L"AlignFolders",defaultAlignFolders)!=0;
statusFields=preference(L"StatusFields",defaultStatusFields)&15;
loadCommandHistoryKeys();
return true;
}
#include "files_options.inl"
void openMenu(HWND window, int index)
@@ -3261,6 +3298,18 @@ bool handleFilesMenuKey(HWND window,UINT message,WPARAM key,LPARAM flags,bool mo
LRESULT CALLBACK filesWindow(HWND window, UINT message, WPARAM wp, LPARAM lp)
{
if(message==filesPreferencesChanged)
{
if(reinterpret_cast<HWND>(wp)!=window)
{
loadFilesPreferences(window);
layout(window);
layoutOpenCommandHistory();
showFileDetails(panels[active]);
RedrawWindow(window,nullptr,nullptr,RDW_INVALIDATE|RDW_ALLCHILDREN);
}
return 0;
}
switch (message)
{
case WM_ACTIVATEAPP:
@@ -3297,29 +3346,7 @@ LRESULT CALLBACK filesWindow(HWND window, UINT message, WPARAM wp, LPARAM lp)
case WM_CREATE:
{
auto instance = GetModuleHandleW(nullptr);
LOGFONTW font{};
DWORD bytes=sizeof(font);
if(RegGetValueW(HKEY_CURRENT_USER,schemeKey,L"DisplayFont",RRF_RT_REG_BINARY,nullptr,&font,&bytes)
!=ERROR_SUCCESS || bytes!=sizeof(font))
{
font=defaultFilesFont();
}
font.lfFaceName[LF_FACESIZE-1]=0;
if(!applyFont(window,font,static_cast<int>(std::clamp(preference(L"FontPoints",defaultFontPoints),80UL,240UL)))) return -1;
loadColors();
dialogFramePadding={
std::min(preference(dialogFrameOuterKey,defaultDialogFramePadding.outer),maxDialogFramePadding),
std::min(preference(dialogFrameInnerKey,defaultDialogFramePadding.inner),maxDialogFramePadding),
std::min(preference(dialogRowTextKey,defaultDialogFramePadding.rowText),maxDialogRowTextPadding)};
loadFileStyles();
loadFolderShortcuts();
panels[0].wide=preference(L"LeftWide",defaultWide)!=0;
panels[1].wide=preference(L"RightWide",defaultWide)!=0;
sizeWidth=static_cast<int>(std::clamp(preference(L"SizeWidth",defaultSizeWidth),6UL,16UL));
alignExtensions=preference(L"AlignExtensions",defaultAlignExtensions)!=0;
showDetails=preference(L"ShowDetails",defaultShowDetails)!=0;
alignFolders=preference(L"AlignFolders",defaultAlignFolders)!=0;
statusFields=preference(L"StatusFields",defaultStatusFields)&15;
if(!loadFilesPreferences(window)) return -1;
menuBar=CreateWindowW(L"BUTTON",L"",WS_CHILD|WS_CLIPSIBLINGS|BS_OWNERDRAW,
0,0,0,0,window,reinterpret_cast<HMENU>(120),instance,nullptr);
const wchar_t *menus[]{L"Left",L"Files",L"Commands",L"Options",L"Right"};
+100 -45
View File
@@ -52,8 +52,22 @@ void resetPanelProperty(HWND dialog,const PanelProperty &property)
else CheckDlgButton(dialog,property.control,property.defaultValue);
}
struct OptionsBaseline
{
LOGFONTW font=displayFont;
int points=fontPoints;
DialogFramePadding padding=dialogFramePadding;
std::array<COLORREF,ColorCount> palette=colors;
std::vector<FileStyle> styles=fileStyles;
std::array<WORD,2> keys=commandHistoryKeys;
DWORD width=static_cast<DWORD>(sizeWidth), fields=statusFields;
bool extensions=alignExtensions, folders=alignFolders, details=showDetails;
std::array<bool,2> wide{panels[0].wide,panels[1].wide};
};
struct OptionsDraft
{
OptionsBaseline baseline;
LOGFONTW font=displayFont;
int points=fontPoints;
DialogFramePadding framePadding=dialogFramePadding;
@@ -81,15 +95,28 @@ struct OptionsDraft
bool optionsFontChanged(const OptionsDraft &draft)
{
auto pending=draft.font, applied=displayFont;
auto pending=draft.font, applied=draft.baseline.font;
// Height follows the selected point size and DPI. applyFont always uses natural width.
pending.lfHeight=applied.lfHeight=0;
pending.lfWidth=applied.lfWidth=0;
return draft.points!=fontPoints ||
return draft.points!=draft.baseline.points ||
memcmp(&pending,&applied,offsetof(LOGFONTW,lfFaceName))!=0 ||
_wcsicmp(pending.lfFaceName,applied.lfFaceName)!=0;
}
struct OptionsWriteLock
{
HANDLE mutex=CreateMutexW(nullptr,FALSE,L"Local\\KSwitcher.Files.OptionsWrite");
DWORD result=mutex?WaitForSingleObject(mutex,2000):WAIT_FAILED;
bool acquired() const { return result==WAIT_OBJECT_0 || result==WAIT_ABANDONED; }
~OptionsWriteLock()
{
if(acquired()) ReleaseMutex(mutex);
if(mutex) CloseHandle(mutex);
}
};
void updateOptionsApply(HWND dialog,const OptionsDraft &draft)
{
BOOL valid{};
@@ -97,12 +124,13 @@ void updateOptionsApply(HWND dialog,const OptionsDraft &draft)
const auto checked=[&](int id){return IsDlgButtonChecked(dialog,id)==BST_CHECKED;};
DWORD fields=0;
for(int i=0;i<4;++i) if(checked(205+i)) fields|=1u<<i;
const bool dirty=!valid || width!=static_cast<UINT>(sizeWidth) ||
checked(273)!=panels[0].wide || checked(274)!=panels[1].wide ||
checked(202)!=alignExtensions || checked(204)!=alignFolders || checked(203)!=showDetails ||
fields!=statusFields || draft.palette!=colors || draft.styles!=fileStyles ||
draft.framePadding!=dialogFramePadding || optionsFontChanged(draft) ||
optionHistoryKeys(dialog)!=commandHistoryKeys;
const auto &base=draft.baseline;
const bool dirty=!valid || width!=base.width ||
checked(273)!=base.wide[0] || checked(274)!=base.wide[1] ||
checked(202)!=base.extensions || checked(204)!=base.folders || checked(203)!=base.details ||
fields!=base.fields || draft.palette!=base.palette || draft.styles!=base.styles ||
draft.framePadding!=base.padding || optionsFontChanged(draft) ||
optionHistoryKeys(dialog)!=base.keys;
EnableWindow(GetDlgItem(dialog,optionsApply),dirty);
InvalidateRect(GetDlgItem(dialog,fileStylePreview),nullptr,FALSE);
}
@@ -521,14 +549,31 @@ INT_PTR CALLBACK optionsDialog(HWND dialog,UINT message,WPARAM wp,LPARAM lp)
SendDlgItemMessageW(dialog,201,EM_SETSEL,0,-1);
return TRUE;
}
const auto keys=optionHistoryKeys(dialog);
const auto owner=GetWindow(dialog,GW_OWNER);
const OptionsWriteLock writeLock;
if(!writeLock.acquired())
{
setStatus(L"Another window is saving Files settings. Try Apply again.");
return TRUE;
}
const auto &base=draft->baseline;
auto keys=optionHistoryKeys(dialog);
loadCommandHistoryKeys();
for(size_t i=0;i<keys.size();++i)
if(keys[i]==base.keys[i]) keys[i]=commandHistoryKeys[i];
if(!validHistoryKeys(keys))
{
MessageBoxW(dialog,L"Choose distinct shortcuts using Ctrl or Alt that are free in Files.",L"Command history",MB_OK|MB_ICONWARNING);
return TRUE;
}
const auto owner=GetWindow(dialog,GW_OWNER);
const bool stylesChanged=draft->styles!=fileStyles;
const bool stylesChanged=draft->styles!=base.styles;
loadFileStyles();
if(stylesChanged && fileStyles!=base.styles && fileStyles!=draft->styles)
{
MessageBoxW(dialog,L"File type styles changed in another window. Reopen Options before editing them again.",
L"KSwitcher Files Options",MB_OK|MB_ICONWARNING);
return TRUE;
}
if(stylesChanged && !saveFileStyles(draft->styles))
{
MessageBoxW(dialog,L"Could not save the file type styles.",L"KSwitcher Files Options",MB_OK|MB_ICONWARNING);
@@ -541,47 +586,57 @@ INT_PTR CALLBACK optionsDialog(HWND dialog,UINT message,WPARAM wp,LPARAM lp)
MessageBoxW(dialog,L"Could not apply the selected font.",optionsTitles[Appearance],MB_OK|MB_ICONWARNING);
return TRUE;
}
commandHistoryKeys=keys;
savePreference(L"PreviousCommandKey",keys[0]);
savePreference(L"CommandHistoryKey",keys[1]);
if(stylesChanged) fileStyles=draft->styles;
sizeWidth=static_cast<int>(width);
alignExtensions=IsDlgButtonChecked(dialog,202)==BST_CHECKED;
showDetails=IsDlgButtonChecked(dialog,203)==BST_CHECKED;
alignFolders=IsDlgButtonChecked(dialog,204)==BST_CHECKED;
statusFields=0;
for(int i=0;i<4;++i)
if(IsDlgButtonChecked(dialog,205+i)==BST_CHECKED) statusFields|=1u<<i;
savePreference(L"SizeWidth",sizeWidth);
savePreference(L"AlignExtensions",alignExtensions);
savePreference(L"ShowDetails",showDetails);
savePreference(L"AlignFolders",alignFolders);
savePreference(L"StatusFields",statusFields);
for(int i=0;i<ColorCount;++i)
if(colors[i]!=draft->palette[i])
{
colors[i]=draft->palette[i];
savePreference(std::to_wstring(i).c_str(),colors[i]);
}
refreshColors();
if(draft->framePadding!=dialogFramePadding)
const auto saveChanged=[](const wchar_t *name,DWORD value,DWORD initial)
{
dialogFramePadding=draft->framePadding;
savePreference(dialogFrameOuterKey,dialogFramePadding.outer);
savePreference(dialogFrameInnerKey,dialogFramePadding.inner);
savePreference(dialogRowTextKey,dialogFramePadding.rowText);
if(value!=initial) savePreference(name,value);
};
const auto checked=[&](int id){return IsDlgButtonChecked(dialog,id)==BST_CHECKED;};
const auto inputKeys=optionHistoryKeys(dialog);
saveChanged(L"PreviousCommandKey",inputKeys[0],base.keys[0]);
saveChanged(L"CommandHistoryKey",inputKeys[1],base.keys[1]);
saveChanged(L"SizeWidth",width,base.width);
saveChanged(L"AlignExtensions",checked(202),base.extensions);
saveChanged(L"AlignFolders",checked(204),base.folders);
saveChanged(L"ShowDetails",checked(203),base.details);
DWORD fields=preference(L"StatusFields",defaultStatusFields)&15;
const auto initialFields=fields;
for(int i=0;i<4;++i)
{
const DWORD bit=1u<<i;
if(checked(205+i)!=((base.fields&bit)!=0)) fields=checked(205+i)?fields|bit:fields&~bit;
}
saveChanged(L"StatusFields",fields,initialFields);
for(int i=0;i<ColorCount;++i)
saveChanged(std::to_wstring(i).c_str(),draft->palette[i],base.palette[i]);
saveChanged(dialogFrameOuterKey,draft->framePadding.outer,base.padding.outer);
saveChanged(dialogFrameInnerKey,draft->framePadding.inner,base.padding.inner);
saveChanged(dialogRowTextKey,draft->framePadding.rowText,base.padding.rowText);
if(fontChanged)
{
savePreference(L"FontPoints",fontPoints);
RegSetKeyValueW(HKEY_CURRENT_USER,schemeKey,L"DisplayFont",REG_BINARY,&displayFont,sizeof(displayFont));
draft->font=displayFont;
}
for(int i=0;i<2;++i)
{
const bool wide=IsDlgButtonChecked(dialog,273+i)==BST_CHECKED;
if(panels[i].wide!=wide) setMode(i,wide);
}
saveChanged(L"LeftWide",checked(273),base.wide[0]);
saveChanged(L"RightWide",checked(274),base.wide[1]);
loadFilesPreferences(owner);
notifyFilesPreferences(owner);
draft->baseline=OptionsBaseline{};
draft->font=displayFont;
draft->points=fontPoints;
draft->styles=fileStyles;
draft->palette=colors;
draft->framePadding=dialogFramePadding;
SetDlgItemInt(dialog,201,sizeWidth,FALSE);
CheckDlgButton(dialog,202,alignExtensions);
CheckDlgButton(dialog,203,showDetails);
CheckDlgButton(dialog,204,alignFolders);
CheckDlgButton(dialog,273,panels[0].wide);
CheckDlgButton(dialog,274,panels[1].wide);
for(int i=0;i<4;++i) CheckDlgButton(dialog,205+i,(statusFields>>i)&1u);
setOptionHistoryKeys(dialog,commandHistoryKeys);
if(draft->page==PanelColors && draft->section==fileStyleSection)
updateFileStyleEditor(dialog,*draft,true);
showOptionsPage(dialog,*draft,draft->page,draft->section);
layout(owner);
showFileDetails(panels[active]);
RedrawWindow(owner,nullptr,nullptr,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN|RDW_UPDATENOW);
+3 -1
View File
@@ -1514,7 +1514,9 @@ Settings collectSettings(HWND w, SettingsView *v)
s.undo = value(w, 213);
s.clipboard = value(w, 214);
s.screenshot = value(w, 215);
s.filesHotkey = value(w, 216);
auto filesHotkey = value(w, 216);
if (s.filesHotkey || !filesHotkey.empty())
s.filesHotkey = std::move(filesHotkey);
s.maxItems = integer(w, 240);
s.maxMiB = integer(w, 241);
s.maxImageMiB = integer(w, 242);
+1 -1
View File
@@ -2,7 +2,7 @@
#include "platform.h"
namespace ks
{
inline constexpr wchar_t AppVersion[] = L"0.6.77";
inline constexpr wchar_t AppVersion[] = L"0.6.78";
inline constexpr UINT UpdateMessage = WM_APP + 7;
inline constexpr UINT UpdateCheckIntervalMs = 6 * 60 * 60 * 1000;
inline constexpr UINT UpdateNotificationRetryMs = 5 * 60 * 1000;