View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001835 | Double Commander | Logic | public | 2017-05-14 15:28 | 2019-12-22 19:57 |
Reporter | CryHam | Assigned To | |||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | new | Resolution | open | ||
Projection | none | ETA | none | ||
Product Version | 1.0.0 (trunk) | ||||
Summary | 0001835: Make Ctrl - (Left,Right or Up) follow links to destination. | ||||
Description | I have many of links to executables, source, project files etc. Normally in Total Commander I can also go to the file in destination. E.g. with Ctrl-Left opening directory and focusing cursor on target on left side view, with Ctrl-Up it will do the same on new tab. Currently in DC links to files do nothing, just open another view with current directory. Those keys work only for symbolic links to directories (which appear as normal [directories] in view). They don't work for shortcuts (*.lnk files) and don't work for symbolic links to files (should open the containing directory and best if also put cursor on target file). | ||||
Tags | No tags attached. | ||||
Attached Files | lnk.patch (6,454 bytes)
Index: src/platform/win/umywindows.pas =================================================================== --- src/platform/win/umywindows.pas (revision 8763) +++ src/platform/win/umywindows.pas (working copy) @@ -137,6 +137,10 @@ } procedure CreateShortcut(const Target, Shortcut: String); {en + Extracts target full file path from windows shortcut file (.lnk) +} +function GetShortcutTarget(const ShortcutFilename: string): string; +{en Extract file attributes from find data record. Removes reparse point attribute if a reparse point tag is not a name surrogate. @param(FindData Find data record from FindFirstFile/FindNextFile function.) @@ -860,6 +864,26 @@ OleCheckUTF8(IPFile.Save(PWideChar(LinkName), False)); end; +function GetShortcutTarget(const ShortcutFilename: string): string; +var + Psl: IShellLink; + Ppf: IPersistFile; + WideName: array[0..MAX_PATH] of WideChar; + pResult: array[0..MAX_PATH-1] of ansiChar; + Data: TWin32FindData; +const + IID_IPersistFile: TGUID = ( + D1:$0000010B; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46)); +begin + CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IID_IShellLinkA, psl); + psl.QueryInterface(IID_IPersistFile, ppf); + MultiByteToWideChar(CP_ACP, 0, pAnsiChar(ShortcutFilename), -1, WideName, Max_Path); + ppf.Load(WideName, STGM_READ); + psl.Resolve(0, SLR_ANY_MATCH); + psl.GetPath(@pResult, MAX_PATH, Data, SLGP_UNCPRIORITY); + Result := StrPas(pResult); +end; + function ExtractFileAttributes(const FindData: TWin32FindDataW): DWORD; inline; begin // If a reparse point tag is not a name surrogate then remove reparse point attribute Index: src/uglobs.pas =================================================================== --- src/uglobs.pas (revision 8763) +++ src/uglobs.pas (working copy) @@ -1018,6 +1018,7 @@ AddIfNotExists(['Alt+Right'],[],'cm_ViewHistoryNext'); AddIfNotExists(['Alt+Shift+Enter'],[],'cm_CountDirContent'); AddIfNotExists(['Alt+Shift+F9'],[],'cm_TestArchive'); + AddIfNotExists(['Ctrl+Shift+S'],[],'cm_CreateShortcut'); AddIfNotExists([ 'Alt+1','','index=1','', 'Alt+2','','index=2','', Index: src/umaincommands.pas =================================================================== --- src/umaincommands.pas (revision 8763) +++ src/umaincommands.pas (working copy) @@ -27,8 +27,9 @@ interface uses - Classes, SysUtils, ActnList, uFileView, uFileViewNotebook, uFileSourceOperation, - uGlobs, uFileFunctions, uFormCommands, uFileSorting, uShellContextMenu, Menus, ufavoritetabs,ufile; + Classes, SysUtils, ActnList, uFileView, uFileViewNotebook, uFileSourceOperation, uTypes, + uGlobs, uFileFunctions, uFormCommands, uFileSorting, + uShellContextMenu, Menus, ufavoritetabs, ufile, uMyWindows; type @@ -295,6 +296,7 @@ procedure cm_RightSortBySize(const Params: array of string); procedure cm_RightSortByAttr(const Params: array of string); procedure cm_SymLink(const Params: array of string); + procedure cm_CreateShortcut(const {%H-}Params: array of string); procedure cm_CopySamePanel(const Params: array of string); procedure cm_DirHistory(const Params: array of string); procedure cm_ViewHistory(const Params: array of string); @@ -832,10 +834,24 @@ begin // Change file source, if the file under cursor can be opened as another file source. try + if LowerCase(aFile.Extension) = 'lnk' then + begin + NewPath := GetShortcutTarget(aFile.FullPath); + if mbDirectoryExists(NewPath) then + ChooseFileSource(TargetPage.FileView, NewPath) + else // file + begin + ChooseFileSource(TargetPage.FileView, ExtractFilePath(NewPath)); + TargetPage.FileView.SetActiveFile(NewPath); + end; + end + else + begin if not ChooseFileSource(TargetPage.FileView, SourcePage.FileView.FileSource, aFile) then TargetPage.FileView.AddFileSource(SourcePage.FileView.FileSource, SourcePage.FileView.CurrentPath); TargetPage.FileView.SetActiveFile(aFile.Name); + end; except on e: EFileSourceException do MessageDlg('Error', e.Message, mtError, [mbOK], 0); @@ -1158,6 +1174,7 @@ var aFile: TFile; NewPage: TFileViewPage; + NewPath: string; begin aFile := FrmMain.ActiveFrame.CloneActiveFile; if not Assigned(aFile) then @@ -1170,6 +1187,17 @@ else if FileIsArchive(aFile.FullPath) then NewPage := OpenArchive(aFile) else + if LowerCase(aFile.Extension) = 'lnk' then + begin + NewPath := GetShortcutTarget(aFile.FullPath); + if mbDirectoryExists(NewPath) then + NewPage := OpenTab(NewPath) + else // file + begin + NewPage := OpenTab(ExtractFilePath(NewPath)); + NewPage.FileView.SetActiveFile(NewPath); + end; + end else NewPage := OpenTab(aFile.Path); finally FreeAndNil(aFile); @@ -3290,6 +3318,49 @@ end; end; +procedure TMainCommands.cm_CreateShortcut(const Params: array of string); +var + sExistingFile, sLinkToCreate: String; + SelectedFiles: TFiles; +begin + with frmMain do + begin + // Shortcut links work only for file system. + if not (ActiveFrame.FileSource.IsClass(TFileSystemFileSource)) then + begin + msgWarning(rsMsgErrNotSupported); + Exit; + end; + + SelectedFiles := ActiveFrame.CloneSelectedOrActiveFiles; + try + if SelectedFiles.Count > 1 then + msgWarning(rsMsgTooManyFilesSelected) + else if SelectedFiles.Count = 0 then + msgWarning(rsMsgNoFilesSelected) + else + begin + sExistingFile := SelectedFiles[0].Path + SelectedFiles[0].Name; + + if Length(Params) > 0 then + sLinkToCreate := Params[0] + else + sLinkToCreate := ActiveFrame.CurrentPath; + + sLinkToCreate := sLinkToCreate + SelectedFiles[0].Name; + try + CreateShortcut(sExistingFile, sLinkToCreate); + finally + ActiveFrame.Reload; + end; + end; + + finally + FreeAndNil(SelectedFiles); + end; + end; +end; + // Uses to change sort direction when columns header is disabled procedure TMainCommands.cm_ReverseOrder(const Params: array of string); begin | ||||
Fixed in Revision | |||||
Operating system | Windows | ||||
Widgetset | Win32 | ||||
Architecture | 64-bit | ||||
|
Wow, I just implemented this. I needed the function GetShortcutTarget from here: http://forum.lazarus.freepascal.org/index.php?topic=1709.0 There is an issue still, it works only for paths with just ansi chars. Probably something bad in this line: MultiByteToWideChar(CP_ACP, 0, pAnsiChar(ShortcutFilename), -1, WideName, Max_Path); or maybe the whole function, not sure. I also BTW added cm_CreateShortcut, that makes .lnk to file/dir under cursor. Probably only useful on Windows. Patch is based on svn rev 8763. I only tested this on Windows 7. |
|
DC already has function FileIsLinkToFolder that has correct Unicode implementation. It can be changed to work with files too or used as template. Create shortcut command already exists in "Files" menu. |
|
(Tested on Ubuntu 18.04.3 LTS) The current version DC 0.9.6 behaves like Total Commander when using Ctrl-Left/Right with files and folders, which is a good idea IMO. (If we tab over there, the same file/folder gets the cursor position, which again matches TC.) But DC treats links to folders just like links to files: make the other pane identical to the current pane (and position the cursor). IMO using Ctrl-Left/Right on a link to a folder should go into the folder in the other pane like using Enter. To go to the "cd -P" equivalent I suggest making the Symlink info in the properties dialog (marked in blue in the attachment) a clickable link and jumping to that destination when we click onto it. (Actually for linked files the same should be possible.) |
Date Modified | Username | Field | Change |
---|---|---|---|
2017-05-14 15:28 | CryHam | New Issue | |
2019-03-30 23:55 | CryHam | File Added: lnk.patch | |
2019-03-30 23:58 | CryHam | Note Added: 0003121 | |
2019-03-30 23:58 | CryHam | Note Edited: 0003121 | |
2019-03-30 23:59 | CryHam | Note Edited: 0003121 | |
2019-03-31 00:23 | Alexx2000 | Note Added: 0003123 | |
2019-12-22 19:56 | w2017 | Note Added: 0003357 | |
2019-12-22 19:57 | w2017 | File Added: 2019-12-22 properties of link to dir.png |