Add depth to native desktop menus (reformatted)

Bill Medland billmedland at mercuryspeed.com
Thu Dec 15 09:11:45 CST 2005


Bill Medland (billmedland at mercuryspeed.com)
Upgrade winemenubuilder to provide depth to the menus created.

Index: wine/tools/wineshelllink
===================================================================
RCS file: /home/wine/wine/tools/wineshelllink,v
retrieving revision 1.19
diff -u -r1.19 wineshelllink
--- wine/tools/wineshelllink 9 May 2005 09:28:05 -0000 1.19
+++ wine/tools/wineshelllink 15 Dec 2005 15:00:39 -0000
@@ -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 @@
   --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
Index: wine/programs/winemenubuilder/winemenubuilder.c
===================================================================
RCS file: /home/wine/wine/programs/winemenubuilder/winemenubuilder.c,v
retrieving revision 1.37
diff -u -r1.37 winemenubuilder.c
--- wine/programs/winemenubuilder/winemenubuilder.c 10 Nov 2005 11:36:26 -0000 1.37
+++ wine/programs/winemenubuilder/winemenubuilder.c 15 Dec 2005 15:01:52 -0000
@@ -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 ] <shortcut.lnk>
  *
  *  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 @@
     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)
-    {
-        WINE_ERR("target link %s not found\n", wine_dbgstr_w(link));
-        return NULL;
+    unix_locn = wine_get_unix_file_name(locn);
+    unix_link = wine_get_unix_file_name(link);
+    if (unix_locn && unix_link)
+    {
+        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 @@
  *           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 @@
 
         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 @@
 
         /* 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 @@
         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 @@
         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 @@
         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);



More information about the wine-patches mailing list