winemenubuilder: Provide depth to the menus created.

This commit is contained in:
Bill Medland 2005-12-19 21:25:52 +01:00 committed by Alexandre Julliard
parent 68df918282
commit d5739ed88f
2 changed files with 71 additions and 36 deletions

View File

@ -5,6 +5,7 @@
* Copyright 1998 Juergen Schmied * Copyright 1998 Juergen Schmied
* Copyright 2003 Mike McCormack for CodeWeavers * Copyright 2003 Mike McCormack for CodeWeavers
* Copyright 2004 Dmitry Timoshkov * Copyright 2004 Dmitry Timoshkov
* Copyright 2005 Bill Medland
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -21,6 +22,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* *
* This program is used to replicate the Windows desktop and start menu
* into the native desktop's copies. Desktop entries are merged directly
* into the native desktop. The Windows Start Menu corresponds to a Wine
* entry within the native "start" menu and replicates the whole tree
* structure of the Windows Start Menu. Currently it does not differentiate
* between the user's desktop/start menu and the "All Users" copies.
*
* This program will read a Windows shortcut file using the IShellLink * This program will read a Windows shortcut file using the IShellLink
* interface, then invoke wineshelllink with the appropriate arguments * interface, then invoke wineshelllink with the appropriate arguments
* to create a KDE/Gnome menu entry for the shortcut. * to create a KDE/Gnome menu entry for the shortcut.
@ -28,10 +36,21 @@
* winemenubuilder [ -r ] <shortcut.lnk> * winemenubuilder [ -r ] <shortcut.lnk>
* *
* If the -r parameter is passed, and the shortcut cannot be created, * If the -r parameter is passed, and the shortcut cannot be created,
* this program will add RunOnce entry to invoke itself at the next * this program will add a RunOnce entry to invoke itself at the next
* reboot. This covers the case when a ShortCut is created before the * reboot. This covers the case when a ShortCut is created before the
* executable containing its icon. * executable containing its icon.
* *
* TODO
* Handle data lnk files. There is no icon in the file; the icon is in
* the handler for the file type (or pointed to by the lnk file). Also it
* might be better to use a native handler (e.g. a native acroread for pdf
* files).
* Differentiate between the user's entries and the "All Users" entries.
* If it is possible to add the desktop files to the native system's
* shared location for an "All Users" entry then do so. As a suggestion the
* shared menu Wine base could be writable to the wine group, or a wineadm
* group.
*
*/ */
#include "config.h" #include "config.h"
@ -650,32 +669,46 @@ static int fork_and_wait( const char *linker, const char *link_name, const char
return retcode; return retcode;
} }
static char *cleanup_link( LPCWSTR link ) /* Return a heap-allocated copy of the unix format difference between the two
* Windows-format paths.
* locn is the owning location
* link is within locn
*/
static char *relative_path( LPCWSTR link, LPCWSTR locn )
{ {
char *unix_file_name; char *unix_locn, *unix_link;
char *p, *link_name; char *relative = NULL;
unix_file_name = wine_get_unix_file_name(link); unix_locn = wine_get_unix_file_name(locn);
if (!unix_file_name) unix_link = wine_get_unix_file_name(link);
if (unix_locn && unix_link)
{ {
WINE_ERR("target link %s not found\n", wine_dbgstr_w(link)); size_t len_unix_locn, len_unix_link;
return NULL; len_unix_locn = strlen (unix_locn);
len_unix_link = strlen (unix_link);
if (len_unix_locn < len_unix_link && memcmp (unix_locn, unix_link, len_unix_locn) == 0 && unix_link[len_unix_locn] == '/')
{
size_t len_rel;
char *p = strrchr (unix_link + len_unix_locn, '/');
p = strrchr (p, '.');
if (p)
{
*p = '\0';
len_unix_link = p - unix_link;
}
len_rel = len_unix_link - len_unix_locn;
relative = HeapAlloc(GetProcessHeap(), 0, len_rel);
if (relative)
{
memcpy (relative, unix_link + len_unix_locn + 1, len_rel);
}
}
} }
if (!relative)
link_name = unix_file_name; WINE_WARN("Could not separate the relative link path of %s in %s\n", wine_dbgstr_w(link), wine_dbgstr_w(locn));
p = strrchr( link_name, '/' ); HeapFree(GetProcessHeap(), 0, unix_locn);
if (p) HeapFree(GetProcessHeap(), 0, unix_link);
link_name = p + 1; return relative;
p = strrchr( link_name, '.' );
if (p)
*p = 0;
p = HeapAlloc(GetProcessHeap(), 0, strlen(link_name) + 1);
strcpy(p, link_name);
HeapFree(GetProcessHeap(), 0, unix_file_name);
return p;
} }
/*********************************************************************** /***********************************************************************
@ -683,9 +716,11 @@ static char *cleanup_link( LPCWSTR link )
* GetLinkLocation * GetLinkLocation
* *
* returns TRUE if successful * returns TRUE if successful
* *loc will contain CS_DESKTOPDIRECTORY, CS_STARTMENU, CS_STARTUP * *loc will contain CS_DESKTOPDIRECTORY, CS_STARTMENU, CS_STARTUP etc.
* *relative will contain the address of a heap-allocated copy of the portion
* of the filename that is within the specified location, in unix form
*/ */
static BOOL GetLinkLocation( LPCWSTR linkfile, DWORD *loc ) static BOOL GetLinkLocation( LPCWSTR linkfile, DWORD *loc, char **relative )
{ {
WCHAR filename[MAX_PATH], buffer[MAX_PATH]; WCHAR filename[MAX_PATH], buffer[MAX_PATH];
DWORD len, i, r, filelen; DWORD len, i, r, filelen;
@ -708,7 +743,7 @@ static BOOL GetLinkLocation( LPCWSTR linkfile, DWORD *loc )
len = lstrlenW(buffer); len = lstrlenW(buffer);
if (len >= MAX_PATH) if (len >= MAX_PATH)
continue; continue; /* We've just trashed memory! Hopefully we are OK */
if (len > filelen || filename[len]!='\\') if (len > filelen || filename[len]!='\\')
continue; continue;
@ -721,7 +756,8 @@ static BOOL GetLinkLocation( LPCWSTR linkfile, DWORD *loc )
/* return the remainder of the string and link type */ /* return the remainder of the string and link type */
*loc = locations[i]; *loc = locations[i];
return TRUE; *relative = relative_path (filename, buffer);
return (*relative != NULL);
} }
return FALSE; return FALSE;
@ -856,7 +892,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain )
return FALSE; return FALSE;
} }
if( !GetLinkLocation( link, &csidl ) ) if( !GetLinkLocation( link, &csidl, &link_name ) )
{ {
WINE_WARN("Unknown link location '%s'. Ignoring.\n",wine_dbgstr_w(link)); WINE_WARN("Unknown link location '%s'. Ignoring.\n",wine_dbgstr_w(link));
return TRUE; return TRUE;
@ -866,6 +902,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain )
WINE_WARN("Not under desktop or start menu. Ignoring.\n"); WINE_WARN("Not under desktop or start menu. Ignoring.\n");
return TRUE; return TRUE;
} }
WINE_TRACE("Link : %s\n", wine_dbgstr_a(link_name));
szWorkDir[0] = 0; szWorkDir[0] = 0;
IShellLinkW_GetWorkingDirectory( sl, szWorkDir, MAX_PATH ); IShellLinkW_GetWorkingDirectory( sl, szWorkDir, MAX_PATH );
@ -935,13 +972,6 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain )
lstrcatW(szPath, startW); lstrcatW(szPath, startW);
} }
link_name = cleanup_link( link );
if( !link_name )
{
WINE_ERR("Couldn't clean up link name %s\n", wine_dbgstr_w(link));
goto cleanup;
}
/* escape the path and parameters */ /* escape the path and parameters */
escaped_path = escape(szPath); escaped_path = escape(szPath);
escaped_args = escape(szArgs); escaped_args = escape(szArgs);

View File

@ -20,6 +20,11 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# #
# Note that the link is a relative unix-style path name. Since the / character
# is not valid in Windows filenames it is an adequate separator to show the
# menu structure. (This program may need to split the menu structure out for
# implementing xdg-style menus)
mode="" mode=""
args="" args=""
menu="" menu=""
@ -38,7 +43,7 @@ options:
--desktop create a desktop link --desktop create a desktop link
--menu create a menu entry --menu create a menu entry
--path xx path to the application --path xx path to the application
--link xx name of link to create --link xx name of link to create, including path
--args xx command-line arguments for the application --args xx command-line arguments for the application
--icon xx icon to display --icon xx icon to display
--workdir xx working directory for the application --workdir xx working directory for the application