winemenubuilder: Moved all wineshelllink functionality to winemenubuilder and removed wineshelllink.

This commit is contained in:
Damjan Jovanovic 2008-11-11 21:39:56 +02:00 committed by Alexandre Julliard
parent 45d7897c62
commit 4e2cec5aba
3 changed files with 180 additions and 277 deletions

View File

@ -12,10 +12,4 @@ C_SRCS = \
@MAKE_PROG_RULES@
install install-lib:: $(DESTDIR)$(bindir)
$(INSTALL_SCRIPT) $(TOPSRCDIR)/tools/wineshelllink $(DESTDIR)$(bindir)/wineshelllink
uninstall::
$(RM) $(DESTDIR)$(bindir)/wineshelllink
@DEPENDENCIES@ # everything below this line is overwritten by make depend

View File

@ -31,8 +31,7 @@
* 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.
* interface, then create a KDE/Gnome menu entry for the shortcut.
*
* winemenubuilder [ -w ] <shortcut.lnk>
*
@ -817,6 +816,184 @@ static BOOL write_desktop_entry(const char *location, const char *linkname, cons
return TRUE;
}
static BOOL write_directory_entry(const char *directory, const char *location)
{
FILE *file;
WINE_TRACE("(%s,%s)\n", wine_dbgstr_a(directory), wine_dbgstr_a(location));
file = fopen(location, "w");
if (file == NULL)
return FALSE;
fprintf(file, "[Desktop Entry]\n");
fprintf(file, "Type=Directory\n");
if (strcmp(directory, "wine") == 0)
{
fprintf(file, "Name=Wine\n");
fprintf(file, "Icon=wine\n");
}
else
{
fprintf(file, "Name=%s\n", directory);
fprintf(file, "Icon=folder\n");
}
fclose(file);
return TRUE;
}
static BOOL write_menu_file(const char *filename)
{
char *tempfilename;
FILE *tempfile = NULL;
char *lastEntry;
char *name = NULL;
char *menuPath = NULL;
int i;
int count = 0;
BOOL ret = FALSE;
WINE_TRACE("(%s)\n", wine_dbgstr_a(filename));
while (1)
{
tempfilename = tempnam(xdg_config_dir, "_wine");
if (tempfilename)
{
int tempfd = open(tempfilename, O_EXCL | O_CREAT | O_WRONLY, 0666);
if (tempfd >= 0)
{
tempfile = fdopen(tempfd, "w");
if (tempfile)
break;
close(tempfd);
goto end;
}
else if (errno == EEXIST)
{
free(tempfilename);
continue;
}
free(tempfilename);
}
return FALSE;
}
fprintf(tempfile, "<!DOCTYPE Menu PUBLIC \"-//freedesktop//DTD Menu 1.0//EN\"\n");
fprintf(tempfile, "\"http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd\">\n");
fprintf(tempfile, "<Menu>\n");
fprintf(tempfile, " <Name>Applications</Name>\n");
name = HeapAlloc(GetProcessHeap(), 0, lstrlenA(filename) + 1);
if (name == NULL) goto end;
lastEntry = name;
for (i = 0; filename[i]; i++)
{
name[i] = filename[i];
if (filename[i] == '/')
{
char *dir_file_name;
struct stat st;
name[i] = 0;
fprintf(tempfile, " <Menu>\n");
fprintf(tempfile, " <Name>%s%s</Name>\n", count ? "" : "wine-", name);
fprintf(tempfile, " <Directory>%s%s.directory</Directory>\n", count ? "" : "wine-", name);
dir_file_name = heap_printf("%s/desktop-directories/%s%s.directory",
xdg_data_dir, count ? "" : "wine-", name);
if (dir_file_name)
{
if (stat(dir_file_name, &st) != 0 && errno == ENOENT)
write_directory_entry(lastEntry, dir_file_name);
HeapFree(GetProcessHeap(), 0, dir_file_name);
}
name[i] = '-';
lastEntry = &name[i+1];
++count;
}
}
name[i] = 0;
fprintf(tempfile, " <Include>\n");
fprintf(tempfile, " <Filename>%s</Filename>\n", name);
fprintf(tempfile, " </Include>\n");
for (i = 0; i < count; i++)
fprintf(tempfile, " </Menu>\n");
fprintf(tempfile, "</Menu>\n");
menuPath = heap_printf("%s/%s", xdg_config_dir, name);
if (menuPath == NULL) goto end;
strcpy(menuPath + strlen(menuPath) - strlen(".desktop"), ".menu");
ret = TRUE;
end:
if (tempfile)
fclose(tempfile);
if (ret)
ret = (rename(tempfilename, menuPath) == 0);
if (!ret && tempfilename)
remove(tempfilename);
free(tempfilename);
HeapFree(GetProcessHeap(), 0, name);
HeapFree(GetProcessHeap(), 0, menuPath);
return ret;
}
static BOOL write_menu_entry(const char *link, const char *path, const char *args,
const char *descr, const char *workdir, const char *icon)
{
const char *linkname;
char *desktopPath = NULL;
char *desktopDir;
char *filename = NULL;
BOOL ret = TRUE;
WINE_TRACE("(%s, %s, %s, %s, %s, %s)\n", wine_dbgstr_a(link), wine_dbgstr_a(path),
wine_dbgstr_a(args), wine_dbgstr_a(descr), wine_dbgstr_a(workdir),
wine_dbgstr_a(icon));
linkname = strrchr(link, '/');
if (linkname == NULL)
linkname = link;
else
++linkname;
desktopPath = heap_printf("%s/applications/wine/%s.desktop", xdg_data_dir, link);
if (!desktopPath)
{
WINE_WARN("out of memory creating menu entry\n");
ret = FALSE;
goto end;
}
desktopDir = strrchr(desktopPath, '/');
*desktopDir = 0;
if (!create_directories(desktopPath))
{
WINE_WARN("couldn't make parent directories for %s\n", wine_dbgstr_a(desktopPath));
ret = FALSE;
goto end;
}
*desktopDir = '/';
if (!write_desktop_entry(desktopPath, linkname, path, args, descr, workdir, icon))
{
WINE_WARN("couldn't make desktop entry %s\n", wine_dbgstr_a(desktopPath));
ret = FALSE;
goto end;
}
filename = heap_printf("wine/%s.desktop", link);
if (!filename || !write_menu_file(filename))
{
WINE_WARN("couldn't make menu file %s\n", wine_dbgstr_a(filename));
ret = FALSE;
}
end:
HeapFree(GetProcessHeap(), 0, desktopPath);
HeapFree(GetProcessHeap(), 0, filename);
return ret;
}
/* This escapes \ in filenames */
static LPSTR escape(LPCWSTR arg)
{
@ -848,53 +1025,6 @@ static LPSTR escape(LPCWSTR arg)
return narg;
}
static int fork_and_wait( const char *linker, const char *link_name, const char *path,
int desktop, const char *args, const char *icon_name,
const char *workdir, const char *description )
{
int pos = 0;
const char *argv[20];
int retcode;
WINE_TRACE( "linker app='%s' link='%s' mode=%s "
"path='%s' args='%s' icon='%s' workdir='%s' descr='%s'\n",
linker, link_name, desktop ? "desktop" : "menu",
path, args, icon_name, workdir, description );
argv[pos++] = linker ;
argv[pos++] = "--link";
argv[pos++] = link_name;
argv[pos++] = "--path";
argv[pos++] = path;
argv[pos++] = desktop ? "--desktop" : "--menu";
if (args && strlen(args))
{
argv[pos++] = "--args";
argv[pos++] = args;
}
if (icon_name)
{
argv[pos++] = "--icon";
argv[pos++] = icon_name;
}
if (workdir && strlen(workdir))
{
argv[pos++] = "--workdir";
argv[pos++] = workdir;
}
if (description && strlen(description))
{
argv[pos++] = "--descr";
argv[pos++] = description;
}
argv[pos] = NULL;
retcode=spawnvp( _P_WAIT, linker, argv );
if (retcode!=0)
WINE_ERR("%s returned %d\n",linker,retcode);
return retcode;
}
/* Return a heap-allocated copy of the unix format difference between the two
* Windows-format paths.
* locn is the owning location
@ -1260,9 +1390,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
}
}
else
r = fork_and_wait("wineshelllink", link_name, escaped_path,
0, escaped_args, icon_name,
work_dir ? work_dir : "", escaped_description);
r = !write_menu_entry(link_name, escaped_path, escaped_args, escaped_description, work_dir, icon_name);
ReleaseSemaphore( hsem, 1, NULL );

View File

@ -1,219 +0,0 @@
#!/bin/sh
#
# Create menu/desktop entries for an application
# This is used by the IShellLink interface
#
# Copyright 2000 Alexandre Julliard
# Copyright 2006 Vitaliy Margolen
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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.
mode=""
args=""
menu=""
icon=""
descr=""
link=""
path=""
workdir=""
usage()
{
cat <<EOF
usage: wineshelllink options
options:
--desktop create a desktop link
--menu create a menu entry
--path xx path to the application
--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
--descr xx application description
EOF
exit 2
}
if [ $# -eq 0 ] ; then
usage
fi
while [ $# -gt 0 ]
do
case "$1" in
--desktop) mode="desktop"; shift 1 ;;
--menu) mode="menu"; shift 1 ;;
--path) path="$2"; shift 2 ;;
--link) link="$2"; shift 2 ;;
--args) args="$2"; shift 2 ;;
--icon) icon="$2"; shift 2 ;;
--descr) descr="$2"; shift 2 ;;
--workdir) workdir="$2"; shift 2 ;;
*) usage ;;
esac
done
if [ -z "$mode" ] ; then
echo "Either --desktop or --menu required"
usage
fi
if [ -z "$link" ] ; then
echo "You must specify a link name with --link"
usage
fi
desktop_entry()
{
cat <<EOF
[Desktop Entry]
Name=$linkname
Exec=env WINEPREFIX="${WINEPREFIX:-$HOME/.wine}" wine "$path" $args
Type=Application
StartupWMClass=Wine
EOF
[ -z "$descr" ] || echo "Comment=$descr"
[ -z "$workdir" ] || echo "Path=$workdir"
[ -z "$icon" ] || echo "Icon=$icon"
}
directory_entry()
{
cat <<EOF
[Desktop Entry]
Type=Directory
EOF
if [ "$1" = "wine" ] ; then
echo "Name=Wine"
echo "Icon=wine"
else
echo "Name=$1"
echo "Icon=folder"
fi
}
# XDG
xdg_config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/menus/applications-merged"
xdg_data_dir="${XDG_DATA_HOME:-$HOME/.local/share}"
# Create common directories
mkdir -p "$xdg_config_dir"
mkdir -p "$xdg_data_dir/desktop-directories"
get_menu_entries()
{
tmp="$xdg_config_dir/$1.menu"
if [ -r "$tmp" ] ; then
awk '
BEGIN { RS="<" }
/^Filename/ {
RSTART=index($0,">")
if (RSTART>0) {
print substr($0,RSTART+1)
}
}' $tmp
fi
}
# Input
# menu file name
# new item
write_menu_file()
{
menu=`echo "$1" | sed 's!/!-!g'`
filename=`echo "$2" | sed 's!/!-!g'`
tmpfile=`mktemp /tmp/wine.XXXXXX`
(
echo '<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"'
echo '"http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">'
echo '<Menu>'
echo ' <Name>Applications</Name>'
IFS="/"
fullname='wine'
for i in $1; do
echo " <Menu>"
echo " <Name>$fullname-$i</Name>"
echo " <Directory>$fullname-$i.directory</Directory>"
dir_file_name="$xdg_data_dir/desktop-directories/$fullname-$i.directory"
if [ ! -f "$dir_file_name" ] ; then
directory_entry "$i" > "$dir_file_name"
fi
test "$i" = "wine" || fullname="$fullname-$i"
done
echo " <Include>"
IFS="
"
for i in `get_menu_entries "$menu"`
do
test "$i" = "$filename" && continue
echo " <Filename>$i</Filename>"
done
# New record
echo " <Filename>$filename</Filename>"
echo " </Include>"
IFS='/'
for i in $1; do
echo " </Menu>"
done
echo '</Menu>'
) > $tmpfile
chmod 0600 $tmpfile
mv -f $tmpfile "$xdg_config_dir/$menu.menu"
}
linkname=`basename "$link"`
if [ $mode = "menu" ] ; then
mkdir -p "$xdg_data_dir/applications/wine/`dirname "$link"`"
linkpath=`dirname "$link"`
if [ "$linkpath" = "." ] ; then
linkpath=""
else
linkpath="/$linkpath"
fi
desktop_entry > "$xdg_data_dir/applications/wine/$link.desktop"
write_menu_file "wine$linkpath" "wine$linkpath/$linkname.desktop"
else
if [ -d "$HOME/Desktop" ]
then
desktop_target="$HOME/Desktop/$linkname.desktop"
else
desktop_target="$HOME/$linkname.desktop"
fi
desktop_entry > "$desktop_target"
fi
exit 0