[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: 21.x feature request: windows shortcut support
From: |
Steve Kemp |
Subject: |
Re: 21.x feature request: windows shortcut support |
Date: |
10 Oct 2001 03:49:56 -0700 |
rms@gnu.org (Richard Stallman) wrote:
> Support for non-GNU-like systems is low priority for us. If you want
> to implement this, we will probably merge it in, if a Windows
> maintainer likes the code.
I actually put together some code to do this a while back - its
something I've been meaning to post for a while, to gnu.emacs.sources
/ gnu.emacs.bugs.
Anyway, below is a patch to implement `w32-resolve-shortcut',
usage is something like this:
(setq target (w32-resolve-shortcut "d:/t.lnk"))
Once you have this function the resolving of files on loading
becomes trivial.
The patch is a bit longer than I like, because the inclusion of
a Windows header file needed for the definitions of IShellLink, etc,
caused conficts over the names of some enum members, so I had to
rename them.
Context diff follows.
(The code could be improved, but is functional, and handles
errors appropriately).
Steve
---
# GNU Stuff on Windows.
http://GNUSoftware.com/
diff --recursive --context emacs-20.7-orig/src/makefile.nt
emacs-20.7/src/makefile.nt
*** emacs-20.7-orig/src/makefile.nt Wed Oct 10 09:20:33 2001
--- emacs-20.7/src/makefile.nt Wed Oct 10 10:33:10 2001
***************
*** 174,179 ****
--- 174,180 ----
user32.lib \
mpr.lib \
shell32.lib \
+ ole32.lib \
setargv.obj
#
diff --recursive --context emacs-20.7-orig/src/w32fns.c
emacs-20.7/src/w32fns.c
*** emacs-20.7-orig/src/w32fns.c Wed Oct 10 09:20:36 2001
--- emacs-20.7/src/w32fns.c Wed Oct 10 10:39:27 2001
***************
*** 44,49 ****
--- 44,51 ----
#include <commdlg.h>
#include <shellapi.h>
+ #include <windows.h>
+ #include <shlobj.h>
extern void abort ();
extern void free_frame_menubar ();
***************
*** 2653,2659 ****
/* Types we might convert a resource string into. */
enum resource_types
{
! number, boolean, string, symbol
};
/* Return the value of parameter PARAM.
--- 2655,2661 ----
/* Types we might convert a resource string into. */
enum resource_types
{
! w32_number, w32_boolean, w32_string, w32_symbol
};
/* Return the value of parameter PARAM.
***************
*** 2693,2702 ****
switch (type)
{
! case number:
return make_number (atoi (XSTRING (tem)->data));
! case boolean:
tem = Fdowncase (tem);
if (!strcmp (XSTRING (tem)->data, "on")
|| !strcmp (XSTRING (tem)->data, "true"))
--- 2695,2704 ----
switch (type)
{
! case w32_number:
return make_number (atoi (XSTRING (tem)->data));
! case w32_boolean:
tem = Fdowncase (tem);
if (!strcmp (XSTRING (tem)->data, "on")
|| !strcmp (XSTRING (tem)->data, "true"))
***************
*** 2704,2713 ****
else
return Qnil;
! case string:
return tem;
! case symbol:
/* As a special case, we map the values `true' and `on'
to Qt, and `false' and `off' to Qnil. */
{
--- 2706,2715 ----
else
return Qnil;
! case w32_string:
return tem;
! case w32_symbol:
/* As a special case, we map the values `true' and `on'
to Qt, and `false' and `off' to Qnil. */
{
***************
*** 2840,2848 ****
f->output_data.w32->top_pos = 0;
f->output_data.w32->left_pos = 0;
! tem0 = x_get_arg (parms, Qheight, 0, 0, number);
! tem1 = x_get_arg (parms, Qwidth, 0, 0, number);
! tem2 = x_get_arg (parms, Quser_size, 0, 0, number);
if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
{
if (!EQ (tem0, Qunbound))
--- 2842,2850 ----
f->output_data.w32->top_pos = 0;
f->output_data.w32->left_pos = 0;
! tem0 = x_get_arg (parms, Qheight, 0, 0, w32_number);
! tem1 = x_get_arg (parms, Qwidth, 0, 0, w32_number);
! tem2 = x_get_arg (parms, Quser_size, 0, 0, w32_number);
if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
{
if (!EQ (tem0, Qunbound))
***************
*** 2870,2878 ****
f->output_data.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f,
f->width);
f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f,
f->height);
! tem0 = x_get_arg (parms, Qtop, 0, 0, number);
! tem1 = x_get_arg (parms, Qleft, 0, 0, number);
! tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
{
if (EQ (tem0, Qminus))
--- 2872,2880 ----
f->output_data.w32->pixel_width = CHAR_TO_PIXEL_WIDTH (f,
f->width);
f->output_data.w32->pixel_height = CHAR_TO_PIXEL_HEIGHT (f,
f->height);
! tem0 = x_get_arg (parms, Qtop, 0, 0, w32_number);
! tem1 = x_get_arg (parms, Qleft, 0, 0, w32_number);
! tem2 = x_get_arg (parms, Quser_position, 0, 0, w32_number);
if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
{
if (EQ (tem0, Qminus))
***************
*** 4670,4677 ****
/* Set the position of the icon. Note that Windows 95 groups all
icons in the tray. */
! icon_x = x_get_arg (parms, Qicon_left, 0, 0, number);
! icon_y = x_get_arg (parms, Qicon_top, 0, 0, number);
if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
{
CHECK_NUMBER (icon_x, 0);
--- 4672,4679 ----
/* Set the position of the icon. Note that Windows 95 groups all
icons in the tray. */
! icon_x = x_get_arg (parms, Qicon_left, 0, 0, w32_number);
! icon_y = x_get_arg (parms, Qicon_top, 0, 0, w32_number);
if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
{
CHECK_NUMBER (icon_x, 0);
***************
*** 4688,4694 ****
#if 0 /* TODO */
/* Start up iconic or window? */
x_wm_set_window_state
! (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, symbol), Qicon)
? IconicState
: NormalState));
--- 4690,4696 ----
#if 0 /* TODO */
/* Start up iconic or window? */
x_wm_set_window_state
! (f, (EQ (x_get_arg (parms, Qvisibility, 0, 0, w32_symbol),
Qicon)
? IconicState
: NormalState));
***************
*** 4733,4739 ****
until we know if this frame has a specified name. */
Vx_resource_name = Vinvocation_name;
! display = x_get_arg (parms, Qdisplay, 0, 0, string);
if (EQ (display, Qunbound))
display = Qnil;
dpyinfo = check_x_display_info (display);
--- 4735,4741 ----
until we know if this frame has a specified name. */
Vx_resource_name = Vinvocation_name;
! display = x_get_arg (parms, Qdisplay, 0, 0, w32_string);
if (EQ (display, Qunbound))
display = Qnil;
dpyinfo = check_x_display_info (display);
***************
*** 4743,4749 ****
kb = &the_only_kboard;
#endif
! name = x_get_arg (parms, Qname, "name", "Name", string);
if (!STRINGP (name)
&& ! EQ (name, Qunbound)
&& ! NILP (name))
--- 4745,4751 ----
kb = &the_only_kboard;
#endif
! name = x_get_arg (parms, Qname, "name", "Name", w32_string);
if (!STRINGP (name)
&& ! EQ (name, Qunbound)
&& ! NILP (name))
***************
*** 4753,4759 ****
Vx_resource_name = name;
/* See if parent window is specified. */
! parent = x_get_arg (parms, Qparent_id, NULL, NULL, number);
if (EQ (parent, Qunbound))
parent = Qnil;
if (! NILP (parent))
--- 4755,4761 ----
Vx_resource_name = name;
/* See if parent window is specified. */
! parent = x_get_arg (parms, Qparent_id, NULL, NULL, w32_number);
if (EQ (parent, Qunbound))
parent = Qnil;
if (! NILP (parent))
***************
*** 4764,4770 ****
it to make_frame_without_minibuffer. */
frame = Qnil;
GCPRO4 (parms, parent, name, frame);
! tem = x_get_arg (parms, Qminibuffer, 0, 0, symbol);
if (EQ (tem, Qnone) || NILP (tem))
f = make_frame_without_minibuffer (Qnil, kb, display);
else if (EQ (tem, Qonly))
--- 4766,4772 ----
it to make_frame_without_minibuffer. */
frame = Qnil;
GCPRO4 (parms, parent, name, frame);
! tem = x_get_arg (parms, Qminibuffer, 0, 0, w32_symbol);
if (EQ (tem, Qnone) || NILP (tem))
f = make_frame_without_minibuffer (Qnil, kb, display);
else if (EQ (tem, Qonly))
***************
*** 4791,4797 ****
FRAME_FONTSET (f) = -1;
f->icon_name
! = x_get_arg (parms, Qicon_name, "iconName", "Title", string);
if (! STRINGP (f->icon_name))
f->icon_name = Qnil;
--- 4793,4799 ----
FRAME_FONTSET (f) = -1;
f->icon_name
! = x_get_arg (parms, Qicon_name, "iconName", "Title",
w32_string);
if (! STRINGP (f->icon_name))
f->icon_name = Qnil;
***************
*** 4840,4846 ****
{
Lisp_Object font;
! font = x_get_arg (parms, Qfont, "font", "Font", string);
BLOCK_INPUT;
/* First, try whatever font the caller has specified. */
if (STRINGP (font))
--- 4842,4848 ----
{
Lisp_Object font;
! font = x_get_arg (parms, Qfont, "font", "Font", w32_string);
BLOCK_INPUT;
/* First, try whatever font the caller has specified. */
if (STRINGP (font))
***************
*** 4864,4874 ****
font = build_string ("Fixedsys");
x_default_parameter (f, parms, Qfont, font,
! "font", "Font", string);
}
x_default_parameter (f, parms, Qborder_width, make_number (2),
! "borderwidth", "BorderWidth", number);
/* This defaults to 2 in order to match xterm. We recognize
either
internalBorderWidth or internalBorder (which is what xterm
calls
it). */
--- 4866,4876 ----
font = build_string ("Fixedsys");
x_default_parameter (f, parms, Qfont, font,
! "font", "Font", w32_string);
}
x_default_parameter (f, parms, Qborder_width, make_number (2),
! "borderwidth", "BorderWidth", w32_number);
/* This defaults to 2 in order to match xterm. We recognize
either
internalBorderWidth or internalBorder (which is what xterm
calls
it). */
***************
*** 4877,4913 ****
Lisp_Object value;
value = x_get_arg (parms, Qinternal_border_width,
! "internalBorder", "BorderWidth", number);
if (! EQ (value, Qunbound))
parms = Fcons (Fcons (Qinternal_border_width, value),
parms);
}
/* Default internalBorderWidth to 0 on Windows to match other
programs. */
x_default_parameter (f, parms, Qinternal_border_width, make_number
(0),
! "internalBorderWidth", "BorderWidth", number);
x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
! "verticalScrollBars", "ScrollBars", boolean);
/* Also do the stuff which must be set before the window exists.
*/
x_default_parameter (f, parms, Qforeground_color, build_string
("black"),
! "foreground", "Foreground", string);
x_default_parameter (f, parms, Qbackground_color, build_string
("white"),
! "background", "Background", string);
x_default_parameter (f, parms, Qmouse_color, build_string
("black"),
! "pointerColor", "Foreground", string);
x_default_parameter (f, parms, Qcursor_color, build_string
("black"),
! "cursorColor", "Foreground", string);
x_default_parameter (f, parms, Qborder_color, build_string
("black"),
! "borderColor", "BorderColor", string);
x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
! "menuBar", "MenuBar", number);
x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
! "scrollBarWidth", "ScrollBarWidth", number);
x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
! "bufferPredicate", "BufferPredicate", symbol);
x_default_parameter (f, parms, Qtitle, Qnil,
! "title", "Title", string);
f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO
(f)->root_window;
--- 4879,4915 ----
Lisp_Object value;
value = x_get_arg (parms, Qinternal_border_width,
! "internalBorder", "BorderWidth", w32_number);
if (! EQ (value, Qunbound))
parms = Fcons (Fcons (Qinternal_border_width, value),
parms);
}
/* Default internalBorderWidth to 0 on Windows to match other
programs. */
x_default_parameter (f, parms, Qinternal_border_width, make_number
(0),
! "internalBorderWidth", "BorderWidth", w32_number);
x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
! "verticalScrollBars", "ScrollBars", w32_boolean);
/* Also do the stuff which must be set before the window exists.
*/
x_default_parameter (f, parms, Qforeground_color, build_string
("black"),
! "foreground", "Foreground", w32_string);
x_default_parameter (f, parms, Qbackground_color, build_string
("white"),
! "background", "Background", w32_string);
x_default_parameter (f, parms, Qmouse_color, build_string
("black"),
! "pointerColor", "Foreground", w32_string);
x_default_parameter (f, parms, Qcursor_color, build_string
("black"),
! "cursorColor", "Foreground", w32_string);
x_default_parameter (f, parms, Qborder_color, build_string
("black"),
! "borderColor", "BorderColor", w32_string);
x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
! "menuBar", "MenuBar", w32_number);
x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
! "scrollBarWidth", "ScrollBarWidth", w32_number);
x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
! "bufferPredicate", "BufferPredicate", w32_symbol);
x_default_parameter (f, parms, Qtitle, Qnil,
! "title", "Title", w32_string);
f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO
(f)->root_window;
***************
*** 4937,4950 ****
/* We need to do this after creating the window, so that the
icon-creation functions can say whose icon they're describing.
*/
x_default_parameter (f, parms, Qicon_type, Qnil,
! "bitmapIcon", "BitmapIcon", symbol);
x_default_parameter (f, parms, Qauto_raise, Qnil,
! "autoRaise", "AutoRaiseLower", boolean);
x_default_parameter (f, parms, Qauto_lower, Qnil,
! "autoLower", "AutoRaiseLower", boolean);
x_default_parameter (f, parms, Qcursor_type, Qbox,
! "cursorType", "CursorType", symbol);
/* Dimensions, especially f->height, must be done via
change_frame_size.
Change will not be effected unless different from the current
--- 4939,4952 ----
/* We need to do this after creating the window, so that the
icon-creation functions can say whose icon they're describing.
*/
x_default_parameter (f, parms, Qicon_type, Qnil,
! "bitmapIcon", "BitmapIcon", w32_symbol);
x_default_parameter (f, parms, Qauto_raise, Qnil,
! "autoRaise", "AutoRaiseLower", w32_boolean);
x_default_parameter (f, parms, Qauto_lower, Qnil,
! "autoLower", "AutoRaiseLower", w32_boolean);
x_default_parameter (f, parms, Qcursor_type, Qbox,
! "cursorType", "CursorType", w32_symbol);
/* Dimensions, especially f->height, must be done via
change_frame_size.
Change will not be effected unless different from the current
***************
*** 4961,4967 ****
x_wm_set_size_hint (f, window_prompting, 0);
UNBLOCK_INPUT;
! tem = x_get_arg (parms, Qunsplittable, 0, 0, boolean);
f->no_split = minibuffer_only || EQ (tem, Qt);
UNGCPRO;
--- 4963,4969 ----
x_wm_set_size_hint (f, window_prompting, 0);
UNBLOCK_INPUT;
! tem = x_get_arg (parms, Qunsplittable, 0, 0, w32_boolean);
f->no_split = minibuffer_only || EQ (tem, Qt);
UNGCPRO;
***************
*** 4983,4989 ****
{
Lisp_Object visibility;
! visibility = x_get_arg (parms, Qvisibility, 0, 0, symbol);
if (EQ (visibility, Qunbound))
visibility = Qt;
--- 4985,4991 ----
{
Lisp_Object visibility;
! visibility = x_get_arg (parms, Qvisibility, 0, 0, w32_symbol);
if (EQ (visibility, Qunbound))
visibility = Qt;
***************
*** 6983,6988 ****
--- 6985,7079 ----
/* These are the w32 specialized functions */
+ DEFUN ("w32-resolve-shortcut", Fw32_resolve_shortcut,
Sw32_resolve_shortcut, 0, 1, 0,
+ "Return the target of a Windows shortcut.\n\
+ Find, and return the target of a Windows shortcut file,\n\
+ returns nil on error.\n\
+ LINKFILE is the name of the link file to resolve.\n")
+ (linkfile)
+ Lisp_Object linkfile;
+ {
+ Lisp_Object target;
+ HRESULT hres;
+ IShellLink* psl;
+
+ char szGotPath[MAX_PATH];
+ WIN32_FIND_DATA wfd;
+
+ CoInitialize( NULL );
+
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(&CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER,
+ &IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,
&ppf);
+ if (SUCCEEDED(hres))
+ {
+ WORD wsz[MAX_PATH];
+
+ // Ensure string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, ((char *) XSTRING
(linkfile)->data), -1, wsz,
+ MAX_PATH);
+
+ // Load the shell link.
+ hres = ppf->lpVtbl->Load(ppf,wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ // Resolve the link.
+ hres = psl->lpVtbl->Resolve(psl,NULL,
SLR_ANY_MATCH);
+
+ if (SUCCEEDED(hres))
+ {
+ // Get the path to the link target.
+ hres = psl->lpVtbl->GetPath(psl, szGotPath,
MAX_PATH, (WIN32_FIND_DATA*)&wfd,
+ SLGP_UNCPRIORITY);
+ // Store the result.
+ target = build_string( szGotPath );
+ }
+ else
+ {
+ #ifdef _DEBUG_LNK_
+ error("Failed to resolve\n" );
+ #endif
+ return( Qnil );
+ }
+ // Release pointer to IPersistFile interface.
+ ppf->lpVtbl->Release(ppf);
+ }
+ else
+ {
+ #ifdef _DEBUG_LNK_
+ error("Failed to load\n" );
+ #endif
+ return Qnil;
+ }
+ // Release pointer to IShellLink interface.
+ psl->lpVtbl->Release(psl);
+ }
+ else
+ {
+ #ifdef _DEBUG_LNK_
+ error("Failed to query interface\n" );
+ #endif
+ return( Qnil );
+ }
+ }
+ else
+ {
+ #ifdef _DEBUG_LNK_
+ error("Failed to create object\n" );
+ #endif
+ return Qnil;
+ }
+
+ CoUninitialize();
+
+ return target;
+ }
DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 1,
0,
"This will display the W32 font dialog and return an X font
string corresponding to the selection.")
***************
*** 7632,7638 ****
defsubr (&Sx_synchronize);
/* W32 specific functions */
!
defsubr (&Sw32_focus_frame);
defsubr (&Sw32_select_font);
defsubr (&Sw32_define_rgb_color);
--- 7723,7729 ----
defsubr (&Sx_synchronize);
/* W32 specific functions */
! defsubr (&Sw32_resolve_shortcut);
defsubr (&Sw32_focus_frame);
defsubr (&Sw32_select_font);
defsubr (&Sw32_define_rgb_color);
- 21.x feature request: windows shortcut support, Jari Aalto+mail.emacs, 2001/10/04
- Re: 21.x feature request: windows shortcut support, Richard Stallman, 2001/10/05
- Re: 21.x feature request: windows shortcut support,
Steve Kemp <=
- Re: 21.x feature request: windows shortcut support, Jason Rumney, 2001/10/11
- Re: 21.x feature request: windows shortcut support, Eli Zaretskii, 2001/10/11
- Re: 21.x feature request: windows shortcut support, Jason Rumney, 2001/10/11
- Re: 21.x feature request: windows shortcut support, Eli Zaretskii, 2001/10/11
- Re: 21.x feature request: windows shortcut support, Richard Stallman, 2001/10/12
- Re: 21.x feature request: windows shortcut support, Jason Rumney, 2001/10/12
- Re: 21.x feature request: windows shortcut support, David Masterson, 2001/10/12