From d5739ed88f916b53325a16fa08bf62990ff149bf Mon Sep 17 00:00:00 2001 From: Bill Medland Date: Mon, 19 Dec 2005 21:25:52 +0100 Subject: [PATCH] winemenubuilder: Provide depth to the menus created. --- programs/winemenubuilder/winemenubuilder.c | 100 +++++++++++++-------- tools/wineshelllink | 7 +- 2 files changed, 71 insertions(+), 36 deletions(-) diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index 589b2086611..38231426360 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -5,6 +5,7 @@ * Copyright 1998 Juergen Schmied * Copyright 2003 Mike McCormack for CodeWeavers * Copyright 2004 Dmitry Timoshkov + * Copyright 2005 Bill Medland * * This library is free software; you can redistribute it and/or * 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 * * + * 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 * interface, then invoke wineshelllink with the appropriate arguments * to create a KDE/Gnome menu entry for the shortcut. @@ -28,10 +36,21 @@ * winemenubuilder [ -r ] * * 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 * 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" @@ -650,32 +669,46 @@ static int fork_and_wait( const char *linker, const char *link_name, const char 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 *p, *link_name; + char *unix_locn, *unix_link; + char *relative = NULL; - unix_file_name = wine_get_unix_file_name(link); - if (!unix_file_name) + unix_locn = wine_get_unix_file_name(locn); + 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)); - return NULL; + size_t len_unix_locn, len_unix_link; + 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); + } + } } - - link_name = unix_file_name; - p = strrchr( link_name, '/' ); - if (p) - link_name = p + 1; - - 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; + if (!relative) + WINE_WARN("Could not separate the relative link path of %s in %s\n", wine_dbgstr_w(link), wine_dbgstr_w(locn)); + HeapFree(GetProcessHeap(), 0, unix_locn); + HeapFree(GetProcessHeap(), 0, unix_link); + return relative; } /*********************************************************************** @@ -683,9 +716,11 @@ static char *cleanup_link( LPCWSTR link ) * GetLinkLocation * * 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]; DWORD len, i, r, filelen; @@ -708,7 +743,7 @@ static BOOL GetLinkLocation( LPCWSTR linkfile, DWORD *loc ) len = lstrlenW(buffer); if (len >= MAX_PATH) - continue; + continue; /* We've just trashed memory! Hopefully we are OK */ if (len > filelen || filename[len]!='\\') continue; @@ -721,7 +756,8 @@ static BOOL GetLinkLocation( LPCWSTR linkfile, DWORD *loc ) /* return the remainder of the string and link type */ *loc = locations[i]; - return TRUE; + *relative = relative_path (filename, buffer); + return (*relative != NULL); } return FALSE; @@ -856,7 +892,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain ) return FALSE; } - if( !GetLinkLocation( link, &csidl ) ) + if( !GetLinkLocation( link, &csidl, &link_name ) ) { WINE_WARN("Unknown link location '%s'. Ignoring.\n",wine_dbgstr_w(link)); 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"); return TRUE; } + WINE_TRACE("Link : %s\n", wine_dbgstr_a(link_name)); szWorkDir[0] = 0; IShellLinkW_GetWorkingDirectory( sl, szWorkDir, MAX_PATH ); @@ -935,13 +972,6 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain ) 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 */ escaped_path = escape(szPath); escaped_args = escape(szArgs); diff --git a/tools/wineshelllink b/tools/wineshelllink index 722ede02b98..10fa80ba716 100755 --- a/tools/wineshelllink +++ b/tools/wineshelllink @@ -20,6 +20,11 @@ # 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="" args="" menu="" @@ -38,7 +43,7 @@ options: --desktop create a desktop link --menu create a menu entry --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 --icon xx icon to display --workdir xx working directory for the application