From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Sean O'Rourke" Newsgroups: gmane.emacs.devel Subject: [patch] enhanced mac drag-n-drop Date: Tue, 05 Apr 2005 17:53:00 -0700 Message-ID: NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: sea.gmane.org 1112748955 16161 80.91.229.2 (6 Apr 2005 00:55:55 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 6 Apr 2005 00:55:55 +0000 (UTC) Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Apr 06 02:55:52 2005 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1DIypG-00071q-6E for ged-emacs-devel@m.gmane.org; Wed, 06 Apr 2005 02:55:22 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DIyOG-0003Vr-38 for ged-emacs-devel@m.gmane.org; Tue, 05 Apr 2005 20:27:28 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1DIyNa-0003LK-3C for emacs-devel@gnu.org; Tue, 05 Apr 2005 20:26:47 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DIyNZ-0003Io-QY for emacs-devel@gnu.org; Tue, 05 Apr 2005 20:26:45 -0400 Original-Received: from [132.239.1.59] (helo=mailbox7.ucsd.edu) by monty-python.gnu.org with esmtp (TLS-1.0:DHE_RSA_3DES_EDE_CBC_SHA:24) (Exim 4.34) id 1DIynT-0006es-36 for emacs-devel@gnu.org; Tue, 05 Apr 2005 20:53:31 -0400 Original-Received: from smtp.ucsd.edu (smtp-a.ucsd.edu [132.239.1.49]) by mailbox7.ucsd.edu (8.13.3/8.13.3) with ESMTP id j360r9Rd084340 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 5 Apr 2005 17:53:10 -0700 (PDT) Original-Received: from Sean-ORourkes-Computer.local (80363334.dynamic.ucsd.edu [128.54.51.52]) by smtp.ucsd.edu (8.12.10/8.9.3) with ESMTP id j360r2Tg024424 for ; Tue, 5 Apr 2005 17:53:09 -0700 (PDT) Original-To: emacs-devel@gnu.org User-Agent: Gnus/5.110003 (No Gnus v0.3) Emacs/22.0.50 (darwin) X-Greylisting: NO DELAY (Trusted relay host); processed by UCSD_GL-v1.2 on mailbox7.ucsd.edu; Tue, 05 April 2005 17:53:10 -0700 (PDT) X-MailScanner: PASSED (v1.2.8 72239 j360r9Rd084340 mailbox7.ucsd.edu) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:35601 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:35601 --=-=-= The included patch to src/macterm.c extends Carbon Emacs' drag-n-drop to handle directories, URLs, and text. To use it, the included Lisp code also needs to be added to the appropriate Lisp file, probably lisp/term/mac-win.el. This is my first foray into Emacs C-hackery, so although it's been working for me for the last few days, I would appreciate some Mac users' trying it out. Thanks for your time, /s ps -- please Cc me on replies, as I'm not subscribed to emacs-devel. (defun mac-primary-dnd-function (event) "Perform the most common action for each type of item dropped onto Emacs on Mac OS X. Currently, this means: * File or directory -- call `find-file'. * URL -- call `browse-url-browser-function'. * Text -- insert text at point." (interactive "e") ;; Make sure the drop target has positive co-ords before setting the ;; selected frame - otherwise it won't work. (let* ((window (posn-window (event-start event))) (coords (posn-x-y (event-start event))) (x (car coords)) (y (cdr coords))) (if (and (> x 0) (> y 0)) (set-frame-selected-window nil window)) (mapcar (lambda (name) (case (car name) (text (insert (cdr name))) (url (funcall browse-url-browser-function (cdr name))) (file (setq name (cdr name)) (if (and (file-exists-p name) (not (string-match (image-file-name-regexp) name))) (find-file name) (insert name))))) (cadd event))) (raise-frame) (recenter)) (defun mac-secondary-dnd-function (event) "Perform a less common action for each type of item dropped onto Emacs on Mac OS X. Currently, this means: * File or directory -- insert pathname at point. * URL -- insert URL text at point. * Text -- if it is a file or directory name, edit that file; otherwise, insert text at point." (interactive "e") ;; Make sure the drop target has positive co-ords before setting the ;; selected frame - otherwise it won't work. (let* ((window (posn-window (event-start event))) (coords (posn-x-y (event-start event))) (x (car coords)) (y (cdr coords))) (if (and (> x 0) (> y 0)) (set-frame-selected-window nil window)) (mapcar (lambda (name) (case (car name) (text (setq name (cdr name)) (if (and (file-exists-p name) (not (string-match (image-file-name-regexp) name))) (find-file name) (insert name))) ((url file) (insert (cdr name))))) (caddr event))) (raise-frame) (recenter)) (global-set-key [drag-n-drop] 'mac-primary-dnd-function) (global-set-key [shift drag-n-drop] 'mac-secondary-dnd-function) --=-=-= Content-Type: text/x-patch Content-Disposition: attachment Index: macterm.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/macterm.c,v retrieving revision 1.106 diff -p -u -w -u -r1.106 macterm.c --- macterm.c 16 Mar 2005 08:08:06 -0000 1.106 +++ macterm.c 5 Apr 2005 20:23:29 -0000 @@ -7155,7 +7159,8 @@ int current_mac_keyboard_text_encoding = drag and drop events. */ Lisp_Object Qmac_ready_for_drag_n_drop; -Lisp_Object drag_and_drop_file_list; +/* List of objects for a pending drag-n-drop event. */ +Lisp_Object drag_and_drop_list; Point saved_menu_event_location; @@ -8078,10 +8083,10 @@ do_ae_open_documents(AppleEvent *message err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size); if (err == noErr) - drag_and_drop_file_list = Fcons (list3 (make_number (position.lineNum + 1), + drag_and_drop_list = Fcons (list3 (make_number (position.lineNum + 1), make_number (position.startRange + 1), make_number (position.endRange + 1)), - drag_and_drop_file_list); + drag_and_drop_list); /* Check to see that we got all of the required parameters from the event descriptor. For an 'odoc' event this should just be the @@ -8135,10 +8140,11 @@ do_ae_open_documents(AppleEvent *message sizeof (unix_path_name) - 1) == noErr) #endif /* x-dnd functions expect undecoded filenames. */ - drag_and_drop_file_list = - Fcons (make_unibyte_string (unix_path_name, - strlen (unix_path_name)), - drag_and_drop_file_list); + drag_and_drop_list = + Fcons (Fcons (intern("file"), + make_unibyte_string (unix_path_name, + strlen (unix_path_name))), + drag_and_drop_list); } } } @@ -8152,8 +8158,27 @@ descriptor_error_exit: return err; } - #if TARGET_API_MAC_CARBON + +static FlavorType +mac_favorite_flavor (DragReference theDrag, ItemReference theItem, + FlavorFlags* theFlags) +{ + const FlavorType accepted_flavors[] = { + flavorTypeHFS, + flavorTypeDirectory, + 'url ', + 'utxt', + 0 + }; + int j; + for (j = 0; accepted_flavors[j]; j++) + if (GetFlavorFlags (theDrag, theItem, accepted_flavors[j], &theFlags) + == noErr) + return accepted_flavors[j]; + return 0; +} + static pascal OSErr mac_do_track_drag (DragTrackingMessage message, WindowPtr window, void *handlerRefCon, DragReference theDrag) @@ -8176,8 +8201,7 @@ mac_do_track_drag (DragTrackingMessage m for (index = 1; index <= items; index++) { GetDragItemReferenceNumber (theDrag, index, &theItem); - result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags); - if (result == noErr) + if (mac_favorite_flavor (theDrag, theItem, &theFlags) != 0) { can_accept = 1; break; @@ -8231,28 +8255,33 @@ mac_do_receive_drag (WindowPtr window, v Point mouse; OSErr result; ItemReference theItem; - HFSFlavor data; - Size size = sizeof (HFSFlavor); if (GetFrontWindowOfClass (kMovableModalWindowClass, false)) return dragNotAcceptedErr; - drag_and_drop_file_list = Qnil; + drag_and_drop_list = Qnil; GetDragMouse (theDrag, &mouse, 0L); CountDragItems (theDrag, &items); for (index = 1; index <= items; index++) { - /* Only handle file references. */ + FlavorType flavor; + GetDragItemReferenceNumber (theDrag, index, &theItem); - result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags); - if (result == noErr) + flavor = mac_favorite_flavor (theDrag, theItem, &theFlags); + switch (flavor) + { + case flavorTypeHFS: + case flavorTypeDirectory: + /* Handle file/directory references. */ { + HFSFlavor data; + Size size = sizeof (HFSFlavor); #ifdef MAC_OSX FSRef fref; #endif char unix_path_name[MAXPATHLEN]; - GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L); + GetFlavorData (theDrag, theItem, flavor, &data, &size, 0L); #ifdef MAC_OSX /* Use Carbon routines, otherwise it converts the file name to /Macintosh HD/..., which is not correct. */ @@ -8262,16 +8291,52 @@ mac_do_receive_drag (WindowPtr window, v if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name, sizeof (unix_path_name) - 1) == noErr) #endif - /* x-dnd functions expect undecoded filenames. */ - drag_and_drop_file_list = - Fcons (make_unibyte_string (unix_path_name, + /* x-dnd functions expect undecoded filenames, but we + don't have to follow that. */ + drag_and_drop_list = + Fcons (Fcons + (intern ("file"), + Fdecode_coding_string + (make_unibyte_string (unix_path_name, strlen (unix_path_name)), - drag_and_drop_file_list); + NILP (Vfile_name_coding_system) + ? Vdefault_file_name_coding_system + : Vfile_name_coding_system, + Qnil)), + drag_and_drop_list); + } + break; + + case 'url ': + case 'utxt': + { + Size size; + char * data; + if (GetFlavorDataSize (theDrag, theItem, flavor, &size) != noErr) + break; + data = xmalloc (size + 1); + GetFlavorData (theDrag, theItem, flavor, data, &size, 0L); + if (flavor == 'url ') + drag_and_drop_list = + Fcons (Fcons (intern ("url"), + make_unibyte_string (data, size)), + drag_and_drop_list); + else + drag_and_drop_list = + Fcons (Fcons (intern ("text"), + Fdecode_coding_string + (make_unibyte_string (data, size), + intern ("utf-16"), + Qnil)), + drag_and_drop_list); + free (data); } + break; + }; } /* If there are items in the list, construct an event and post it to the queue like an interrupt using kbd_buffer_store_event. */ - if (!NILP (drag_and_drop_file_list)) + if (!NILP (drag_and_drop_list)) { struct input_event event; Lisp_Object frame; @@ -8288,7 +8353,7 @@ mac_do_receive_drag (WindowPtr window, v XSETINT (event.x, mouse.h); XSETINT (event.y, mouse.v); XSETFRAME (frame, f); - event.frame_or_window = Fcons (frame, drag_and_drop_file_list); + event.frame_or_window = Fcons (frame, drag_and_drop_list); event.arg = Qnil; /* Post to the interrupt queue */ kbd_buffer_store_event (&event); @@ -8298,12 +8363,13 @@ mac_do_receive_drag (WindowPtr window, v GetCurrentProcess (&psn); SetFrontProcess (&psn); } - return noErr; } else + { return dragNotAcceptedErr; } +} #endif @@ -9091,13 +9157,13 @@ XTread_socket (sd, expected, hold_quit) break; case kHighLevelEvent: - drag_and_drop_file_list = Qnil; + drag_and_drop_list = Qnil; AEProcessAppleEvent(&er); /* Build a DRAG_N_DROP_EVENT type event as is done in constuct_drag_n_drop in w32term.c. */ - if (!NILP (drag_and_drop_file_list)) + if (!NILP (drag_and_drop_list)) { struct frame *f = NULL; WindowPtr wp; @@ -9129,7 +9195,7 @@ XTread_socket (sd, expected, hold_quit) XSETINT (inev.y, 0); XSETFRAME (frame, f); - inev.frame_or_window = Fcons (frame, drag_and_drop_file_list); + inev.frame_or_window = Fcons (frame, drag_and_drop_list); /* Regardless of whether Emacs was suspended or in the foreground, ask it to redraw its entire screen. --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel --=-=-=--