Add depth to native desktop menus

Bill Medland billmedland at mercuryspeed.com
Wed Dec 14 20:25:43 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 02:05:26 -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 02:02:57 -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
@@ -28,7 +29,7 @@
  *  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.
  *
@@ -650,32 +651,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 +698,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 +725,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 +738,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 +874,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 +884,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 +954,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);
--- /dev/null 2005-12-09 07:39:41.851395336 -0800
+++ wine/programs/winemenubuilder/design.txt 2005-12-14 16:47:33.000000000 -0800
@@ -0,0 +1,16 @@
+This documents the aims of the integration between Wine and the native desktop.
+
+Overview
+--------
+
+The aim is to sit the apparent Windows desktop and menu under the native desktop as tidily as possible.  Since Wine is running within the native system the Wine menu sits under the main desktop menu, rather than merged into it. However the desktop is merged into the native desktop.
+We aim to support submenus within the "Start Menu".
+The system basically runs off the winemenubuilder program which currently parses an existing lnk file from the "Windows" file system and requests the wineshelllink program to create corresponding native entries.
+
+Issues
+------
+
+The many ways that the menus are handled, including RedHat complications etc.
+Desktops that actually have multiple "menus".
+The lnk may point to data rather than a program.  It may be better to handle that data natively rather than through wine (e.g there are usually native processors of pdf files).
+What to do about lnks in "shared locations" such as "All Users" mapping to shared menus between multiple native desktop users etc.



More information about the wine-patches mailing list