diff options
| author | Dan Nicolaescu | 2008-07-27 18:24:48 +0000 |
|---|---|---|
| committer | Dan Nicolaescu | 2008-07-27 18:24:48 +0000 |
| commit | 9e2a2647758db83b490e2993aa31cd4607305a82 (patch) | |
| tree | 9c3d41b47bcd316c60d56bef8d7fd32789e59411 /src/macselect.c | |
| parent | 7f19297073b2dd6c28987bf5663933591f59e91e (diff) | |
| download | emacs-9e2a2647758db83b490e2993aa31cd4607305a82.tar.gz emacs-9e2a2647758db83b490e2993aa31cd4607305a82.zip | |
Remove support for Mac Carbon.
* mactoolbox.c:
* macterm.h:
* macterm.c:
* macselect.c:
* macmenu.c:
* macgui.h:
* macfns.c:
* mac.c: Remove file.
* s/darwin.h:
* m/intel386.h:
* xfaces.c:
* xdisp.c:
* window.c:
* tparam.c:
* termhooks.h:
* termcap.c:
* term.c:
* syssignal.h:
* sysselect.h:
* sysdep.c:
* process.c:
* lread.c:
* lisp.h:
* keyboard.c:
* image.c:
* fringe.c:
* frame.h:
* frame.c:
* fontset.c:
* font.h:
* font.c:
* fns.c:
* fileio.c:
* emacs.c:
* dispnew.c:
* dispextern.h:
* config.in:
* atimer.c:
* Makefile.in: Remove code for Carbon
* erc.el: Remove code for Carbon.
Remove support for Mac Carbon.
* term/mac-win.el: Remove file
* international/mule-cmds.el:
* version.el:
* startup.el:
* simple.el:
* mwheel.el:
* mouse.el:
* loadup.el:
* isearch.el:
* info.el:
* frame.el:
* faces.el:
* disp-table.el:
* cus-start.el:
* cus-face.el:
* cus-edit.el:
* Makefile.in: Remove code for Carbon.
Remove support for Mac Carbon.
* makefile.w32-in:
* emacsclient.c: Remove code for Carbon.
* PROBLEMS:
* MACHINES: Remove mentions of Mac Carbon.
* ns-emacs.texi:
* faq.texi: Remove mentions of Mac Carbon.
* os.texi:
* frames.texi:
* display.texi: Remove mentions of Mac Carbon.
* xresources.texi: Remove mentions of Mac Carbon.
* make-tarball.txt:
* admin.el:
* FOR-RELEASE:
* CPP-DEFINES: Remove mentions of Mac Carbon.
Remove support for Mac Carbon.
* mac: Remove directory.
* make-dist:
* configure.in:
* README:
* Makefile.in:
* INSTALL: Remove code for Carbon.
* configure: Regenerate.
Diffstat (limited to 'src/macselect.c')
| -rw-r--r-- | src/macselect.c | 1165 |
1 files changed, 0 insertions, 1165 deletions
diff --git a/src/macselect.c b/src/macselect.c deleted file mode 100644 index b505698fab0..00000000000 --- a/src/macselect.c +++ /dev/null | |||
| @@ -1,1165 +0,0 @@ | |||
| 1 | /* Selection processing for Emacs on Mac OS. | ||
| 2 | Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 3 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 18 | |||
| 19 | #include <config.h> | ||
| 20 | |||
| 21 | #include "lisp.h" | ||
| 22 | #include "macterm.h" | ||
| 23 | #include "blockinput.h" | ||
| 24 | #include "keymap.h" | ||
| 25 | |||
| 26 | #if !TARGET_API_MAC_CARBON | ||
| 27 | #include <Endian.h> | ||
| 28 | #endif | ||
| 29 | |||
| 30 | static void x_own_selection P_ ((Lisp_Object, Lisp_Object)); | ||
| 31 | static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object, int)); | ||
| 32 | static Lisp_Object x_get_foreign_selection P_ ((Lisp_Object, | ||
| 33 | Lisp_Object, | ||
| 34 | Lisp_Object)); | ||
| 35 | |||
| 36 | Lisp_Object QPRIMARY, QSECONDARY, QTIMESTAMP, QTARGETS; | ||
| 37 | |||
| 38 | static Lisp_Object Vx_lost_selection_functions; | ||
| 39 | /* Coding system for communicating with other programs via selections. */ | ||
| 40 | static Lisp_Object Vselection_coding_system; | ||
| 41 | |||
| 42 | /* Coding system for the next communicating with other programs. */ | ||
| 43 | static Lisp_Object Vnext_selection_coding_system; | ||
| 44 | |||
| 45 | static Lisp_Object Qforeign_selection; | ||
| 46 | |||
| 47 | /* The timestamp of the last input event Emacs received from the | ||
| 48 | window server. */ | ||
| 49 | /* Defined in keyboard.c. */ | ||
| 50 | extern unsigned long last_event_timestamp; | ||
| 51 | |||
| 52 | /* This is an association list whose elements are of the form | ||
| 53 | ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME OWNERSHIP-INFO) | ||
| 54 | SELECTION-NAME is a lisp symbol. | ||
| 55 | SELECTION-VALUE is the value that emacs owns for that selection. | ||
| 56 | It may be any kind of Lisp object. | ||
| 57 | SELECTION-TIMESTAMP is the time at which emacs began owning this selection, | ||
| 58 | as a cons of two 16-bit numbers (making a 32 bit time.) | ||
| 59 | FRAME is the frame for which we made the selection. | ||
| 60 | OWNERSHIP-INFO is a value saved when emacs owns for that selection. | ||
| 61 | If another application takes the ownership of that selection | ||
| 62 | later, then newly examined ownership info value should be | ||
| 63 | different from the saved one. | ||
| 64 | If there is an entry in this alist, the current ownership info for | ||
| 65 | the selection coincides with OWNERSHIP-INFO, then it can be | ||
| 66 | assumed that Emacs owns that selection. | ||
| 67 | The only (eq) parts of this list that are visible from Lisp are the | ||
| 68 | selection-values. */ | ||
| 69 | static Lisp_Object Vselection_alist; | ||
| 70 | |||
| 71 | /* This is an alist whose CARs are selection-types and whose CDRs are | ||
| 72 | the names of Lisp functions to call to convert the given Emacs | ||
| 73 | selection value to a string representing the given selection type. | ||
| 74 | This is for Lisp-level extension of the emacs selection | ||
| 75 | handling. */ | ||
| 76 | Lisp_Object Vselection_converter_alist; | ||
| 77 | |||
| 78 | /* A selection name (represented as a Lisp symbol) can be associated | ||
| 79 | with a named scrap via `mac-scrap-name' property. Likewise for a | ||
| 80 | selection type with a scrap flavor type via `mac-ostype'. */ | ||
| 81 | Lisp_Object Qmac_scrap_name, Qmac_ostype; | ||
| 82 | |||
| 83 | |||
| 84 | /* Do protocol to assert ourself as a selection owner. | ||
| 85 | Update the Vselection_alist so that we can reply to later requests for | ||
| 86 | our selection. */ | ||
| 87 | |||
| 88 | static void | ||
| 89 | x_own_selection (selection_name, selection_value) | ||
| 90 | Lisp_Object selection_name, selection_value; | ||
| 91 | { | ||
| 92 | OSStatus err; | ||
| 93 | Selection sel; | ||
| 94 | struct gcpro gcpro1, gcpro2; | ||
| 95 | Lisp_Object rest, handler_fn, value, target_type; | ||
| 96 | int count; | ||
| 97 | |||
| 98 | CHECK_SYMBOL (selection_name); | ||
| 99 | |||
| 100 | GCPRO2 (selection_name, selection_value); | ||
| 101 | |||
| 102 | BLOCK_INPUT; | ||
| 103 | |||
| 104 | err = mac_get_selection_from_symbol (selection_name, 1, &sel); | ||
| 105 | if (err == noErr && sel) | ||
| 106 | { | ||
| 107 | /* Don't allow a quit within the converter. | ||
| 108 | When the user types C-g, he would be surprised | ||
| 109 | if by luck it came during a converter. */ | ||
| 110 | count = SPECPDL_INDEX (); | ||
| 111 | specbind (Qinhibit_quit, Qt); | ||
| 112 | |||
| 113 | for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest)) | ||
| 114 | { | ||
| 115 | if (!(CONSP (XCAR (rest)) | ||
| 116 | && (target_type = XCAR (XCAR (rest)), | ||
| 117 | SYMBOLP (target_type)) | ||
| 118 | && mac_valid_selection_target_p (target_type) | ||
| 119 | && (handler_fn = XCDR (XCAR (rest)), | ||
| 120 | SYMBOLP (handler_fn)))) | ||
| 121 | continue; | ||
| 122 | |||
| 123 | if (!NILP (handler_fn)) | ||
| 124 | value = call3 (handler_fn, selection_name, | ||
| 125 | target_type, selection_value); | ||
| 126 | |||
| 127 | if (NILP (value)) | ||
| 128 | continue; | ||
| 129 | |||
| 130 | if (mac_valid_selection_value_p (value, target_type)) | ||
| 131 | err = mac_put_selection_value (sel, target_type, value); | ||
| 132 | else if (CONSP (value) | ||
| 133 | && EQ (XCAR (value), target_type) | ||
| 134 | && mac_valid_selection_value_p (XCDR (value), target_type)) | ||
| 135 | err = mac_put_selection_value (sel, target_type, XCDR (value)); | ||
| 136 | } | ||
| 137 | |||
| 138 | unbind_to (count, Qnil); | ||
| 139 | } | ||
| 140 | |||
| 141 | UNBLOCK_INPUT; | ||
| 142 | |||
| 143 | UNGCPRO; | ||
| 144 | |||
| 145 | if (sel && err != noErr) | ||
| 146 | error ("Can't set selection"); | ||
| 147 | |||
| 148 | /* Now update the local cache */ | ||
| 149 | { | ||
| 150 | Lisp_Object selection_time; | ||
| 151 | Lisp_Object selection_data; | ||
| 152 | Lisp_Object ownership_info; | ||
| 153 | Lisp_Object prev_value; | ||
| 154 | |||
| 155 | selection_time = long_to_cons (last_event_timestamp); | ||
| 156 | if (sel) | ||
| 157 | { | ||
| 158 | BLOCK_INPUT; | ||
| 159 | ownership_info = mac_get_selection_ownership_info (sel); | ||
| 160 | UNBLOCK_INPUT; | ||
| 161 | } | ||
| 162 | else | ||
| 163 | ownership_info = Qnil; /* dummy value for local-only selection */ | ||
| 164 | selection_data = Fcons (selection_name, | ||
| 165 | Fcons (selection_value, | ||
| 166 | Fcons (selection_time, | ||
| 167 | Fcons (selected_frame, | ||
| 168 | Fcons (ownership_info, | ||
| 169 | Qnil))))); | ||
| 170 | prev_value = assq_no_quit (selection_name, Vselection_alist); | ||
| 171 | |||
| 172 | Vselection_alist = Fcons (selection_data, Vselection_alist); | ||
| 173 | |||
| 174 | /* If we already owned the selection, remove the old selection data. | ||
| 175 | Perhaps we should destructively modify it instead. | ||
| 176 | Don't use Fdelq as that may QUIT. */ | ||
| 177 | if (!NILP (prev_value)) | ||
| 178 | { | ||
| 179 | Lisp_Object rest; /* we know it's not the CAR, so it's easy. */ | ||
| 180 | for (rest = Vselection_alist; CONSP (rest); rest = XCDR (rest)) | ||
| 181 | if (EQ (prev_value, Fcar (XCDR (rest)))) | ||
| 182 | { | ||
| 183 | XSETCDR (rest, Fcdr (XCDR (rest))); | ||
| 184 | break; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | /* Given a selection-name and desired type, look up our local copy of | ||
| 191 | the selection value and convert it to the type. | ||
| 192 | The value is nil or a string. | ||
| 193 | This function is used both for remote requests (LOCAL_REQUEST is zero) | ||
| 194 | and for local x-get-selection-internal (LOCAL_REQUEST is nonzero). | ||
| 195 | |||
| 196 | This calls random Lisp code, and may signal or gc. */ | ||
| 197 | |||
| 198 | static Lisp_Object | ||
| 199 | x_get_local_selection (selection_symbol, target_type, local_request) | ||
| 200 | Lisp_Object selection_symbol, target_type; | ||
| 201 | int local_request; | ||
| 202 | { | ||
| 203 | Lisp_Object local_value; | ||
| 204 | Lisp_Object handler_fn, value, type, check; | ||
| 205 | int count; | ||
| 206 | |||
| 207 | if (NILP (Fx_selection_owner_p (selection_symbol))) | ||
| 208 | return Qnil; | ||
| 209 | |||
| 210 | local_value = assq_no_quit (selection_symbol, Vselection_alist); | ||
| 211 | |||
| 212 | /* TIMESTAMP is a special case 'cause that's easiest. */ | ||
| 213 | if (EQ (target_type, QTIMESTAMP)) | ||
| 214 | { | ||
| 215 | handler_fn = Qnil; | ||
| 216 | value = XCAR (XCDR (XCDR (local_value))); | ||
| 217 | } | ||
| 218 | #if 0 | ||
| 219 | else if (EQ (target_type, QDELETE)) | ||
| 220 | { | ||
| 221 | handler_fn = Qnil; | ||
| 222 | Fx_disown_selection_internal | ||
| 223 | (selection_symbol, | ||
| 224 | XCAR (XCDR (XCDR (local_value)))); | ||
| 225 | value = QNULL; | ||
| 226 | } | ||
| 227 | #endif | ||
| 228 | else | ||
| 229 | { | ||
| 230 | /* Don't allow a quit within the converter. | ||
| 231 | When the user types C-g, he would be surprised | ||
| 232 | if by luck it came during a converter. */ | ||
| 233 | count = SPECPDL_INDEX (); | ||
| 234 | specbind (Qinhibit_quit, Qt); | ||
| 235 | |||
| 236 | CHECK_SYMBOL (target_type); | ||
| 237 | handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); | ||
| 238 | /* gcpro is not needed here since nothing but HANDLER_FN | ||
| 239 | is live, and that ought to be a symbol. */ | ||
| 240 | |||
| 241 | if (!NILP (handler_fn)) | ||
| 242 | value = call3 (handler_fn, | ||
| 243 | selection_symbol, (local_request ? Qnil : target_type), | ||
| 244 | XCAR (XCDR (local_value))); | ||
| 245 | else | ||
| 246 | value = Qnil; | ||
| 247 | unbind_to (count, Qnil); | ||
| 248 | } | ||
| 249 | |||
| 250 | if (local_request) | ||
| 251 | return value; | ||
| 252 | |||
| 253 | /* Make sure this value is of a type that we could transmit | ||
| 254 | to another application. */ | ||
| 255 | |||
| 256 | type = target_type; | ||
| 257 | check = value; | ||
| 258 | if (CONSP (value) | ||
| 259 | && SYMBOLP (XCAR (value))) | ||
| 260 | type = XCAR (value), | ||
| 261 | check = XCDR (value); | ||
| 262 | |||
| 263 | if (NILP (value) || mac_valid_selection_value_p (check, type)) | ||
| 264 | return value; | ||
| 265 | |||
| 266 | signal_error ("Invalid data returned by selection-conversion function", | ||
| 267 | list2 (handler_fn, value)); | ||
| 268 | } | ||
| 269 | |||
| 270 | |||
| 271 | /* Clear all selections that were made from frame F. | ||
| 272 | We do this when about to delete a frame. */ | ||
| 273 | |||
| 274 | void | ||
| 275 | x_clear_frame_selections (f) | ||
| 276 | FRAME_PTR f; | ||
| 277 | { | ||
| 278 | Lisp_Object frame; | ||
| 279 | Lisp_Object rest; | ||
| 280 | |||
| 281 | XSETFRAME (frame, f); | ||
| 282 | |||
| 283 | /* Otherwise, we're really honest and truly being told to drop it. | ||
| 284 | Don't use Fdelq as that may QUIT;. */ | ||
| 285 | |||
| 286 | /* Delete elements from the beginning of Vselection_alist. */ | ||
| 287 | while (!NILP (Vselection_alist) | ||
| 288 | && EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (Vselection_alist))))))) | ||
| 289 | { | ||
| 290 | /* Let random Lisp code notice that the selection has been stolen. */ | ||
| 291 | Lisp_Object hooks, selection_symbol; | ||
| 292 | |||
| 293 | hooks = Vx_lost_selection_functions; | ||
| 294 | selection_symbol = Fcar (Fcar (Vselection_alist)); | ||
| 295 | |||
| 296 | if (!EQ (hooks, Qunbound) | ||
| 297 | && !NILP (Fx_selection_owner_p (selection_symbol))) | ||
| 298 | { | ||
| 299 | for (; CONSP (hooks); hooks = Fcdr (hooks)) | ||
| 300 | call1 (Fcar (hooks), selection_symbol); | ||
| 301 | #if 0 /* This can crash when deleting a frame | ||
| 302 | from x_connection_closed. Anyway, it seems unnecessary; | ||
| 303 | something else should cause a redisplay. */ | ||
| 304 | redisplay_preserve_echo_area (21); | ||
| 305 | #endif | ||
| 306 | } | ||
| 307 | |||
| 308 | Vselection_alist = Fcdr (Vselection_alist); | ||
| 309 | } | ||
| 310 | |||
| 311 | /* Delete elements after the beginning of Vselection_alist. */ | ||
| 312 | for (rest = Vselection_alist; CONSP (rest); rest = XCDR (rest)) | ||
| 313 | if (EQ (frame, Fcar (Fcdr (Fcdr (Fcdr (Fcar (XCDR (rest)))))))) | ||
| 314 | { | ||
| 315 | /* Let random Lisp code notice that the selection has been stolen. */ | ||
| 316 | Lisp_Object hooks, selection_symbol; | ||
| 317 | |||
| 318 | hooks = Vx_lost_selection_functions; | ||
| 319 | selection_symbol = Fcar (Fcar (XCDR (rest))); | ||
| 320 | |||
| 321 | if (!EQ (hooks, Qunbound) | ||
| 322 | && !NILP (Fx_selection_owner_p (selection_symbol))) | ||
| 323 | { | ||
| 324 | for (; CONSP (hooks); hooks = Fcdr (hooks)) | ||
| 325 | call1 (Fcar (hooks), selection_symbol); | ||
| 326 | #if 0 /* See above */ | ||
| 327 | redisplay_preserve_echo_area (22); | ||
| 328 | #endif | ||
| 329 | } | ||
| 330 | XSETCDR (rest, Fcdr (XCDR (rest))); | ||
| 331 | break; | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | /* Do protocol to read selection-data from the server. | ||
| 336 | Converts this to Lisp data and returns it. */ | ||
| 337 | |||
| 338 | static Lisp_Object | ||
| 339 | x_get_foreign_selection (selection_symbol, target_type, time_stamp) | ||
| 340 | Lisp_Object selection_symbol, target_type, time_stamp; | ||
| 341 | { | ||
| 342 | OSStatus err; | ||
| 343 | Selection sel; | ||
| 344 | Lisp_Object result = Qnil; | ||
| 345 | |||
| 346 | BLOCK_INPUT; | ||
| 347 | |||
| 348 | err = mac_get_selection_from_symbol (selection_symbol, 0, &sel); | ||
| 349 | if (err == noErr && sel) | ||
| 350 | { | ||
| 351 | if (EQ (target_type, QTARGETS)) | ||
| 352 | { | ||
| 353 | result = mac_get_selection_target_list (sel); | ||
| 354 | result = Fvconcat (1, &result); | ||
| 355 | } | ||
| 356 | else | ||
| 357 | { | ||
| 358 | result = mac_get_selection_value (sel, target_type); | ||
| 359 | if (STRINGP (result)) | ||
| 360 | Fput_text_property (make_number (0), make_number (SBYTES (result)), | ||
| 361 | Qforeign_selection, target_type, result); | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | UNBLOCK_INPUT; | ||
| 366 | |||
| 367 | return result; | ||
| 368 | } | ||
| 369 | |||
| 370 | |||
| 371 | DEFUN ("x-own-selection-internal", Fx_own_selection_internal, | ||
| 372 | Sx_own_selection_internal, 2, 2, 0, | ||
| 373 | doc: /* Assert a selection of the given TYPE with the given VALUE. | ||
| 374 | TYPE is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. | ||
| 375 | VALUE is typically a string, or a cons of two markers, but may be | ||
| 376 | anything that the functions on `selection-converter-alist' know about. */) | ||
| 377 | (selection_name, selection_value) | ||
| 378 | Lisp_Object selection_name, selection_value; | ||
| 379 | { | ||
| 380 | check_mac (); | ||
| 381 | CHECK_SYMBOL (selection_name); | ||
| 382 | if (NILP (selection_value)) error ("SELECTION-VALUE may not be nil"); | ||
| 383 | x_own_selection (selection_name, selection_value); | ||
| 384 | return selection_value; | ||
| 385 | } | ||
| 386 | |||
| 387 | |||
| 388 | /* Request the selection value from the owner. If we are the owner, | ||
| 389 | simply return our selection value. If we are not the owner, this | ||
| 390 | will block until all of the data has arrived. */ | ||
| 391 | |||
| 392 | DEFUN ("x-get-selection-internal", Fx_get_selection_internal, | ||
| 393 | Sx_get_selection_internal, 2, 3, 0, | ||
| 394 | doc: /* Return text selected from some Mac application. | ||
| 395 | SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. | ||
| 396 | TYPE is the type of data desired, typically `STRING'. | ||
| 397 | TIME_STAMP is ignored on Mac. */) | ||
| 398 | (selection_symbol, target_type, time_stamp) | ||
| 399 | Lisp_Object selection_symbol, target_type, time_stamp; | ||
| 400 | { | ||
| 401 | Lisp_Object val = Qnil; | ||
| 402 | struct gcpro gcpro1, gcpro2; | ||
| 403 | GCPRO2 (target_type, val); /* we store newly consed data into these */ | ||
| 404 | check_mac (); | ||
| 405 | CHECK_SYMBOL (selection_symbol); | ||
| 406 | CHECK_SYMBOL (target_type); | ||
| 407 | |||
| 408 | val = x_get_local_selection (selection_symbol, target_type, 1); | ||
| 409 | |||
| 410 | if (NILP (val)) | ||
| 411 | { | ||
| 412 | val = x_get_foreign_selection (selection_symbol, target_type, time_stamp); | ||
| 413 | goto DONE; | ||
| 414 | } | ||
| 415 | |||
| 416 | if (CONSP (val) | ||
| 417 | && SYMBOLP (XCAR (val))) | ||
| 418 | { | ||
| 419 | val = XCDR (val); | ||
| 420 | if (CONSP (val) && NILP (XCDR (val))) | ||
| 421 | val = XCAR (val); | ||
| 422 | } | ||
| 423 | DONE: | ||
| 424 | UNGCPRO; | ||
| 425 | return val; | ||
| 426 | } | ||
| 427 | |||
| 428 | DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal, | ||
| 429 | Sx_disown_selection_internal, 1, 2, 0, | ||
| 430 | doc: /* If we own the selection SELECTION, disown it. | ||
| 431 | Disowning it means there is no such selection. */) | ||
| 432 | (selection, time) | ||
| 433 | Lisp_Object selection; | ||
| 434 | Lisp_Object time; | ||
| 435 | { | ||
| 436 | OSStatus err; | ||
| 437 | Selection sel; | ||
| 438 | Lisp_Object local_selection_data; | ||
| 439 | |||
| 440 | check_mac (); | ||
| 441 | CHECK_SYMBOL (selection); | ||
| 442 | |||
| 443 | if (NILP (Fx_selection_owner_p (selection))) | ||
| 444 | return Qnil; /* Don't disown the selection when we're not the owner. */ | ||
| 445 | |||
| 446 | local_selection_data = assq_no_quit (selection, Vselection_alist); | ||
| 447 | |||
| 448 | /* Don't use Fdelq as that may QUIT;. */ | ||
| 449 | |||
| 450 | if (EQ (local_selection_data, Fcar (Vselection_alist))) | ||
| 451 | Vselection_alist = Fcdr (Vselection_alist); | ||
| 452 | else | ||
| 453 | { | ||
| 454 | Lisp_Object rest; | ||
| 455 | for (rest = Vselection_alist; CONSP (rest); rest = XCDR (rest)) | ||
| 456 | if (EQ (local_selection_data, Fcar (XCDR (rest)))) | ||
| 457 | { | ||
| 458 | XSETCDR (rest, Fcdr (XCDR (rest))); | ||
| 459 | break; | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | /* Let random lisp code notice that the selection has been stolen. */ | ||
| 464 | |||
| 465 | { | ||
| 466 | Lisp_Object rest; | ||
| 467 | rest = Vx_lost_selection_functions; | ||
| 468 | if (!EQ (rest, Qunbound)) | ||
| 469 | { | ||
| 470 | for (; CONSP (rest); rest = Fcdr (rest)) | ||
| 471 | call1 (Fcar (rest), selection); | ||
| 472 | prepare_menu_bars (); | ||
| 473 | redisplay_preserve_echo_area (20); | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | BLOCK_INPUT; | ||
| 478 | |||
| 479 | err = mac_get_selection_from_symbol (selection, 0, &sel); | ||
| 480 | if (err == noErr && sel) | ||
| 481 | mac_clear_selection (&sel); | ||
| 482 | |||
| 483 | UNBLOCK_INPUT; | ||
| 484 | |||
| 485 | return Qt; | ||
| 486 | } | ||
| 487 | |||
| 488 | |||
| 489 | DEFUN ("x-selection-owner-p", Fx_selection_owner_p, Sx_selection_owner_p, | ||
| 490 | 0, 1, 0, | ||
| 491 | doc: /* Whether the current Emacs process owns the given SELECTION. | ||
| 492 | The arg should be the name of the selection in question, typically one of | ||
| 493 | the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. | ||
| 494 | For convenience, the symbol nil is the same as `PRIMARY', | ||
| 495 | and t is the same as `SECONDARY'. */) | ||
| 496 | (selection) | ||
| 497 | Lisp_Object selection; | ||
| 498 | { | ||
| 499 | OSStatus err; | ||
| 500 | Selection sel; | ||
| 501 | Lisp_Object result = Qnil, local_selection_data; | ||
| 502 | |||
| 503 | check_mac (); | ||
| 504 | CHECK_SYMBOL (selection); | ||
| 505 | if (EQ (selection, Qnil)) selection = QPRIMARY; | ||
| 506 | if (EQ (selection, Qt)) selection = QSECONDARY; | ||
| 507 | |||
| 508 | local_selection_data = assq_no_quit (selection, Vselection_alist); | ||
| 509 | |||
| 510 | if (NILP (local_selection_data)) | ||
| 511 | return Qnil; | ||
| 512 | |||
| 513 | BLOCK_INPUT; | ||
| 514 | |||
| 515 | err = mac_get_selection_from_symbol (selection, 0, &sel); | ||
| 516 | if (err == noErr && sel) | ||
| 517 | { | ||
| 518 | Lisp_Object ownership_info; | ||
| 519 | |||
| 520 | ownership_info = XCAR (XCDR (XCDR (XCDR (XCDR (local_selection_data))))); | ||
| 521 | if (!NILP (Fequal (ownership_info, | ||
| 522 | mac_get_selection_ownership_info (sel)))) | ||
| 523 | result = Qt; | ||
| 524 | } | ||
| 525 | else | ||
| 526 | result = Qt; | ||
| 527 | |||
| 528 | UNBLOCK_INPUT; | ||
| 529 | |||
| 530 | return result; | ||
| 531 | } | ||
| 532 | |||
| 533 | DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p, | ||
| 534 | 0, 1, 0, | ||
| 535 | doc: /* Whether there is an owner for the given SELECTION. | ||
| 536 | The arg should be the name of the selection in question, typically one of | ||
| 537 | the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. | ||
| 538 | For convenience, the symbol nil is the same as `PRIMARY', | ||
| 539 | and t is the same as `SECONDARY'. */) | ||
| 540 | (selection) | ||
| 541 | Lisp_Object selection; | ||
| 542 | { | ||
| 543 | OSStatus err; | ||
| 544 | Selection sel; | ||
| 545 | Lisp_Object result = Qnil, rest; | ||
| 546 | |||
| 547 | /* It should be safe to call this before we have an Mac frame. */ | ||
| 548 | if (! FRAME_MAC_P (SELECTED_FRAME ())) | ||
| 549 | return Qnil; | ||
| 550 | |||
| 551 | CHECK_SYMBOL (selection); | ||
| 552 | if (!NILP (Fx_selection_owner_p (selection))) | ||
| 553 | return Qt; | ||
| 554 | if (EQ (selection, Qnil)) selection = QPRIMARY; | ||
| 555 | if (EQ (selection, Qt)) selection = QSECONDARY; | ||
| 556 | |||
| 557 | BLOCK_INPUT; | ||
| 558 | |||
| 559 | err = mac_get_selection_from_symbol (selection, 0, &sel); | ||
| 560 | if (err == noErr && sel) | ||
| 561 | for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest)) | ||
| 562 | { | ||
| 563 | if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest))) | ||
| 564 | && mac_selection_has_target_p (sel, XCAR (XCAR (rest)))) | ||
| 565 | { | ||
| 566 | result = Qt; | ||
| 567 | break; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | |||
| 571 | UNBLOCK_INPUT; | ||
| 572 | |||
| 573 | return result; | ||
| 574 | } | ||
| 575 | |||
| 576 | |||
| 577 | /*********************************************************************** | ||
| 578 | Apple event support | ||
| 579 | ***********************************************************************/ | ||
| 580 | int mac_ready_for_apple_events = 0; | ||
| 581 | Lisp_Object Vmac_apple_event_map; | ||
| 582 | Lisp_Object Qmac_apple_event_class, Qmac_apple_event_id; | ||
| 583 | static Lisp_Object Qemacs_suspension_id; | ||
| 584 | extern Lisp_Object Qundefined; | ||
| 585 | extern void mac_store_apple_event P_ ((Lisp_Object, Lisp_Object, | ||
| 586 | const AEDesc *)); | ||
| 587 | |||
| 588 | struct apple_event_binding | ||
| 589 | { | ||
| 590 | UInt32 code; /* Apple event class or ID. */ | ||
| 591 | Lisp_Object key, binding; | ||
| 592 | }; | ||
| 593 | |||
| 594 | struct suspended_ae_info | ||
| 595 | { | ||
| 596 | UInt32 expiration_tick, suspension_id; | ||
| 597 | AppleEvent apple_event, reply; | ||
| 598 | struct suspended_ae_info *next; | ||
| 599 | }; | ||
| 600 | |||
| 601 | /* List of apple events deferred at the startup time. */ | ||
| 602 | static struct suspended_ae_info *deferred_apple_events = NULL; | ||
| 603 | |||
| 604 | /* List of suspended apple events, in order of expiration_tick. */ | ||
| 605 | static struct suspended_ae_info *suspended_apple_events = NULL; | ||
| 606 | |||
| 607 | static void | ||
| 608 | find_event_binding_fun (key, binding, args, data) | ||
| 609 | Lisp_Object key, binding, args; | ||
| 610 | void *data; | ||
| 611 | { | ||
| 612 | struct apple_event_binding *event_binding = | ||
| 613 | (struct apple_event_binding *)data; | ||
| 614 | Lisp_Object code_string; | ||
| 615 | |||
| 616 | if (!SYMBOLP (key)) | ||
| 617 | return; | ||
| 618 | code_string = Fget (key, args); | ||
| 619 | if (STRINGP (code_string) && SBYTES (code_string) == 4 | ||
| 620 | && (EndianU32_BtoN (*((UInt32 *) SDATA (code_string))) | ||
| 621 | == event_binding->code)) | ||
| 622 | { | ||
| 623 | event_binding->key = key; | ||
| 624 | event_binding->binding = binding; | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 628 | static void | ||
| 629 | find_event_binding (keymap, event_binding, class_p) | ||
| 630 | Lisp_Object keymap; | ||
| 631 | struct apple_event_binding *event_binding; | ||
| 632 | int class_p; | ||
| 633 | { | ||
| 634 | if (event_binding->code == 0) | ||
| 635 | event_binding->binding = | ||
| 636 | access_keymap (keymap, event_binding->key, 0, 1, 0); | ||
| 637 | else | ||
| 638 | { | ||
| 639 | event_binding->binding = Qnil; | ||
| 640 | map_keymap (keymap, find_event_binding_fun, | ||
| 641 | class_p ? Qmac_apple_event_class : Qmac_apple_event_id, | ||
| 642 | event_binding, 0); | ||
| 643 | } | ||
| 644 | } | ||
| 645 | |||
| 646 | void | ||
| 647 | mac_find_apple_event_spec (class, id, class_key, id_key, binding) | ||
| 648 | AEEventClass class; | ||
| 649 | AEEventID id; | ||
| 650 | Lisp_Object *class_key, *id_key, *binding; | ||
| 651 | { | ||
| 652 | struct apple_event_binding event_binding; | ||
| 653 | Lisp_Object keymap; | ||
| 654 | |||
| 655 | *binding = Qnil; | ||
| 656 | |||
| 657 | keymap = get_keymap (Vmac_apple_event_map, 0, 0); | ||
| 658 | if (NILP (keymap)) | ||
| 659 | return; | ||
| 660 | |||
| 661 | event_binding.code = class; | ||
| 662 | event_binding.key = *class_key; | ||
| 663 | event_binding.binding = Qnil; | ||
| 664 | find_event_binding (keymap, &event_binding, 1); | ||
| 665 | *class_key = event_binding.key; | ||
| 666 | keymap = get_keymap (event_binding.binding, 0, 0); | ||
| 667 | if (NILP (keymap)) | ||
| 668 | return; | ||
| 669 | |||
| 670 | event_binding.code = id; | ||
| 671 | event_binding.key = *id_key; | ||
| 672 | event_binding.binding = Qnil; | ||
| 673 | find_event_binding (keymap, &event_binding, 0); | ||
| 674 | *id_key = event_binding.key; | ||
| 675 | *binding = event_binding.binding; | ||
| 676 | } | ||
| 677 | |||
| 678 | static OSErr | ||
| 679 | defer_apple_events (apple_event, reply) | ||
| 680 | const AppleEvent *apple_event, *reply; | ||
| 681 | { | ||
| 682 | OSErr err; | ||
| 683 | struct suspended_ae_info *new; | ||
| 684 | |||
| 685 | new = xmalloc (sizeof (struct suspended_ae_info)); | ||
| 686 | bzero (new, sizeof (struct suspended_ae_info)); | ||
| 687 | new->apple_event.descriptorType = typeNull; | ||
| 688 | new->reply.descriptorType = typeNull; | ||
| 689 | |||
| 690 | err = AESuspendTheCurrentEvent (apple_event); | ||
| 691 | |||
| 692 | /* Mac OS 10.3 Xcode manual says AESuspendTheCurrentEvent makes | ||
| 693 | copies of the Apple event and the reply, but Mac OS 10.4 Xcode | ||
| 694 | manual says it doesn't. Anyway we create copies of them and save | ||
| 695 | them in `deferred_apple_events'. */ | ||
| 696 | if (err == noErr) | ||
| 697 | err = AEDuplicateDesc (apple_event, &new->apple_event); | ||
| 698 | if (err == noErr) | ||
| 699 | err = AEDuplicateDesc (reply, &new->reply); | ||
| 700 | if (err == noErr) | ||
| 701 | { | ||
| 702 | new->next = deferred_apple_events; | ||
| 703 | deferred_apple_events = new; | ||
| 704 | } | ||
| 705 | else | ||
| 706 | { | ||
| 707 | AEDisposeDesc (&new->apple_event); | ||
| 708 | AEDisposeDesc (&new->reply); | ||
| 709 | xfree (new); | ||
| 710 | } | ||
| 711 | |||
| 712 | return err; | ||
| 713 | } | ||
| 714 | |||
| 715 | static OSErr | ||
| 716 | mac_handle_apple_event_1 (class, id, apple_event, reply) | ||
| 717 | Lisp_Object class, id; | ||
| 718 | const AppleEvent *apple_event; | ||
| 719 | AppleEvent *reply; | ||
| 720 | { | ||
| 721 | OSErr err; | ||
| 722 | static UInt32 suspension_id = 0; | ||
| 723 | struct suspended_ae_info *new; | ||
| 724 | |||
| 725 | new = xmalloc (sizeof (struct suspended_ae_info)); | ||
| 726 | bzero (new, sizeof (struct suspended_ae_info)); | ||
| 727 | new->apple_event.descriptorType = typeNull; | ||
| 728 | new->reply.descriptorType = typeNull; | ||
| 729 | |||
| 730 | err = AESuspendTheCurrentEvent (apple_event); | ||
| 731 | if (err == noErr) | ||
| 732 | err = AEDuplicateDesc (apple_event, &new->apple_event); | ||
| 733 | if (err == noErr) | ||
| 734 | err = AEDuplicateDesc (reply, &new->reply); | ||
| 735 | if (err == noErr) | ||
| 736 | err = AEPutAttributePtr (&new->apple_event, KEY_EMACS_SUSPENSION_ID_ATTR, | ||
| 737 | typeUInt32, &suspension_id, sizeof (UInt32)); | ||
| 738 | if (err == noErr) | ||
| 739 | { | ||
| 740 | OSErr err1; | ||
| 741 | SInt32 reply_requested; | ||
| 742 | |||
| 743 | err1 = AEGetAttributePtr (&new->apple_event, keyReplyRequestedAttr, | ||
| 744 | typeSInt32, NULL, &reply_requested, | ||
| 745 | sizeof (SInt32), NULL); | ||
| 746 | if (err1 != noErr) | ||
| 747 | { | ||
| 748 | /* Emulate keyReplyRequestedAttr in older versions. */ | ||
| 749 | reply_requested = reply->descriptorType != typeNull; | ||
| 750 | err = AEPutAttributePtr (&new->apple_event, keyReplyRequestedAttr, | ||
| 751 | typeSInt32, &reply_requested, | ||
| 752 | sizeof (SInt32)); | ||
| 753 | } | ||
| 754 | } | ||
| 755 | if (err == noErr) | ||
| 756 | { | ||
| 757 | SInt32 timeout = 0; | ||
| 758 | struct suspended_ae_info **p; | ||
| 759 | |||
| 760 | new->suspension_id = suspension_id; | ||
| 761 | suspension_id++; | ||
| 762 | err = AEGetAttributePtr (apple_event, keyTimeoutAttr, typeSInt32, | ||
| 763 | NULL, &timeout, sizeof (SInt32), NULL); | ||
| 764 | new->expiration_tick = TickCount () + timeout; | ||
| 765 | |||
| 766 | for (p = &suspended_apple_events; *p; p = &(*p)->next) | ||
| 767 | if ((*p)->expiration_tick >= new->expiration_tick) | ||
| 768 | break; | ||
| 769 | new->next = *p; | ||
| 770 | *p = new; | ||
| 771 | |||
| 772 | mac_store_apple_event (class, id, &new->apple_event); | ||
| 773 | } | ||
| 774 | else | ||
| 775 | { | ||
| 776 | AEDisposeDesc (&new->reply); | ||
| 777 | AEDisposeDesc (&new->apple_event); | ||
| 778 | xfree (new); | ||
| 779 | } | ||
| 780 | |||
| 781 | return err; | ||
| 782 | } | ||
| 783 | |||
| 784 | pascal OSErr | ||
| 785 | mac_handle_apple_event (apple_event, reply, refcon) | ||
| 786 | const AppleEvent *apple_event; | ||
| 787 | AppleEvent *reply; | ||
| 788 | SInt32 refcon; | ||
| 789 | { | ||
| 790 | OSErr err; | ||
| 791 | UInt32 suspension_id; | ||
| 792 | AEEventClass event_class; | ||
| 793 | AEEventID event_id; | ||
| 794 | Lisp_Object class_key, id_key, binding; | ||
| 795 | |||
| 796 | if (!mac_ready_for_apple_events) | ||
| 797 | { | ||
| 798 | err = defer_apple_events (apple_event, reply); | ||
| 799 | if (err != noErr) | ||
| 800 | return errAEEventNotHandled; | ||
| 801 | return noErr; | ||
| 802 | } | ||
| 803 | |||
| 804 | err = AEGetAttributePtr (apple_event, KEY_EMACS_SUSPENSION_ID_ATTR, | ||
| 805 | typeUInt32, NULL, | ||
| 806 | &suspension_id, sizeof (UInt32), NULL); | ||
| 807 | if (err == noErr) | ||
| 808 | /* Previously suspended event. Pass it to the next handler. */ | ||
| 809 | return errAEEventNotHandled; | ||
| 810 | |||
| 811 | err = AEGetAttributePtr (apple_event, keyEventClassAttr, typeType, NULL, | ||
| 812 | &event_class, sizeof (AEEventClass), NULL); | ||
| 813 | if (err == noErr) | ||
| 814 | err = AEGetAttributePtr (apple_event, keyEventIDAttr, typeType, NULL, | ||
| 815 | &event_id, sizeof (AEEventID), NULL); | ||
| 816 | if (err == noErr) | ||
| 817 | { | ||
| 818 | mac_find_apple_event_spec (event_class, event_id, | ||
| 819 | &class_key, &id_key, &binding); | ||
| 820 | if (!NILP (binding) && !EQ (binding, Qundefined)) | ||
| 821 | { | ||
| 822 | if (INTEGERP (binding)) | ||
| 823 | return XINT (binding); | ||
| 824 | err = mac_handle_apple_event_1 (class_key, id_key, | ||
| 825 | apple_event, reply); | ||
| 826 | } | ||
| 827 | else | ||
| 828 | err = errAEEventNotHandled; | ||
| 829 | } | ||
| 830 | if (err == noErr) | ||
| 831 | return noErr; | ||
| 832 | else | ||
| 833 | return errAEEventNotHandled; | ||
| 834 | } | ||
| 835 | |||
| 836 | static int | ||
| 837 | cleanup_suspended_apple_events (head, all_p) | ||
| 838 | struct suspended_ae_info **head; | ||
| 839 | int all_p; | ||
| 840 | { | ||
| 841 | UInt32 current_tick = TickCount (), nresumed = 0; | ||
| 842 | struct suspended_ae_info *p, *next; | ||
| 843 | |||
| 844 | for (p = *head; p; p = next) | ||
| 845 | { | ||
| 846 | if (!all_p && p->expiration_tick > current_tick) | ||
| 847 | break; | ||
| 848 | AESetTheCurrentEvent (&p->apple_event); | ||
| 849 | AEResumeTheCurrentEvent (&p->apple_event, &p->reply, | ||
| 850 | (AEEventHandlerUPP) kAENoDispatch, 0); | ||
| 851 | AEDisposeDesc (&p->reply); | ||
| 852 | AEDisposeDesc (&p->apple_event); | ||
| 853 | nresumed++; | ||
| 854 | next = p->next; | ||
| 855 | xfree (p); | ||
| 856 | } | ||
| 857 | *head = p; | ||
| 858 | |||
| 859 | return nresumed; | ||
| 860 | } | ||
| 861 | |||
| 862 | void | ||
| 863 | cleanup_all_suspended_apple_events () | ||
| 864 | { | ||
| 865 | cleanup_suspended_apple_events (&deferred_apple_events, 1); | ||
| 866 | cleanup_suspended_apple_events (&suspended_apple_events, 1); | ||
| 867 | } | ||
| 868 | |||
| 869 | static UInt32 | ||
| 870 | get_suspension_id (apple_event) | ||
| 871 | Lisp_Object apple_event; | ||
| 872 | { | ||
| 873 | Lisp_Object tem; | ||
| 874 | |||
| 875 | CHECK_CONS (apple_event); | ||
| 876 | CHECK_STRING_CAR (apple_event); | ||
| 877 | if (SBYTES (XCAR (apple_event)) != 4 | ||
| 878 | || strcmp (SDATA (XCAR (apple_event)), "aevt") != 0) | ||
| 879 | error ("Not an apple event"); | ||
| 880 | |||
| 881 | tem = assq_no_quit (Qemacs_suspension_id, XCDR (apple_event)); | ||
| 882 | if (NILP (tem)) | ||
| 883 | error ("Suspension ID not available"); | ||
| 884 | |||
| 885 | tem = XCDR (tem); | ||
| 886 | if (!(CONSP (tem) | ||
| 887 | && STRINGP (XCAR (tem)) && SBYTES (XCAR (tem)) == 4 | ||
| 888 | && strcmp (SDATA (XCAR (tem)), "magn") == 0 | ||
| 889 | && STRINGP (XCDR (tem)) && SBYTES (XCDR (tem)) == 4)) | ||
| 890 | error ("Bad suspension ID format"); | ||
| 891 | |||
| 892 | return *((UInt32 *) SDATA (XCDR (tem))); | ||
| 893 | } | ||
| 894 | |||
| 895 | |||
| 896 | DEFUN ("mac-process-deferred-apple-events", Fmac_process_deferred_apple_events, Smac_process_deferred_apple_events, 0, 0, 0, | ||
| 897 | doc: /* Process Apple events that are deferred at the startup time. */) | ||
| 898 | () | ||
| 899 | { | ||
| 900 | if (mac_ready_for_apple_events) | ||
| 901 | return Qnil; | ||
| 902 | |||
| 903 | BLOCK_INPUT; | ||
| 904 | mac_ready_for_apple_events = 1; | ||
| 905 | if (deferred_apple_events) | ||
| 906 | { | ||
| 907 | struct suspended_ae_info *prev, *tail, *next; | ||
| 908 | |||
| 909 | /* `nreverse' deferred_apple_events. */ | ||
| 910 | prev = NULL; | ||
| 911 | for (tail = deferred_apple_events; tail; tail = next) | ||
| 912 | { | ||
| 913 | next = tail->next; | ||
| 914 | tail->next = prev; | ||
| 915 | prev = tail; | ||
| 916 | } | ||
| 917 | |||
| 918 | /* Now `prev' points to the first cell. */ | ||
| 919 | for (tail = prev; tail; tail = next) | ||
| 920 | { | ||
| 921 | next = tail->next; | ||
| 922 | AEResumeTheCurrentEvent (&tail->apple_event, &tail->reply, | ||
| 923 | ((AEEventHandlerUPP) | ||
| 924 | kAEUseStandardDispatch), 0); | ||
| 925 | AEDisposeDesc (&tail->reply); | ||
| 926 | AEDisposeDesc (&tail->apple_event); | ||
| 927 | xfree (tail); | ||
| 928 | } | ||
| 929 | |||
| 930 | deferred_apple_events = NULL; | ||
| 931 | } | ||
| 932 | UNBLOCK_INPUT; | ||
| 933 | |||
| 934 | return Qt; | ||
| 935 | } | ||
| 936 | |||
| 937 | DEFUN ("mac-cleanup-expired-apple-events", Fmac_cleanup_expired_apple_events, Smac_cleanup_expired_apple_events, 0, 0, 0, | ||
| 938 | doc: /* Clean up expired Apple events. | ||
| 939 | Return the number of expired events. */) | ||
| 940 | () | ||
| 941 | { | ||
| 942 | int nexpired; | ||
| 943 | |||
| 944 | BLOCK_INPUT; | ||
| 945 | nexpired = cleanup_suspended_apple_events (&suspended_apple_events, 0); | ||
| 946 | UNBLOCK_INPUT; | ||
| 947 | |||
| 948 | return make_number (nexpired); | ||
| 949 | } | ||
| 950 | |||
| 951 | DEFUN ("mac-ae-set-reply-parameter", Fmac_ae_set_reply_parameter, Smac_ae_set_reply_parameter, 3, 3, 0, | ||
| 952 | doc: /* Set parameter KEYWORD to DESCRIPTOR on reply of APPLE-EVENT. | ||
| 953 | KEYWORD is a 4-byte string. DESCRIPTOR is a Lisp representation of an | ||
| 954 | Apple event descriptor. It has the form of (TYPE . DATA), where TYPE | ||
| 955 | is a 4-byte string. Valid format of DATA is as follows: | ||
| 956 | |||
| 957 | * If TYPE is "null", then DATA is nil. | ||
| 958 | * If TYPE is "list", then DATA is a list (DESCRIPTOR1 ... DESCRIPTORn). | ||
| 959 | * If TYPE is "reco", then DATA is a list ((KEYWORD1 . DESCRIPTOR1) | ||
| 960 | ... (KEYWORDn . DESCRIPTORn)). | ||
| 961 | * If TYPE is "aevt", then DATA is ignored and the descriptor is | ||
| 962 | treated as null. | ||
| 963 | * Otherwise, DATA is a string. | ||
| 964 | |||
| 965 | If a (sub-)descriptor is in an invalid format, it is silently treated | ||
| 966 | as null. | ||
| 967 | |||
| 968 | Return t if the parameter is successfully set. Otherwise return nil. */) | ||
| 969 | (apple_event, keyword, descriptor) | ||
| 970 | Lisp_Object apple_event, keyword, descriptor; | ||
| 971 | { | ||
| 972 | Lisp_Object result = Qnil; | ||
| 973 | UInt32 suspension_id; | ||
| 974 | struct suspended_ae_info *p; | ||
| 975 | |||
| 976 | suspension_id = get_suspension_id (apple_event); | ||
| 977 | |||
| 978 | CHECK_STRING (keyword); | ||
| 979 | if (SBYTES (keyword) != 4) | ||
| 980 | error ("Apple event keyword must be a 4-byte string: %s", | ||
| 981 | SDATA (keyword)); | ||
| 982 | |||
| 983 | BLOCK_INPUT; | ||
| 984 | for (p = suspended_apple_events; p; p = p->next) | ||
| 985 | if (p->suspension_id == suspension_id) | ||
| 986 | break; | ||
| 987 | if (p && p->reply.descriptorType != typeNull) | ||
| 988 | { | ||
| 989 | OSErr err; | ||
| 990 | |||
| 991 | err = mac_ae_put_lisp (&p->reply, | ||
| 992 | EndianU32_BtoN (*((UInt32 *) SDATA (keyword))), | ||
| 993 | descriptor); | ||
| 994 | if (err == noErr) | ||
| 995 | result = Qt; | ||
| 996 | } | ||
| 997 | UNBLOCK_INPUT; | ||
| 998 | |||
| 999 | return result; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | DEFUN ("mac-resume-apple-event", Fmac_resume_apple_event, Smac_resume_apple_event, 1, 2, 0, | ||
| 1003 | doc: /* Resume handling of APPLE-EVENT. | ||
| 1004 | Every Apple event handled by the Lisp interpreter is suspended first. | ||
| 1005 | This function resumes such a suspended event either to complete Apple | ||
| 1006 | event handling to give a reply, or to redispatch it to other handlers. | ||
| 1007 | |||
| 1008 | If optional ERROR-CODE is an integer, it specifies the error number | ||
| 1009 | that is set in the reply. If ERROR-CODE is t, the resumed event is | ||
| 1010 | handled with the standard dispatching mechanism, but it is not handled | ||
| 1011 | by Emacs again, thus it is redispatched to other handlers. | ||
| 1012 | |||
| 1013 | Return t if APPLE-EVENT is successfully resumed. Otherwise return | ||
| 1014 | nil, which means the event is already resumed or expired. */) | ||
| 1015 | (apple_event, error_code) | ||
| 1016 | Lisp_Object apple_event, error_code; | ||
| 1017 | { | ||
| 1018 | Lisp_Object result = Qnil; | ||
| 1019 | UInt32 suspension_id; | ||
| 1020 | struct suspended_ae_info **p, *ae; | ||
| 1021 | |||
| 1022 | suspension_id = get_suspension_id (apple_event); | ||
| 1023 | |||
| 1024 | BLOCK_INPUT; | ||
| 1025 | for (p = &suspended_apple_events; *p; p = &(*p)->next) | ||
| 1026 | if ((*p)->suspension_id == suspension_id) | ||
| 1027 | break; | ||
| 1028 | if (*p) | ||
| 1029 | { | ||
| 1030 | ae = *p; | ||
| 1031 | *p = (*p)->next; | ||
| 1032 | if (INTEGERP (error_code) | ||
| 1033 | && ae->reply.descriptorType != typeNull) | ||
| 1034 | { | ||
| 1035 | SInt32 errn = XINT (error_code); | ||
| 1036 | |||
| 1037 | AEPutParamPtr (&ae->reply, keyErrorNumber, typeSInt32, | ||
| 1038 | &errn, sizeof (SInt32)); | ||
| 1039 | } | ||
| 1040 | AESetTheCurrentEvent (&ae->apple_event); | ||
| 1041 | AEResumeTheCurrentEvent (&ae->apple_event, &ae->reply, | ||
| 1042 | ((AEEventHandlerUPP) | ||
| 1043 | (EQ (error_code, Qt) ? | ||
| 1044 | kAEUseStandardDispatch : kAENoDispatch)), | ||
| 1045 | 0); | ||
| 1046 | AEDisposeDesc (&ae->reply); | ||
| 1047 | AEDisposeDesc (&ae->apple_event); | ||
| 1048 | xfree (ae); | ||
| 1049 | result = Qt; | ||
| 1050 | } | ||
| 1051 | UNBLOCK_INPUT; | ||
| 1052 | |||
| 1053 | return result; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | |||
| 1057 | /*********************************************************************** | ||
| 1058 | Drag and drop support | ||
| 1059 | ***********************************************************************/ | ||
| 1060 | #if TARGET_API_MAC_CARBON | ||
| 1061 | Lisp_Object Vmac_dnd_known_types; | ||
| 1062 | #endif /* TARGET_API_MAC_CARBON */ | ||
| 1063 | |||
| 1064 | |||
| 1065 | /*********************************************************************** | ||
| 1066 | Services menu support | ||
| 1067 | ***********************************************************************/ | ||
| 1068 | #ifdef MAC_OSX | ||
| 1069 | /* Selection name for communication via Services menu. */ | ||
| 1070 | Lisp_Object Vmac_service_selection; | ||
| 1071 | #endif | ||
| 1072 | |||
| 1073 | void | ||
| 1074 | syms_of_macselect () | ||
| 1075 | { | ||
| 1076 | defsubr (&Sx_get_selection_internal); | ||
| 1077 | defsubr (&Sx_own_selection_internal); | ||
| 1078 | defsubr (&Sx_disown_selection_internal); | ||
| 1079 | defsubr (&Sx_selection_owner_p); | ||
| 1080 | defsubr (&Sx_selection_exists_p); | ||
| 1081 | defsubr (&Smac_process_deferred_apple_events); | ||
| 1082 | defsubr (&Smac_cleanup_expired_apple_events); | ||
| 1083 | defsubr (&Smac_resume_apple_event); | ||
| 1084 | defsubr (&Smac_ae_set_reply_parameter); | ||
| 1085 | |||
| 1086 | Vselection_alist = Qnil; | ||
| 1087 | staticpro (&Vselection_alist); | ||
| 1088 | |||
| 1089 | DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist, | ||
| 1090 | doc: /* An alist associating selection-types with functions. | ||
| 1091 | These functions are called to convert the selection, with three args: | ||
| 1092 | the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD'); | ||
| 1093 | a desired type to which the selection should be converted; | ||
| 1094 | and the local selection value (whatever was given to `x-own-selection'). | ||
| 1095 | |||
| 1096 | The function should return the value to send to the Scrap Manager | ||
| 1097 | \(must be a string). A return value of nil | ||
| 1098 | means that the conversion could not be done. */); | ||
| 1099 | Vselection_converter_alist = Qnil; | ||
| 1100 | |||
| 1101 | DEFVAR_LISP ("x-lost-selection-functions", &Vx_lost_selection_functions, | ||
| 1102 | doc: /* A list of functions to be called when Emacs loses a selection. | ||
| 1103 | \(This happens when a Lisp program explicitly clears the selection.) | ||
| 1104 | The functions are called with one argument, the selection type | ||
| 1105 | \(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */); | ||
| 1106 | Vx_lost_selection_functions = Qnil; | ||
| 1107 | |||
| 1108 | DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system, | ||
| 1109 | doc: /* Coding system for communicating with other programs. | ||
| 1110 | When sending or receiving text via cut_buffer, selection, and clipboard, | ||
| 1111 | the text is encoded or decoded by this coding system. | ||
| 1112 | The default value is determined by the system script code. */); | ||
| 1113 | Vselection_coding_system = Qnil; | ||
| 1114 | |||
| 1115 | DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, | ||
| 1116 | doc: /* Coding system for the next communication with other programs. | ||
| 1117 | Usually, `selection-coding-system' is used for communicating with | ||
| 1118 | other programs. But, if this variable is set, it is used for the | ||
| 1119 | next communication only. After the communication, this variable is | ||
| 1120 | set to nil. */); | ||
| 1121 | Vnext_selection_coding_system = Qnil; | ||
| 1122 | |||
| 1123 | DEFVAR_LISP ("mac-apple-event-map", &Vmac_apple_event_map, | ||
| 1124 | doc: /* Keymap for Apple events handled by Emacs. */); | ||
| 1125 | Vmac_apple_event_map = Qnil; | ||
| 1126 | |||
| 1127 | #if TARGET_API_MAC_CARBON | ||
| 1128 | DEFVAR_LISP ("mac-dnd-known-types", &Vmac_dnd_known_types, | ||
| 1129 | doc: /* The types accepted by default for dropped data. | ||
| 1130 | The types are chosen in the order they appear in the list. */); | ||
| 1131 | Vmac_dnd_known_types = mac_dnd_default_known_types (); | ||
| 1132 | #endif | ||
| 1133 | |||
| 1134 | #ifdef MAC_OSX | ||
| 1135 | DEFVAR_LISP ("mac-service-selection", &Vmac_service_selection, | ||
| 1136 | doc: /* Selection name for communication via Services menu. */); | ||
| 1137 | Vmac_service_selection = intern ("PRIMARY"); | ||
| 1138 | #endif | ||
| 1139 | |||
| 1140 | QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY); | ||
| 1141 | QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY); | ||
| 1142 | QTIMESTAMP = intern ("TIMESTAMP"); staticpro (&QTIMESTAMP); | ||
| 1143 | QTARGETS = intern ("TARGETS"); staticpro (&QTARGETS); | ||
| 1144 | |||
| 1145 | Qforeign_selection = intern ("foreign-selection"); | ||
| 1146 | staticpro (&Qforeign_selection); | ||
| 1147 | |||
| 1148 | Qmac_scrap_name = intern ("mac-scrap-name"); | ||
| 1149 | staticpro (&Qmac_scrap_name); | ||
| 1150 | |||
| 1151 | Qmac_ostype = intern ("mac-ostype"); | ||
| 1152 | staticpro (&Qmac_ostype); | ||
| 1153 | |||
| 1154 | Qmac_apple_event_class = intern ("mac-apple-event-class"); | ||
| 1155 | staticpro (&Qmac_apple_event_class); | ||
| 1156 | |||
| 1157 | Qmac_apple_event_id = intern ("mac-apple-event-id"); | ||
| 1158 | staticpro (&Qmac_apple_event_id); | ||
| 1159 | |||
| 1160 | Qemacs_suspension_id = intern ("emacs-suspension-id"); | ||
| 1161 | staticpro (&Qemacs_suspension_id); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | /* arch-tag: f3c91ad8-99e0-4bd6-9eef-251b2f848732 | ||
| 1165 | (do not change this comment) */ | ||