blob: 96f04c55a31a4f5e911d99b71412fad14701cc97 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 * GUI/Motif support by Robert Webb
5 * Macintosh port by Dany St-Amant
6 * and Axel Kielhorn
Bram Moolenaar79ee3152007-04-26 16:20:50 +00007 * Port to MPW by Bernhard Pruemmer
Bram Moolenaar071d4272004-06-13 20:20:40 +00008 * Initial Carbon port by Ammon Skidmore
9 *
10 * Do ":help uganda" in Vim to read copying and usage conditions.
11 * Do ":help credits" in Vim to see a list of people who contributed.
12 * See README.txt for an overview of the Vim source code.
13 */
14
15/*
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000016 * NOTES: - Vim 7+ does not support classic MacOS. Please use Vim 6.x
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000017 * - Comments mentioning FAQ refer to the book:
18 * "Macworld Mac Programming FAQs" from "IDG Books"
Bram Moolenaar071d4272004-06-13 20:20:40 +000019 */
20
21/*
22 * TODO: Change still to merge from the macvim's iDisk
23 *
24 * error_ga, mch_errmsg, Navigation's changes in gui_mch_browse
25 * uses of MenuItemIndex, changes in gui_mch_set_shellsize,
26 * ScrapManager error handling.
27 * Comments about function remaining to Carbonize.
28 *
29 */
30
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +000031/* TODO (Jussi)
32 * * Clipboard does not work (at least some cases)
33 * * ATSU font rendering has some problems
34 * * Investigate and remove dead code (there is still lots of that)
35 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000036
37#include <Devices.h> /* included first to avoid CR problems */
38#include "vim.h"
39
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000040#define USE_CARBONIZED
41#define USE_AEVENT /* Enable AEVENT */
42#undef USE_OFFSETED_WINDOW /* Debugging feature: start Vim window OFFSETed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000043
Bram Moolenaar84a05ac2013-05-06 04:24:17 +020044/* Compile as CodeWarrior External Editor */
Bram Moolenaar071d4272004-06-13 20:20:40 +000045#if defined(FEAT_CW_EDITOR) && !defined(USE_AEVENT)
46# define USE_AEVENT /* Need Apple Event Support */
47#endif
48
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000049/* Vim's Scrap flavor. */
50#define VIMSCRAPFLAVOR 'VIM!'
Bram Moolenaarfc1421e2006-04-20 22:17:20 +000051#ifdef FEAT_MBYTE
52# define SCRAPTEXTFLAVOR kScrapFlavorTypeUnicode
53#else
54# define SCRAPTEXTFLAVOR kScrapFlavorTypeText
55#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000056
Bram Moolenaar071d4272004-06-13 20:20:40 +000057static EventHandlerUPP mouseWheelHandlerUPP = NULL;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000058SInt32 gMacSystemVersion;
Bram Moolenaar071d4272004-06-13 20:20:40 +000059
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +000060#ifdef MACOS_CONVERT
61# define USE_CARBONKEYHANDLER
Bram Moolenaar1b60e502008-03-12 13:40:54 +000062
63static int im_is_active = FALSE;
Bram Moolenaar259f26a2018-05-15 22:25:40 +020064# if 0
Bram Moolenaared39e1d2008-08-09 17:55:22 +000065 /* TODO: Implement me! */
Bram Moolenaar1b60e502008-03-12 13:40:54 +000066static int im_start_row = 0;
67static int im_start_col = 0;
Bram Moolenaar259f26a2018-05-15 22:25:40 +020068# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +000069
Bram Moolenaar259f26a2018-05-15 22:25:40 +020070# define NR_ELEMS(x) (sizeof(x) / sizeof(x[0]))
Bram Moolenaar1b60e502008-03-12 13:40:54 +000071
72static TSMDocumentID gTSMDocument;
73
74static void im_on_window_switch(int active);
Bram Moolenaar26a60b42005-02-22 08:49:11 +000075static EventHandlerUPP keyEventHandlerUPP = NULL;
Bram Moolenaar1b60e502008-03-12 13:40:54 +000076static EventHandlerUPP winEventHandlerUPP = NULL;
77
78static pascal OSStatus gui_mac_handle_window_activate(
79 EventHandlerCallRef nextHandler, EventRef theEvent, void *data);
80
81static pascal OSStatus gui_mac_handle_text_input(
82 EventHandlerCallRef nextHandler, EventRef theEvent, void *data);
83
84static pascal OSStatus gui_mac_update_input_area(
85 EventHandlerCallRef nextHandler, EventRef theEvent);
86
87static pascal OSStatus gui_mac_unicode_key_event(
88 EventHandlerCallRef nextHandler, EventRef theEvent);
89
Bram Moolenaar26a60b42005-02-22 08:49:11 +000090#endif
91
Bram Moolenaar071d4272004-06-13 20:20:40 +000092
93/* Include some file. TODO: move into os_mac.h */
94#include <Menus.h>
95#include <Resources.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000096#include <Processes.h>
97#ifdef USE_AEVENT
98# include <AppleEvents.h>
99# include <AERegistry.h>
100#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000101# include <Gestalt.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000102#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
103# include <ControlDefinitions.h>
104# include <Navigation.h> /* Navigation only part of ?? */
105#endif
106
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000107/* Help Manager (balloon.h, HM prefixed functions) are not supported
108 * under Carbon (Jussi) */
109# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000110/* New Help Interface for Mac, not implemented yet.*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000111# include <MacHelp.h>
112# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000113
114/*
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000115 * These seem to be rectangle options. Why are they not found in
116 * headers? (Jussi)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000117 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000118#define kNothing 0
119#define kCreateEmpty 2 /*1*/
120#define kCreateRect 2
121#define kDestroy 3
122
123/*
124 * Dany: Don't like those...
125 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000126#define topLeft(r) (((Point*)&(r))[0])
127#define botRight(r) (((Point*)&(r))[1])
128
129
130/* Time of last mouse click, to detect double-click */
131static long lastMouseTick = 0;
132
133/* ??? */
134static RgnHandle cursorRgn;
135static RgnHandle dragRgn;
136static Rect dragRect;
137static short dragRectEnbl;
138static short dragRectControl;
139
140/* This variable is set when waiting for an event, which is the only moment
141 * scrollbar dragging can be done directly. It's not allowed while commands
142 * are executed, because it may move the cursor and that may cause unexpected
143 * problems (e.g., while ":s" is working).
144 */
145static int allow_scrollbar = FALSE;
146
147/* Last mouse click caused contextual menu, (to provide proper release) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000148static short clickIsPopup;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000149
150/* Feedback Action for Scrollbar */
151ControlActionUPP gScrollAction;
152ControlActionUPP gScrollDrag;
153
154/* Keeping track of which scrollbar is being dragged */
155static ControlHandle dragged_sb = NULL;
156
Bram Moolenaarc52da9d2008-03-20 13:39:37 +0000157/* Vector of char_u --> control index for hotkeys in dialogs */
158static short *gDialogHotKeys;
159
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000160static struct
161{
162 FMFontFamily family;
163 FMFontSize size;
164 FMFontStyle style;
165 Boolean isPanelVisible;
166} gFontPanelInfo = { 0, 0, 0, false };
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000167
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000168#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000169# define USE_ATSUI_DRAWING
Bram Moolenaar1b60e502008-03-12 13:40:54 +0000170int p_macatsui_last;
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000171ATSUStyle gFontStyle;
Bram Moolenaar1b60e502008-03-12 13:40:54 +0000172# ifdef FEAT_MBYTE
173ATSUStyle gWideFontStyle;
174# endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000175Boolean gIsFontFallbackSet;
Bram Moolenaar76b96fc2010-07-17 16:44:59 +0200176UInt32 useAntialias_cached = 0x0;
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000177#endif
178
Bram Moolenaar071d4272004-06-13 20:20:40 +0000179/* Colors Macros */
180#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
181#define Red(c) ((c & 0x00FF0000) >> 16)
182#define Green(c) ((c & 0x0000FF00) >> 8)
183#define Blue(c) ((c & 0x000000FF) >> 0)
184
185/* Key mapping */
186
187#define vk_Esc 0x35 /* -> 1B */
188
189#define vk_F1 0x7A /* -> 10 */
190#define vk_F2 0x78 /*0x63*/
191#define vk_F3 0x63 /*0x76*/
192#define vk_F4 0x76 /*0x60*/
193#define vk_F5 0x60 /*0x61*/
194#define vk_F6 0x61 /*0x62*/
195#define vk_F7 0x62 /*0x63*/ /*?*/
196#define vk_F8 0x64
197#define vk_F9 0x65
198#define vk_F10 0x6D
199#define vk_F11 0x67
200#define vk_F12 0x6F
201#define vk_F13 0x69
202#define vk_F14 0x6B
203#define vk_F15 0x71
204
205#define vk_Clr 0x47 /* -> 1B (ESC) */
206#define vk_Enter 0x4C /* -> 03 */
207
208#define vk_Space 0x31 /* -> 20 */
209#define vk_Tab 0x30 /* -> 09 */
210#define vk_Return 0x24 /* -> 0D */
211/* This is wrong for OSX, what is it for? */
212#define vk_Delete 0X08 /* -> 08 BackSpace */
213
214#define vk_Help 0x72 /* -> 05 */
215#define vk_Home 0x73 /* -> 01 */
216#define vk_PageUp 0x74 /* -> 0D */
217#define vk_FwdDelete 0x75 /* -> 7F */
218#define vk_End 0x77 /* -> 04 */
219#define vk_PageDown 0x79 /* -> 0C */
220
221#define vk_Up 0x7E /* -> 1E */
222#define vk_Down 0x7D /* -> 1F */
223#define vk_Left 0x7B /* -> 1C */
224#define vk_Right 0x7C /* -> 1D */
225
226#define vk_Undo vk_F1
227#define vk_Cut vk_F2
228#define vk_Copy vk_F3
229#define vk_Paste vk_F4
230#define vk_PrintScreen vk_F13
231#define vk_SCrollLock vk_F14
232#define vk_Pause vk_F15
233#define vk_NumLock vk_Clr
234#define vk_Insert vk_Help
235
236#define KeySym char
237
238static struct
239{
240 KeySym key_sym;
241 char_u vim_code0;
242 char_u vim_code1;
243} special_keys[] =
244{
245 {vk_Up, 'k', 'u'},
246 {vk_Down, 'k', 'd'},
247 {vk_Left, 'k', 'l'},
248 {vk_Right, 'k', 'r'},
249
250 {vk_F1, 'k', '1'},
251 {vk_F2, 'k', '2'},
252 {vk_F3, 'k', '3'},
253 {vk_F4, 'k', '4'},
254 {vk_F5, 'k', '5'},
255 {vk_F6, 'k', '6'},
256 {vk_F7, 'k', '7'},
257 {vk_F8, 'k', '8'},
258 {vk_F9, 'k', '9'},
259 {vk_F10, 'k', ';'},
260
261 {vk_F11, 'F', '1'},
262 {vk_F12, 'F', '2'},
263 {vk_F13, 'F', '3'},
264 {vk_F14, 'F', '4'},
265 {vk_F15, 'F', '5'},
266
267/* {XK_Help, '%', '1'}, */
268/* {XK_Undo, '&', '8'}, */
269/* {XK_BackSpace, 'k', 'b'}, */
Bram Moolenaard0573012017-10-28 21:11:06 +0200270/* {vk_Delete, 'k', 'b'}, */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000271 {vk_Insert, 'k', 'I'},
272 {vk_FwdDelete, 'k', 'D'},
273 {vk_Home, 'k', 'h'},
274 {vk_End, '@', '7'},
275/* {XK_Prior, 'k', 'P'}, */
276/* {XK_Next, 'k', 'N'}, */
277/* {XK_Print, '%', '9'}, */
278
279 {vk_PageUp, 'k', 'P'},
280 {vk_PageDown, 'k', 'N'},
281
282 /* End of list marker: */
283 {(KeySym)0, 0, 0}
284};
285
286/*
287 * ------------------------------------------------------------
288 * Forward declaration (for those needed)
289 * ------------------------------------------------------------
290 */
291
292#ifdef USE_AEVENT
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000293OSErr HandleUnusedParms(const AppleEvent *theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000294#endif
295
Bram Moolenaar79ee3152007-04-26 16:20:50 +0000296#ifdef FEAT_GUI_TABLINE
297static void initialise_tabline(void);
298static WindowRef drawer = NULL; // TODO: put into gui.h
299#endif
300
Bram Moolenaar1b60e502008-03-12 13:40:54 +0000301#ifdef USE_ATSUI_DRAWING
302static void gui_mac_set_font_attributes(GuiFont font);
Bram Moolenaar1b60e502008-03-12 13:40:54 +0000303#endif
304
Bram Moolenaar071d4272004-06-13 20:20:40 +0000305/*
306 * ------------------------------------------------------------
307 * Conversion Utility
308 * ------------------------------------------------------------
309 */
310
311/*
312 * C2Pascal_save
313 *
314 * Allocate memory and convert the C-String passed in
315 * into a pascal string
316 *
317 */
318
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000319 char_u *
320C2Pascal_save(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000321{
322 char_u *PascalString;
323 int len;
324
325 if (Cstring == NULL)
326 return NULL;
327
328 len = STRLEN(Cstring);
329
330 if (len > 255) /* Truncate if necessary */
331 len = 255;
332
333 PascalString = alloc(len + 1);
334 if (PascalString != NULL)
335 {
336 mch_memmove(PascalString + 1, Cstring, len);
337 PascalString[0] = len;
338 }
339
340 return PascalString;
341}
342
343/*
344 * C2Pascal_save_and_remove_backslash
345 *
346 * Allocate memory and convert the C-String passed in
347 * into a pascal string. Also remove the backslash at the same time
348 *
349 */
350
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000351 char_u *
352C2Pascal_save_and_remove_backslash(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000353{
354 char_u *PascalString;
355 int len;
356 char_u *p, *c;
357
358 len = STRLEN(Cstring);
359
360 if (len > 255) /* Truncate if necessary */
361 len = 255;
362
363 PascalString = alloc(len + 1);
364 if (PascalString != NULL)
365 {
366 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
367 {
368 if ((*c == '\\') && (c[1] != 0))
369 {
370 c++;
371 }
372 *p = *c;
373 p++;
374 len++;
375 }
376 PascalString[0] = len;
377 }
378
379 return PascalString;
380}
381
382/*
383 * Convert the modifiers of an Event into vim's modifiers (mouse)
384 */
385
386 int_u
387EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
388{
389 int_u vimModifiers = 0x00;
390
391 if (macModifiers & (shiftKey | rightShiftKey))
392 vimModifiers |= MOUSE_SHIFT;
393 if (macModifiers & (controlKey | rightControlKey))
394 vimModifiers |= MOUSE_CTRL;
395 if (macModifiers & (optionKey | rightOptionKey))
396 vimModifiers |= MOUSE_ALT;
397#if 0
398 /* Not yet supported */
399 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
400 vimModifiers |= MOUSE_CMD;
401#endif
402 return (vimModifiers);
403}
404
405/*
406 * Convert the modifiers of an Event into vim's modifiers (keys)
407 */
408
409 static int_u
410EventModifiers2VimModifiers(EventModifiers macModifiers)
411{
412 int_u vimModifiers = 0x00;
413
414 if (macModifiers & (shiftKey | rightShiftKey))
415 vimModifiers |= MOD_MASK_SHIFT;
416 if (macModifiers & (controlKey | rightControlKey))
417 vimModifiers |= MOD_MASK_CTRL;
418 if (macModifiers & (optionKey | rightOptionKey))
419 vimModifiers |= MOD_MASK_ALT;
420#ifdef USE_CMD_KEY
421 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
422 vimModifiers |= MOD_MASK_CMD;
423#endif
424 return (vimModifiers);
425}
426
427/* Convert a string representing a point size into pixels. The string should
428 * be a positive decimal number, with an optional decimal point (eg, "12", or
429 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
430 * character is stored in *end. The flag "vertical" says whether this
431 * calculation is for a vertical (height) size or a horizontal (width) one.
432 *
433 * From gui_w48.c
434 */
435 static int
436points_to_pixels(char_u *str, char_u **end, int vertical)
437{
438 int pixels;
439 int points = 0;
440 int divisor = 0;
441
442 while (*str)
443 {
444 if (*str == '.' && divisor == 0)
445 {
446 /* Start keeping a divisor, for later */
447 divisor = 1;
448 continue;
449 }
450
451 if (!isdigit(*str))
452 break;
453
454 points *= 10;
455 points += *str - '0';
456 divisor *= 10;
457
458 ++str;
459 }
460
461 if (divisor == 0)
462 divisor = 1;
463
464 pixels = points/divisor;
465 *end = str;
466 return pixels;
467}
468
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000469#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000470/*
471 * Deletes all traces of any Windows-style mnemonic text (including any
472 * parentheses) from a menu item and returns the cleaned menu item title.
473 * The caller is responsible for releasing the returned string.
474 */
475 static CFStringRef
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000476menu_title_removing_mnemonic(vimmenu_T *menu)
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000477{
478 CFStringRef name;
479 size_t menuTitleLen;
480 CFIndex displayLen;
481 CFRange mnemonicStart;
482 CFRange mnemonicEnd;
483 CFMutableStringRef cleanedName;
484
485 menuTitleLen = STRLEN(menu->dname);
Bram Moolenaar446cb832008-06-24 21:56:24 +0000486 name = (CFStringRef) mac_enc_to_cfstring(menu->dname, menuTitleLen);
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000487
488 if (name)
489 {
490 /* Simple mnemonic-removal algorithm, assumes single parenthesized
491 * mnemonic character towards the end of the menu text */
492 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
493 displayLen = CFStringGetLength(name);
494
495 if (mnemonicStart.location != kCFNotFound
496 && (mnemonicStart.location + 2) < displayLen
497 && CFStringGetCharacterAtIndex(name,
498 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
499 {
500 if (CFStringFindWithOptions(name, CFSTR(")"),
501 CFRangeMake(mnemonicStart.location + 1,
502 displayLen - mnemonicStart.location - 1),
503 kCFCompareBackwards, &mnemonicEnd) &&
504 (mnemonicStart.location + 2) == mnemonicEnd.location)
505 {
506 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
507 if (cleanedName)
508 {
509 CFStringDelete(cleanedName,
510 CFRangeMake(mnemonicStart.location,
511 mnemonicEnd.location + 1 -
512 mnemonicStart.location));
513
514 CFRelease(name);
515 name = cleanedName;
516 }
517 }
518 }
519 }
520
521 return name;
522}
523#endif
524
Bram Moolenaar071d4272004-06-13 20:20:40 +0000525/*
526 * Convert a list of FSSpec aliases into a list of fullpathname
527 * character strings.
528 */
529
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000530 char_u **
531new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000532{
533 char_u **fnames = NULL;
534 OSErr newError;
535 long fileCount;
536 FSSpec fileToOpen;
537 long actualSize;
538 AEKeyword dummyKeyword;
539 DescType dummyType;
540
541 /* Get number of files in list */
542 *error = AECountItems(theList, numFiles);
543 if (*error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000544 return fnames;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000545
546 /* Allocate the pointer list */
547 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
548
549 /* Empty out the list */
550 for (fileCount = 0; fileCount < *numFiles; fileCount++)
551 fnames[fileCount] = NULL;
552
553 /* Scan the list of FSSpec */
554 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
555 {
556 /* Get the alias for the nth file, convert to an FSSpec */
557 newError = AEGetNthPtr(theList, fileCount, typeFSS,
558 &dummyKeyword, &dummyType,
559 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
560 if (newError)
561 {
562 /* Caller is able to clean up */
563 /* TODO: Should be clean up or not? For safety. */
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000564 return fnames;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000565 }
566
567 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000568 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000569 }
570
571 return (fnames);
572}
573
574/*
575 * ------------------------------------------------------------
576 * CodeWarrior External Editor Support
577 * ------------------------------------------------------------
578 */
579#ifdef FEAT_CW_EDITOR
580
581/*
582 * Handle the Window Search event from CodeWarrior
583 *
584 * Description
585 * -----------
586 *
587 * The IDE sends the Window Search AppleEvent to the editor when it
588 * needs to know whether a particular file is open in the editor.
589 *
590 * Event Reply
591 * -----------
592 *
593 * None. Put data in the location specified in the structure received.
594 *
595 * Remarks
596 * -------
597 *
598 * When the editor receives this event, determine whether the specified
599 * file is open. If it is, return the modification date/time for that file
600 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000601 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000602 *
603 */
604
Bram Moolenaar071d4272004-06-13 20:20:40 +0000605typedef struct WindowSearch WindowSearch;
606struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
607{
608 FSSpec theFile; // identifies the file
609 long *theDate; // where to put the modification date/time
610};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000611
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000612 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000613Handle_KAHL_SRCH_AE(
614 const AppleEvent *theAEvent,
615 AppleEvent *theReply,
616 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000617{
618 OSErr error = noErr;
619 buf_T *buf;
620 int foundFile = false;
621 DescType typeCode;
622 WindowSearch SearchData;
623 Size actualSize;
624
625 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
626 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000627 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000628
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000629 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000630 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000631 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000632
Bram Moolenaar29323592016-07-24 22:04:11 +0200633 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634 if (buf->b_ml.ml_mfp != NULL
635 && SearchData.theFile.parID == buf->b_FSSpec.parID
636 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
637 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
638 {
639 foundFile = true;
640 break;
641 }
642
643 if (foundFile == false)
644 *SearchData.theDate = fnfErr;
645 else
646 *SearchData.theDate = buf->b_mtime;
647
Bram Moolenaar071d4272004-06-13 20:20:40 +0000648 return error;
649};
650
651/*
652 * Handle the Modified (from IDE to Editor) event from CodeWarrior
653 *
654 * Description
655 * -----------
656 *
657 * The IDE sends this event to the external editor when it wants to
658 * know which files that are open in the editor have been modified.
659 *
660 * Parameters None.
661 * ----------
662 *
663 * Event Reply
664 * -----------
665 * The reply for this event is:
666 *
667 * keyDirectObject typeAEList required
668 * each element in the list is a structure of typeChar
669 *
670 * Remarks
671 * -------
672 *
673 * When building the reply event, include one element in the list for
674 * each open file that has been modified.
675 *
676 */
677
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678typedef struct ModificationInfo ModificationInfo;
679struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
680{
681 FSSpec theFile; // identifies the file
682 long theDate; // the date/time the file was last modified
683 short saved; // set this to zero when replying, unused
684};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000685
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000686 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000687Handle_KAHL_MOD_AE(
688 const AppleEvent *theAEvent,
689 AppleEvent *theReply,
690 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000691{
692 OSErr error = noErr;
693 AEDescList replyList;
694 long numFiles;
695 ModificationInfo theFile;
696 buf_T *buf;
697
698 theFile.saved = 0;
699
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000700 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000702 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703
704 /* Send the reply */
705/* replyObject.descriptorType = typeNull;
706 replyObject.dataHandle = nil;*/
707
708/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
709 error = AECreateList(nil, 0, false, &replyList);
710 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000711 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000712
713#if 0
714 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000715
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000716 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
717 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718 * sizeof(DescType))
719 */
720
721 /* AEPutDesc */
722#endif
723
724 numFiles = 0;
Bram Moolenaar29323592016-07-24 22:04:11 +0200725 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000726 if (buf->b_ml.ml_mfp != NULL)
727 {
728 /* Add this file to the list */
729 theFile.theFile = buf->b_FSSpec;
730 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000731/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
732 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000733 };
734
Bram Moolenaar071d4272004-06-13 20:20:40 +0000735#if 0
736 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000737#endif
738
739 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000740 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000741
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742 if (replyList.dataHandle)
743 AEDisposeDesc(&replyList);
744
745 return error;
746};
747
748/*
749 * Handle the Get Text event from CodeWarrior
750 *
751 * Description
752 * -----------
753 *
754 * The IDE sends the Get Text AppleEvent to the editor when it needs
755 * the source code from a file. For example, when the user issues a
756 * Check Syntax or Compile command, the compiler needs access to
757 * the source code contained in the file.
758 *
759 * Event Reply
760 * -----------
761 *
762 * None. Put data in locations specified in the structure received.
763 *
764 * Remarks
765 * -------
766 *
767 * When the editor receives this event, it must set the size of the handle
768 * in theText to fit the data in the file. It must then copy the entire
769 * contents of the specified file into the memory location specified in
770 * theText.
771 *
772 */
773
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774typedef struct CW_GetText CW_GetText;
775struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
776{
777 FSSpec theFile; /* identifies the file */
778 Handle theText; /* the location where you return the text (must be resized properly) */
779 long *unused; /* 0 (not used) */
780 long *theDate; /* where to put the modification date/time */
781};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000783 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000784Handle_KAHL_GTTX_AE(
785 const AppleEvent *theAEvent,
786 AppleEvent *theReply,
787 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788{
789 OSErr error = noErr;
790 buf_T *buf;
791 int foundFile = false;
792 DescType typeCode;
793 CW_GetText GetTextData;
794 Size actualSize;
795 char_u *line;
796 char_u *fullbuffer = NULL;
797 long linesize;
798 long lineStart;
799 long BufferSize;
800 long lineno;
801
802 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
803
804 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000805 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000806
Bram Moolenaar29323592016-07-24 22:04:11 +0200807 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808 if (buf->b_ml.ml_mfp != NULL)
809 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
810 {
811 foundFile = true;
812 break;
813 }
814
815 if (foundFile)
816 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000817 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
819 {
820 /* Must use the right buffer */
821 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
822 linesize = STRLEN(line) + 1;
823 lineStart = BufferSize;
824 BufferSize += linesize;
825 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000826 SetHandleSize(GetTextData.theText, BufferSize);
827 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000829 break; /* Simple handling for now */
830 }
831 else
832 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000833 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000835 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000837 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838 }
839 }
840 if (fullbuffer != NULL)
841 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000842 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000843 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000844 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 }
846 if (foundFile == false)
847 *GetTextData.theDate = fnfErr;
848 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000849/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000850 *GetTextData.theDate = buf->b_mtime;
851 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000853 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000855 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856}
857
858/*
859 *
860 */
861
862/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000863 pascal OSErr
864FindProcessBySignature(
865 const OSType targetType,
866 const OSType targetCreator,
867 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000868{
869 OSErr anErr = noErr;
870 Boolean lookingForProcess = true;
871
872 ProcessInfoRec infoRec;
873
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000874 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875 infoRec.processName = nil;
876 infoRec.processAppSpec = nil;
877
878 psnPtr->lowLongOfPSN = kNoProcess;
879 psnPtr->highLongOfPSN = kNoProcess;
880
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000881 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000883 anErr = GetNextProcess(psnPtr);
884 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000885 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000886 else
887 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000888 anErr = GetProcessInformation(psnPtr, &infoRec);
889 if ((anErr == noErr)
890 && (infoRec.processType == targetType)
891 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000892 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 }
894 }
895
896 return anErr;
897}//end FindProcessBySignature
898
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000899 void
900Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000901{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000902 OSErr anErr = noErr;
903 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +0000904 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
905 AppleEvent theReply = { typeNull, nil };
906 AESendMode sendMode;
907 AppleEvent theEvent = {typeNull, nil };
908 AEIdleUPP idleProcUPP = nil;
909 ModificationInfo ModData;
910
911
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000912 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000913 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000914 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000915 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
916 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000918 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919 {
920 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
921 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
922 }
923
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000924 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925
926 /* Add the parms */
927 ModData.theFile = buf->b_FSSpec;
928 ModData.theDate = buf->b_mtime;
929
930 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000931 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000932
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000933 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000934 sendMode = kAENoReply;
935 else
936 sendMode = kAEWaitReply;
937
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000938 if (anErr == noErr)
939 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
940 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000941 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000942/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000943 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000944 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000945 }
946}
947#endif /* FEAT_CW_EDITOR */
948
949/*
950 * ------------------------------------------------------------
951 * Apple Event Handling procedure
952 * ------------------------------------------------------------
953 */
954#ifdef USE_AEVENT
955
956/*
957 * Handle the Unused parms of an AppleEvent
958 */
959
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000960 OSErr
961HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000962{
963 OSErr error;
964 long actualSize;
965 DescType dummyType;
966 AEKeyword missedKeyword;
967
968 /* Get the "missed keyword" attribute from the AppleEvent. */
969 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
970 typeKeyword, &dummyType,
971 (Ptr)&missedKeyword, sizeof(missedKeyword),
972 &actualSize);
973
974 /* If the descriptor isn't found, then we got the required parameters. */
975 if (error == errAEDescNotFound)
976 {
977 error = noErr;
978 }
979 else
980 {
981#if 0
982 /* Why is this removed? */
983 error = errAEEventNotHandled;
984#endif
985 }
986
987 return error;
988}
989
990
991/*
992 * Handle the ODoc AppleEvent
993 *
994 * Deals with all files dragged to the application icon.
995 *
996 */
997
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998typedef struct SelectionRange SelectionRange;
999struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
1000{
1001 short unused1; // 0 (not used)
1002 short lineNum; // line to select (<0 to specify range)
1003 long startRange; // start of selection range (if line < 0)
1004 long endRange; // end of selection range (if line < 0)
1005 long unused2; // 0 (not used)
1006 long theDate; // modification date/time
1007};
Bram Moolenaar071d4272004-06-13 20:20:40 +00001008
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001009static long drop_numFiles;
1010static short drop_gotPosition;
1011static SelectionRange drop_thePosition;
1012
1013 static void
1014drop_callback(void *cookie UNUSED)
1015{
1016 /* TODO: Handle the goto/select line more cleanly */
1017 if ((drop_numFiles == 1) & (drop_gotPosition))
1018 {
1019 if (drop_thePosition.lineNum >= 0)
1020 {
1021 lnum = drop_thePosition.lineNum + 1;
1022 /* oap->motion_type = MLINE;
1023 setpcmark();*/
1024 if (lnum < 1L)
1025 lnum = 1L;
1026 else if (lnum > curbuf->b_ml.ml_line_count)
1027 lnum = curbuf->b_ml.ml_line_count;
1028 curwin->w_cursor.lnum = lnum;
1029 curwin->w_cursor.col = 0;
1030 /* beginline(BL_SOL | BL_FIX);*/
1031 }
1032 else
1033 goto_byte(drop_thePosition.startRange + 1);
1034 }
1035
1036 /* Update the screen display */
1037 update_screen(NOT_VALID);
1038
1039 /* Select the text if possible */
1040 if (drop_gotPosition)
1041 {
1042 VIsual_active = TRUE;
1043 VIsual_select = FALSE;
1044 VIsual = curwin->w_cursor;
1045 if (drop_thePosition.lineNum < 0)
1046 {
1047 VIsual_mode = 'v';
1048 goto_byte(drop_thePosition.endRange);
1049 }
1050 else
1051 {
1052 VIsual_mode = 'V';
1053 VIsual.col = 0;
1054 }
1055 }
1056}
1057
Bram Moolenaar071d4272004-06-13 20:20:40 +00001058/* The IDE uses the optional keyAEPosition parameter to tell the ed-
1059 itor the selection range. If lineNum is zero or greater, scroll the text
1060 to the specified line. If lineNum is less than zero, use the values in
1061 startRange and endRange to select the specified characters. Scroll
1062 the text to display the selection. If lineNum, startRange, and
1063 endRange are all negative, there is no selection range specified.
1064 */
1065
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001066 pascal OSErr
1067HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001068{
1069 /*
1070 * TODO: Clean up the code with convert the AppleEvent into
1071 * a ":args"
1072 */
1073 OSErr error = noErr;
1074// OSErr firstError = noErr;
1075// short numErrors = 0;
1076 AEDesc theList;
1077 DescType typeCode;
1078 long numFiles;
1079 // long fileCount;
1080 char_u **fnames;
1081// char_u fname[256];
1082 Size actualSize;
1083 SelectionRange thePosition;
1084 short gotPosition = false;
1085 long lnum;
1086
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087 /* the direct object parameter is the list of aliases to files (one or more) */
1088 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1089 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001090 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001091
1092
1093 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1094 if (error == noErr)
1095 gotPosition = true;
1096 if (error == errAEDescNotFound)
1097 error = noErr;
1098 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001099 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001100
Bram Moolenaar071d4272004-06-13 20:20:40 +00001101/*
1102 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1103
1104 if (^error) then
1105 {
1106 if (thePosition.lineNum >= 0)
1107 {
1108 // Goto this line
1109 }
1110 else
1111 {
1112 // Set the range char wise
1113 }
1114 }
1115 */
1116
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117 reset_VIsual();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001118 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1119
1120 if (error)
1121 {
1122 /* TODO: empty fnames[] first */
1123 vim_free(fnames);
1124 return (error);
1125 }
1126
1127 if (starting > 0)
1128 {
1129 int i;
1130 char_u *p;
Bram Moolenaar51b84362007-09-29 11:16:17 +00001131 int fnum = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001132
1133 /* these are the initial files dropped on the Vim icon */
1134 for (i = 0 ; i < numFiles; i++)
1135 {
1136 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1137 || (p = vim_strsave(fnames[i])) == NULL)
1138 mch_exit(2);
1139 else
1140 alist_add(&global_alist, p, 2);
Bram Moolenaar51b84362007-09-29 11:16:17 +00001141 if (fnum == -1)
1142 fnum = GARGLIST[GARGCOUNT - 1].ae_fnum;
1143 }
1144
1145 /* If the file name was already in the buffer list we need to switch
1146 * to it. */
1147 if (curbuf->b_fnum != fnum)
1148 {
1149 char_u cmd[30];
1150
1151 vim_snprintf((char *)cmd, 30, "silent %dbuffer", fnum);
1152 do_cmdline_cmd(cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001153 }
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001154
1155 /* Change directory to the location of the first file. */
Bram Moolenaarb7407d32018-02-03 17:36:27 +01001156 if (GARGCOUNT > 0
1157 && vim_chdirfile(alist_name(&GARGLIST[0]), "drop") == OK)
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001158 shorten_fnames(TRUE);
1159
Bram Moolenaar071d4272004-06-13 20:20:40 +00001160 goto finished;
1161 }
1162
1163 /* Handle the drop, :edit to get to the file */
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001164 drop_numFiles = numFiles;
1165 drop_gotPosition = gotPosition;
1166 drop_thePosition = thePosition;
1167 handle_drop(numFiles, fnames, FALSE, drop_callback, NULL);
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001168
Bram Moolenaar071d4272004-06-13 20:20:40 +00001169 setcursor();
1170 out_flush();
1171
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001172 /* Fake mouse event to wake from stall */
1173 PostEvent(mouseUp, 0);
1174
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001175finished:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001176 AEDisposeDesc(&theList); /* dispose what we allocated */
1177
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001178 error = HandleUnusedParms(theAEvent);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001179 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001180}
1181
1182/*
1183 *
1184 */
1185
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001186 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001187Handle_aevt_oapp_AE(
1188 const AppleEvent *theAEvent,
1189 AppleEvent *theReply,
1190 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001191{
1192 OSErr error = noErr;
1193
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001194 error = HandleUnusedParms(theAEvent);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001195 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001196}
1197
1198/*
1199 *
1200 */
1201
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001202 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001203Handle_aevt_quit_AE(
1204 const AppleEvent *theAEvent,
1205 AppleEvent *theReply,
1206 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001207{
1208 OSErr error = noErr;
1209
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001210 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001211 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001212 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001213
1214 /* Need to fake a :confirm qa */
1215 do_cmdline_cmd((char_u *)"confirm qa");
1216
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001217 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001218}
1219
1220/*
1221 *
1222 */
1223
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001224 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001225Handle_aevt_pdoc_AE(
1226 const AppleEvent *theAEvent,
1227 AppleEvent *theReply,
1228 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001229{
1230 OSErr error = noErr;
1231
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001232 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001233
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001234 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001235}
1236
1237/*
1238 * Handling of unknown AppleEvent
1239 *
1240 * (Just get rid of all the parms)
1241 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001242 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001243Handle_unknown_AE(
1244 const AppleEvent *theAEvent,
1245 AppleEvent *theReply,
1246 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247{
1248 OSErr error = noErr;
1249
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001250 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001251
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001252 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001253}
1254
1255
Bram Moolenaar071d4272004-06-13 20:20:40 +00001256/*
1257 * Install the various AppleEvent Handlers
1258 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001259 OSErr
1260InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001261{
1262 OSErr error;
1263
1264 /* install open application handler */
1265 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001266 NewAEEventHandlerUPP(Handle_aevt_oapp_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001267 if (error)
1268 {
1269 return error;
1270 }
1271
1272 /* install quit application handler */
1273 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001274 NewAEEventHandlerUPP(Handle_aevt_quit_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001275 if (error)
1276 {
1277 return error;
1278 }
1279
1280 /* install open document handler */
1281 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001282 NewAEEventHandlerUPP(HandleODocAE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001283 if (error)
1284 {
1285 return error;
1286 }
1287
1288 /* install print document handler */
1289 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001290 NewAEEventHandlerUPP(Handle_aevt_pdoc_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001291
1292/* Install Core Suite */
1293/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001294 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001295
1296 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001297 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298
1299 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001300 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001301
1302 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001303 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001304
1305 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001306 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001307
1308 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001309 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001310
1311 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001312 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetData, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001313
1314 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001315 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetDataSize, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001316
1317 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001318 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001319
1320 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001321 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001322
1323 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001324 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001325
1326 error = AEInstallEventHandler(kAECoreSuite, kAESave,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001327 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001328
1329 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001330 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001331*/
1332
1333#ifdef FEAT_CW_EDITOR
1334 /*
1335 * Bind codewarrior support handlers
1336 */
1337 error = AEInstallEventHandler('KAHL', 'GTTX',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001338 NewAEEventHandlerUPP(Handle_KAHL_GTTX_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001339 if (error)
1340 {
1341 return error;
1342 }
1343 error = AEInstallEventHandler('KAHL', 'SRCH',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001344 NewAEEventHandlerUPP(Handle_KAHL_SRCH_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001345 if (error)
1346 {
1347 return error;
1348 }
1349 error = AEInstallEventHandler('KAHL', 'MOD ',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001350 NewAEEventHandlerUPP(Handle_KAHL_MOD_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001351 if (error)
1352 {
1353 return error;
1354 }
1355#endif
1356
1357 return error;
1358
1359}
1360#endif /* USE_AEVENT */
1361
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001362
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001363/*
1364 * Callback function, installed by InstallFontPanelHandler(), below,
1365 * to handle Font Panel events.
1366 */
1367 static OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001368FontPanelHandler(
1369 EventHandlerCallRef inHandlerCallRef,
1370 EventRef inEvent,
1371 void *inUserData)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001372{
1373 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1374 {
1375 gFontPanelInfo.isPanelVisible = false;
1376 return noErr;
1377 }
1378
1379 if (GetEventKind(inEvent) == kEventFontSelection)
1380 {
1381 OSStatus status;
1382 FMFontFamily newFamily;
1383 FMFontSize newSize;
1384 FMFontStyle newStyle;
1385
1386 /* Retrieve the font family ID number. */
1387 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1388 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1389 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1390 &newFamily);
1391 if (status == noErr)
1392 gFontPanelInfo.family = newFamily;
1393
1394 /* Retrieve the font size. */
1395 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1396 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1397 if (status == noErr)
1398 gFontPanelInfo.size = newSize;
1399
1400 /* Retrieve the font style (bold, etc.). Currently unused. */
1401 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1402 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1403 if (status == noErr)
1404 gFontPanelInfo.style = newStyle;
1405 }
1406 return noErr;
1407}
1408
1409
1410 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001411InstallFontPanelHandler(void)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001412{
1413 EventTypeSpec eventTypes[2];
1414 EventHandlerUPP handlerUPP;
1415 /* EventHandlerRef handlerRef; */
1416
1417 eventTypes[0].eventClass = kEventClassFont;
1418 eventTypes[0].eventKind = kEventFontSelection;
1419 eventTypes[1].eventClass = kEventClassFont;
1420 eventTypes[1].eventKind = kEventFontPanelClosed;
1421
1422 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1423
1424 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1425 /*userData=*/NULL, /*handlerRef=*/NULL);
1426}
1427
1428
1429/*
1430 * Fill the buffer pointed to by outName with the name and size
1431 * of the font currently selected in the Font Panel.
1432 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001433#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001434 static void
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001435GetFontPanelSelection(char_u *outName)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001436{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001437 Str255 buf;
1438 ByteCount fontNameLen = 0;
1439 ATSUFontID fid;
1440 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001441
1442 if (!outName)
1443 return;
1444
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001445 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1446 {
1447 /* Canonicalize localized font names */
1448 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1449 gFontPanelInfo.style, &fid, NULL) != noErr)
1450 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001451
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001452 /* Request font name with Mac encoding (otherwise we could
1453 * get an unwanted utf-16 name) */
1454 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1455 kFontNoScriptCode, kFontNoLanguageCode,
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001456 255, (char *)outName, &fontNameLen, NULL) != noErr)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001457 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001458
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001459 /* Only encode font size, because style (bold, italic, etc) is
1460 * already part of the font full name */
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001461 vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001462 gFontPanelInfo.size/*,
1463 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1464 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1465 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1466
1467 if ((fontNameLen + STRLEN(styleString)) < 255)
1468 STRCPY(outName + fontNameLen, styleString);
1469 }
1470 else
1471 {
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001472 *outName = NUL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001473 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001474}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001475
1476
Bram Moolenaar071d4272004-06-13 20:20:40 +00001477/*
1478 * ------------------------------------------------------------
1479 * Unfiled yet
1480 * ------------------------------------------------------------
1481 */
1482
1483/*
1484 * gui_mac_get_menu_item_index
1485 *
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001486 * Returns the index inside the menu where
Bram Moolenaar071d4272004-06-13 20:20:40 +00001487 */
Bram Moolenaarb05034a2010-09-21 17:34:31 +02001488 short /* Should we return MenuItemIndex? */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001489gui_mac_get_menu_item_index(vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001490{
1491 short index;
1492 short itemIndex = -1;
1493 vimmenu_T *pBrother;
1494
1495 /* Only menu without parent are the:
1496 * -menu in the menubar
1497 * -popup menu
1498 * -toolbar (guess)
1499 *
1500 * Which are not items anyway.
1501 */
1502 if (pMenu->parent)
1503 {
1504 /* Start from the Oldest Brother */
1505 pBrother = pMenu->parent->children;
1506 index = 1;
1507 while ((pBrother) && (itemIndex == -1))
1508 {
1509 if (pBrother == pMenu)
1510 itemIndex = index;
1511 index++;
1512 pBrother = pBrother->next;
1513 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001514 }
1515 return itemIndex;
1516}
1517
1518 static vimmenu_T *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001519gui_mac_get_vim_menu(short menuID, short itemIndex, vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001520{
1521 short index;
1522 vimmenu_T *pChildMenu;
1523 vimmenu_T *pElder = pMenu->parent;
1524
1525
1526 /* Only menu without parent are the:
1527 * -menu in the menubar
1528 * -popup menu
1529 * -toolbar (guess)
1530 *
1531 * Which are not items anyway.
1532 */
1533
1534 if ((pElder) && (pElder->submenu_id == menuID))
1535 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001536 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1537 pMenu = pMenu->next;
1538 }
1539 else
1540 {
1541 for (; pMenu != NULL; pMenu = pMenu->next)
1542 {
1543 if (pMenu->children != NULL)
1544 {
1545 pChildMenu = gui_mac_get_vim_menu
1546 (menuID, itemIndex, pMenu->children);
1547 if (pChildMenu)
1548 {
1549 pMenu = pChildMenu;
1550 break;
1551 }
1552 }
1553 }
1554 }
1555 return pMenu;
1556}
1557
1558/*
1559 * ------------------------------------------------------------
1560 * MacOS Feedback procedures
1561 * ------------------------------------------------------------
1562 */
1563 pascal
1564 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001565gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001566{
1567 scrollbar_T *sb;
1568 int value, dragging;
1569 ControlHandle theControlToUse;
1570 int dont_scroll_save = dont_scroll;
1571
1572 theControlToUse = dragged_sb;
1573
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001574 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001575
1576 if (sb == NULL)
1577 return;
1578
1579 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001580 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001581 dragging = (partCode != 0);
1582
1583 /* When "allow_scrollbar" is FALSE still need to remember the new
1584 * position, but don't actually scroll by setting "dont_scroll". */
1585 dont_scroll = !allow_scrollbar;
1586 gui_drag_scrollbar(sb, value, dragging);
1587 dont_scroll = dont_scroll_save;
1588}
1589
1590 pascal
1591 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001592gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001593{
1594 /* TODO: have live support */
1595 scrollbar_T *sb, *sb_info;
1596 long data;
1597 long value;
1598 int page;
1599 int dragging = FALSE;
1600 int dont_scroll_save = dont_scroll;
1601
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001602 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001603
1604 if (sb == NULL)
1605 return;
1606
1607 if (sb->wp != NULL) /* Left or right scrollbar */
1608 {
1609 /*
1610 * Careful: need to get scrollbar info out of first (left) scrollbar
1611 * for window, but keep real scrollbar too because we must pass it to
1612 * gui_drag_scrollbar().
1613 */
1614 sb_info = &sb->wp->w_scrollbars[0];
1615
1616 if (sb_info->size > 5)
1617 page = sb_info->size - 2; /* use two lines of context */
1618 else
1619 page = sb_info->size;
1620 }
1621 else /* Bottom scrollbar */
1622 {
1623 sb_info = sb;
Bram Moolenaar02631462017-09-22 15:20:32 +02001624 page = curwin->w_width - 5;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001625 }
1626
1627 switch (partCode)
1628 {
1629 case kControlUpButtonPart: data = -1; break;
1630 case kControlDownButtonPart: data = 1; break;
1631 case kControlPageDownPart: data = page; break;
1632 case kControlPageUpPart: data = -page; break;
1633 default: data = 0; break;
1634 }
1635
1636 value = sb_info->value + data;
1637/* if (value > sb_info->max)
1638 value = sb_info->max;
1639 else if (value < 0)
1640 value = 0;*/
1641
1642 /* When "allow_scrollbar" is FALSE still need to remember the new
1643 * position, but don't actually scroll by setting "dont_scroll". */
1644 dont_scroll = !allow_scrollbar;
1645 gui_drag_scrollbar(sb, value, dragging);
1646 dont_scroll = dont_scroll_save;
1647
1648 out_flush();
1649 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1650
1651/* if (sb_info->wp != NULL)
1652 {
1653 win_T *wp;
1654 int sb_num;
1655
1656 sb_num = 0;
1657 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1658 sb_num++;
1659
1660 if (wp != NULL)
1661 {
1662 current_scrollbar = sb_num;
1663 scrollbar_value = value;
1664 gui_do_scroll();
1665 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1666 }
1667 }*/
1668}
1669
1670/*
1671 * ------------------------------------------------------------
1672 * MacOS Click Handling procedures
1673 * ------------------------------------------------------------
1674 */
1675
1676
1677/*
1678 * Handle a click inside the window, it may happens in the
1679 * scrollbar or the contents.
1680 *
1681 * TODO: Add support for potential TOOLBAR
1682 */
1683 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001684gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001685{
1686 Point thePoint;
1687 int_u vimModifiers;
1688 short thePortion;
1689 ControlHandle theControl;
1690 int vimMouseButton;
1691 short dblClick;
1692
1693 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001694 GlobalToLocal(&thePoint);
1695 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001696
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001697 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001698
1699 if (theControl != NUL)
1700 {
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001701 /* We hit a scrollbar */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001702
1703 if (thePortion != kControlIndicatorPart)
1704 {
1705 dragged_sb = theControl;
1706 TrackControl(theControl, thePoint, gScrollAction);
1707 dragged_sb = NULL;
1708 }
1709 else
1710 {
1711 dragged_sb = theControl;
1712#if 1
1713 TrackControl(theControl, thePoint, gScrollDrag);
1714#else
1715 TrackControl(theControl, thePoint, NULL);
1716#endif
1717 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1718 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001719 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001720 dragged_sb = NULL;
1721 }
1722 }
1723 else
1724 {
1725 /* We are inside the contents */
1726
1727 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1728 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1729
1730 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1731 vimMouseButton = MOUSE_LEFT;
1732
Bram Moolenaar071d4272004-06-13 20:20:40 +00001733 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001734 /* TODO: NEEDED? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001735 clickIsPopup = FALSE;
1736
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001737 if (mouse_model_popup() && IsShowContextualMenuClick(theEvent))
1738 {
1739 vimMouseButton = MOUSE_RIGHT;
1740 vimModifiers &= ~MOUSE_CTRL;
1741 clickIsPopup = TRUE;
1742 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001743
1744 /* Is it a double click ? */
1745 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1746
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001747 /* Send the mouse click to Vim */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001748 gui_send_mouse_event(vimMouseButton, thePoint.h,
1749 thePoint.v, dblClick, vimModifiers);
1750
1751 /* Create the rectangle around the cursor to detect
1752 * the mouse dragging
1753 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001754#if 0
1755 /* TODO: Do we need to this even for the contextual menu?
1756 * It may be require for popup_setpos, but for popup?
1757 */
1758 if (vimMouseButton == MOUSE_LEFT)
1759#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001760 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001761 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001762 FILL_Y(Y_2_ROW(thePoint.v)),
1763 FILL_X(X_2_COL(thePoint.h)+1),
1764 FILL_Y(Y_2_ROW(thePoint.v)+1));
1765
1766 dragRectEnbl = TRUE;
1767 dragRectControl = kCreateRect;
1768 }
1769 }
1770}
1771
1772/*
1773 * Handle the click in the titlebar (to move the window)
1774 */
1775 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001776gui_mac_doInDragClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001777{
1778 Rect movingLimits;
1779 Rect *movingLimitsPtr = &movingLimits;
1780
1781 /* TODO: may try to prevent move outside screen? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001782 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001783 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001784}
1785
1786/*
1787 * Handle the click in the grow box
1788 */
1789 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001790gui_mac_doInGrowClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001791{
1792
1793 long newSize;
1794 unsigned short newWidth;
1795 unsigned short newHeight;
1796 Rect resizeLimits;
1797 Rect *resizeLimitsPtr = &resizeLimits;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001798 Rect NewContentRect;
1799
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001800 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001801
Bram Moolenaar720c7102007-05-10 18:07:50 +00001802 /* Set the minimum size */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001803 /* TODO: Should this come from Vim? */
1804 resizeLimits.top = 100;
1805 resizeLimits.left = 100;
1806
Bram Moolenaar071d4272004-06-13 20:20:40 +00001807 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1808 newWidth = NewContentRect.right - NewContentRect.left;
1809 newHeight = NewContentRect.bottom - NewContentRect.top;
1810 gui_resize_shell(newWidth, newHeight);
1811 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001812 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001813}
1814
1815/*
1816 * Handle the click in the zoom box
1817 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001818 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001819gui_mac_doInZoomClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001820{
1821 Rect r;
1822 Point p;
1823 short thePart;
1824
1825 /* ideal width is current */
1826 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1827 if (gui.which_scrollbars[SBAR_LEFT])
1828 p.h += gui.scrollbar_width;
1829 if (gui.which_scrollbars[SBAR_RIGHT])
1830 p.h += gui.scrollbar_width;
Bram Moolenaarb05034a2010-09-21 17:34:31 +02001831 /* ideal height is as high as we can get */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001832 p.v = 15 * 1024;
1833
1834 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1835 ? inZoomIn : inZoomOut;
1836
1837 if (!TrackBox(whichWindow, theEvent->where, thePart))
1838 return;
1839
1840 /* use returned width */
1841 p.h = r.right - r.left;
1842 /* adjust returned height */
1843 p.v = r.bottom - r.top - 2 * gui.border_offset;
1844 if (gui.which_scrollbars[SBAR_BOTTOM])
1845 p.v -= gui.scrollbar_height;
1846 p.v -= p.v % gui.char_height;
1847 p.v += 2 * gui.border_width;
Bram Moolenaard8644bd2011-06-12 20:33:38 +02001848 if (gui.which_scrollbars[SBAR_BOTTOM])
Bram Moolenaar071d4272004-06-13 20:20:40 +00001849 p.v += gui.scrollbar_height;
1850
1851 ZoomWindowIdeal(whichWindow, thePart, &p);
1852
1853 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
1854 gui_resize_shell(r.right - r.left, r.bottom - r.top);
1855 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001856 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001857}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001858
1859/*
1860 * ------------------------------------------------------------
1861 * MacOS Event Handling procedure
1862 * ------------------------------------------------------------
1863 */
1864
1865/*
1866 * Handle the Update Event
1867 */
1868
1869 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001870gui_mac_doUpdateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001871{
1872 WindowPtr whichWindow;
1873 GrafPtr savePort;
1874 RgnHandle updateRgn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001875 Rect updateRect;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876 Rect *updateRectPtr;
1877 Rect rc;
1878 Rect growRect;
1879 RgnHandle saveRgn;
1880
1881
Bram Moolenaar071d4272004-06-13 20:20:40 +00001882 updateRgn = NewRgn();
1883 if (updateRgn == NULL)
1884 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001885
1886 /* This could be done by the caller as we
1887 * don't require anything else out of the event
1888 */
1889 whichWindow = (WindowPtr) event->message;
1890
1891 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001892 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001893
1894 /* Select the Window's Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001895 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001896
1897 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001898 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001899 /* Redraw the biggest rectangle covering the area
1900 * to be updated.
1901 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001902 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
1903# if 0
Bram Moolenaar720c7102007-05-10 18:07:50 +00001904 /* Would be more appropriate to use the following but doesn't
Bram Moolenaar071d4272004-06-13 20:20:40 +00001905 * seem to work under MacOS X (Dany)
1906 */
1907 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
1908# endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001909
Bram Moolenaar071d4272004-06-13 20:20:40 +00001910 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001911 HLock((Handle) updateRgn);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001912
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001913 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001914# if 0
1915 /* Code from original Carbon Port (using GetWindowRegion.
1916 * I believe the UpdateRgn is already in local (Dany)
1917 */
1918 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
1919 GlobalToLocal(&botRight(updateRect));
1920# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001921 /* Update the content (i.e. the text) */
1922 gui_redraw(updateRectPtr->left, updateRectPtr->top,
1923 updateRectPtr->right - updateRectPtr->left,
1924 updateRectPtr->bottom - updateRectPtr->top);
1925 /* Clear the border areas if needed */
1926 gui_mch_set_bg_color(gui.back_pixel);
1927 if (updateRectPtr->left < FILL_X(0))
1928 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001929 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
1930 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001931 }
1932 if (updateRectPtr->top < FILL_Y(0))
1933 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001934 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
1935 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001936 }
1937 if (updateRectPtr->right > FILL_X(Columns))
1938 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001939 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001940 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001941 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001942 }
1943 if (updateRectPtr->bottom > FILL_Y(Rows))
1944 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001945 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001946 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001947 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001948 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001949 HUnlock((Handle) updateRgn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001950 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001951
1952 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001953 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001954
1955 /* Update the GrowBox */
1956 /* Taken from FAQ 33-27 */
1957 saveRgn = NewRgn();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001958 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001959 GetClip(saveRgn);
1960 ClipRect(&growRect);
1961 DrawGrowIcon(whichWindow);
1962 SetClip(saveRgn);
1963 DisposeRgn(saveRgn);
1964 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001965
1966 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001967 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001968}
1969
1970/*
1971 * Handle the activate/deactivate event
1972 * (apply to a window)
1973 */
1974 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001975gui_mac_doActivateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001976{
1977 WindowPtr whichWindow;
1978
1979 whichWindow = (WindowPtr) event->message;
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001980 /* Dim scrollbars */
1981 if (whichWindow == gui.VimWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001982 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00001983 ControlRef rootControl;
1984 GetRootControl(gui.VimWindow, &rootControl);
1985 if ((event->modifiers) & activeFlag)
1986 ActivateControl(rootControl);
1987 else
1988 DeactivateControl(rootControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001989 }
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001990
1991 /* Activate */
1992 gui_focus_change((event->modifiers) & activeFlag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001993}
1994
1995
1996/*
1997 * Handle the suspend/resume event
1998 * (apply to the application)
1999 */
2000 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002001gui_mac_doSuspendEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002002{
2003 /* The frontmost application just changed */
2004
2005 /* NOTE: the suspend may happen before the deactivate
2006 * seen on MacOS X
2007 */
2008
2009 /* May not need to change focus as the window will
Bram Moolenaar720c7102007-05-10 18:07:50 +00002010 * get an activate/deactivate event
Bram Moolenaar071d4272004-06-13 20:20:40 +00002011 */
2012 if (event->message & 1)
2013 /* Resume */
2014 gui_focus_change(TRUE);
2015 else
2016 /* Suspend */
2017 gui_focus_change(FALSE);
2018}
2019
2020/*
2021 * Handle the key
2022 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002023#ifdef USE_CARBONKEYHANDLER
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002024 static pascal OSStatus
2025gui_mac_handle_window_activate(
2026 EventHandlerCallRef nextHandler,
2027 EventRef theEvent,
2028 void *data)
2029{
2030 UInt32 eventClass = GetEventClass(theEvent);
2031 UInt32 eventKind = GetEventKind(theEvent);
Bram Moolenaard68071d2006-05-02 22:08:30 +00002032
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002033 if (eventClass == kEventClassWindow)
2034 {
2035 switch (eventKind)
2036 {
2037 case kEventWindowActivated:
Bram Moolenaar819edbe2017-11-25 17:14:33 +01002038# if defined(FEAT_MBYTE)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002039 im_on_window_switch(TRUE);
Bram Moolenaar819edbe2017-11-25 17:14:33 +01002040# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002041 return noErr;
2042
2043 case kEventWindowDeactivated:
Bram Moolenaar819edbe2017-11-25 17:14:33 +01002044# if defined(FEAT_MBYTE)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002045 im_on_window_switch(FALSE);
Bram Moolenaar819edbe2017-11-25 17:14:33 +01002046# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002047 return noErr;
2048 }
2049 }
2050
2051 return eventNotHandledErr;
2052}
2053
2054 static pascal OSStatus
2055gui_mac_handle_text_input(
2056 EventHandlerCallRef nextHandler,
2057 EventRef theEvent,
2058 void *data)
2059{
2060 UInt32 eventClass = GetEventClass(theEvent);
2061 UInt32 eventKind = GetEventKind(theEvent);
2062
2063 if (eventClass != kEventClassTextInput)
2064 return eventNotHandledErr;
2065
2066 if ((kEventTextInputUpdateActiveInputArea != eventKind) &&
2067 (kEventTextInputUnicodeForKeyEvent != eventKind) &&
2068 (kEventTextInputOffsetToPos != eventKind) &&
2069 (kEventTextInputPosToOffset != eventKind) &&
2070 (kEventTextInputGetSelectedText != eventKind))
2071 return eventNotHandledErr;
2072
2073 switch (eventKind)
2074 {
2075 case kEventTextInputUpdateActiveInputArea:
2076 return gui_mac_update_input_area(nextHandler, theEvent);
2077 case kEventTextInputUnicodeForKeyEvent:
2078 return gui_mac_unicode_key_event(nextHandler, theEvent);
2079
2080 case kEventTextInputOffsetToPos:
2081 case kEventTextInputPosToOffset:
2082 case kEventTextInputGetSelectedText:
2083 break;
2084 }
2085
2086 return eventNotHandledErr;
2087}
2088
2089 static pascal
2090OSStatus gui_mac_update_input_area(
2091 EventHandlerCallRef nextHandler,
2092 EventRef theEvent)
2093{
2094 return eventNotHandledErr;
2095}
2096
2097static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the
2098 keys */
Bram Moolenaard68071d2006-05-02 22:08:30 +00002099
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002100# define INLINE_KEY_BUFFER_SIZE 80
2101 static pascal OSStatus
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002102gui_mac_unicode_key_event(
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002103 EventHandlerCallRef nextHandler,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002104 EventRef theEvent)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002105{
2106 /* Multibyte-friendly key event handler */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002107 OSStatus err = -1;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002108 UInt32 actualSize;
2109 UniChar *text;
2110 char_u result[INLINE_KEY_BUFFER_SIZE];
2111 short len = 0;
2112 UInt32 key_sym;
2113 char charcode;
2114 int key_char;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002115 UInt32 modifiers, vimModifiers;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002116 size_t encLen;
2117 char_u *to = NULL;
2118 Boolean isSpecial = FALSE;
2119 int i;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002120 EventRef keyEvent;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002121
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002122 /* Mask the mouse (as per user setting) */
2123 if (p_mh)
2124 ObscureCursor();
2125
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002126 /* Don't use the keys when the dialog wants them. */
2127 if (dialog_busy)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002128 return eventNotHandledErr;
Bram Moolenaard68071d2006-05-02 22:08:30 +00002129
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002130 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002131 typeUnicodeText, NULL, 0, &actualSize, NULL))
2132 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002133
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002134 text = (UniChar *)alloc(actualSize);
2135 if (!text)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002136 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002137
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002138 err = GetEventParameter(theEvent, kEventParamTextInputSendText,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002139 typeUnicodeText, NULL, actualSize, NULL, text);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002140 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002141
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002142 err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002143 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002144 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002145
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002146 err = GetEventParameter(keyEvent, kEventParamKeyModifiers,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002147 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002148 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002149
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002150 err = GetEventParameter(keyEvent, kEventParamKeyCode,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002151 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002152 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002153
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002154 err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002155 typeChar, NULL, sizeof(char), NULL, &charcode);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002156 require_noerr(err, done);
2157
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002158#ifndef USE_CMD_KEY
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002159 if (modifiers & cmdKey)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002160 goto done; /* Let system handle Cmd+... */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002161#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002162
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002163 key_char = charcode;
2164 vimModifiers = EventModifiers2VimModifiers(modifiers);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002165
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002166 /* Find the special key (eg., for cursor keys) */
2167 if (actualSize <= sizeof(UniChar) &&
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002168 ((text[0] < 0x20) || (text[0] == 0x7f)))
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002169 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002170 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2171 if (special_keys[i].key_sym == key_sym)
2172 {
2173 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2174 special_keys[i].vim_code1);
2175 key_char = simplify_key(key_char,
2176 (int *)&vimModifiers);
2177 isSpecial = TRUE;
2178 break;
2179 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002180 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002181
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002182 /* Intercept CMD-. and CTRL-c */
2183 if (((modifiers & controlKey) && key_char == 'c') ||
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002184 ((modifiers & cmdKey) && key_char == '.'))
2185 got_int = TRUE;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002186
2187 if (!isSpecial)
2188 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002189 /* remove SHIFT for keys that are already shifted, e.g.,
2190 * '(' and '*' */
2191 if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char))
2192 vimModifiers &= ~MOD_MASK_SHIFT;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002193
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002194 /* remove CTRL from keys that already have it */
2195 if (key_char < 0x20)
2196 vimModifiers &= ~MOD_MASK_CTRL;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002197
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002198 /* don't process unicode characters here */
2199 if (!IS_SPECIAL(key_char))
2200 {
2201 /* Following code to simplify and consolidate vimModifiers
2202 * taken liberally from gui_w48.c */
2203 key_char = simplify_key(key_char, (int *)&vimModifiers);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002204
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002205 /* Interpret META, include SHIFT, etc. */
2206 key_char = extract_modifiers(key_char, (int *)&vimModifiers);
2207 if (key_char == CSI)
2208 key_char = K_CSI;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002209
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002210 if (IS_SPECIAL(key_char))
2211 isSpecial = TRUE;
2212 }
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002213 }
2214
2215 if (vimModifiers)
2216 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002217 result[len++] = CSI;
2218 result[len++] = KS_MODIFIER;
2219 result[len++] = vimModifiers;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002220 }
2221
2222 if (isSpecial && IS_SPECIAL(key_char))
2223 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002224 result[len++] = CSI;
2225 result[len++] = K_SECOND(key_char);
2226 result[len++] = K_THIRD(key_char);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002227 }
2228 else
2229 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002230 encLen = actualSize;
2231 to = mac_utf16_to_enc(text, actualSize, &encLen);
2232 if (to)
2233 {
2234 /* This is basically add_to_input_buf_csi() */
2235 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2236 {
2237 result[len++] = to[i];
2238 if (to[i] == CSI)
2239 {
2240 result[len++] = KS_EXTRA;
2241 result[len++] = (int)KE_CSI;
2242 }
2243 }
2244 vim_free(to);
2245 }
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002246 }
2247
2248 add_to_input_buf(result, len);
2249 err = noErr;
2250
2251done:
2252 vim_free(text);
2253 if (err == noErr)
2254 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002255 /* Fake event to wake up WNE (required to get
2256 * key repeat working */
2257 PostEvent(keyUp, 0);
2258 return noErr;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002259 }
2260
2261 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002262}
2263#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002264 void
2265gui_mac_doKeyEvent(EventRecord *theEvent)
2266{
2267 /* TODO: add support for COMMAND KEY */
2268 long menu;
2269 unsigned char string[20];
2270 short num, i;
2271 short len = 0;
2272 KeySym key_sym;
2273 int key_char;
2274 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002275 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002276
2277 /* Mask the mouse (as per user setting) */
2278 if (p_mh)
2279 ObscureCursor();
2280
Bram Moolenaarc4568ab2018-11-16 16:21:05 +01002281 /* Get the key code and its ASCII representation */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2283 key_char = theEvent->message & charCodeMask;
2284 num = 1;
2285
2286 /* Intercept CTRL-C */
2287 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002288 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002289 if (key_char == Ctrl_C && ctrl_c_interrupts)
2290 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002291 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2292 && (key_char == '2' || key_char == '6'))
2293 {
2294 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2295 if (key_char == '2')
2296 key_char = Ctrl_AT;
2297 else
2298 key_char = Ctrl_HAT;
2299 theEvent->modifiers = 0;
2300 }
2301 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002302
2303 /* Intercept CMD-. */
2304 if (theEvent->modifiers & cmdKey)
2305 if (key_char == '.')
2306 got_int = TRUE;
2307
2308 /* Handle command key as per menu */
2309 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2310 if (theEvent->modifiers & cmdKey)
2311 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2312 * Why the mouse button? */
2313 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2314 {
2315 menu = MenuKey(key_char);
2316 if (HiWord(menu))
2317 {
2318 gui_mac_handle_menu(menu);
2319 return;
2320 }
2321 }
2322
2323 /* Convert the modifiers */
2324 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2325
2326
2327 /* Handle special keys. */
2328#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002329 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002330 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2331#endif
2332 {
2333 /* Find the special key (for non-printable keyt_char) */
2334 if ((key_char < 0x20) || (key_char == 0x7f))
2335 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2336 if (special_keys[i].key_sym == key_sym)
2337 {
2338# if 0
2339 /* We currently don't have not so special key */
2340 if (special_keys[i].vim_code1 == NUL)
2341 key_char = special_keys[i].vim_code0;
2342 else
2343# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002344 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2345 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002346 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002347 break;
2348 }
2349 }
2350
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002351 /* For some keys the modifier is included in the char itself. */
2352 if (simplify || key_char == TAB || key_char == ' ')
2353 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002354
2355 /* Add the modifier to the input bu if needed */
2356 /* Do not want SHIFT-A or CTRL-A with modifier */
2357 if (!IS_SPECIAL(key_char)
2358 && key_sym != vk_Space
2359 && key_sym != vk_Tab
2360 && key_sym != vk_Return
2361 && key_sym != vk_Enter
2362 && key_sym != vk_Esc)
2363 {
2364#if 1
2365 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002366 if ((modifiers == MOD_MASK_SHIFT)
2367 || (modifiers == MOD_MASK_CTRL)
2368 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002369 modifiers = 0;
2370#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002371 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002372 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002373 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002374 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002375 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002376 modifiers = modifiers & ~MOD_MASK_SHIFT;
2377#endif
2378 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002379 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002380 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002381 string[len++] = CSI;
2382 string[len++] = KS_MODIFIER;
2383 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002384 }
2385
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002386 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002387 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002388 string[len++] = CSI;
2389 string[len++] = K_SECOND(key_char);
2390 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002391 }
2392 else
2393 {
2394#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002395 /* Convert characters when needed (e.g., from MacRoman to latin1).
2396 * This doesn't work for the NUL byte. */
2397 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002398 {
2399 char_u from[2], *to;
2400 int l;
2401
2402 from[0] = key_char;
2403 from[1] = NUL;
2404 l = 1;
2405 to = string_convert(&input_conv, from, &l);
2406 if (to != NULL)
2407 {
2408 for (i = 0; i < l && len < 19; i++)
2409 {
2410 if (to[i] == CSI)
2411 {
2412 string[len++] = KS_EXTRA;
2413 string[len++] = KE_CSI;
2414 }
2415 else
2416 string[len++] = to[i];
2417 }
2418 vim_free(to);
2419 }
2420 else
2421 string[len++] = key_char;
2422 }
2423 else
2424#endif
2425 string[len++] = key_char;
2426 }
2427
2428 if (len == 1 && string[0] == CSI)
2429 {
2430 /* Turn CSI into K_CSI. */
2431 string[ len++ ] = KS_EXTRA;
2432 string[ len++ ] = KE_CSI;
2433 }
2434
2435 add_to_input_buf(string, len);
2436}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002437#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002438
2439/*
2440 * Handle MouseClick
2441 */
2442 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002443gui_mac_doMouseDownEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002444{
2445 short thePart;
2446 WindowPtr whichWindow;
2447
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002448 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002449
Bram Moolenaar79ee3152007-04-26 16:20:50 +00002450#ifdef FEAT_GUI_TABLINE
2451 /* prevent that the vim window size changes if it's activated by a
2452 click into the tab pane */
2453 if (whichWindow == drawer)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002454 return;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00002455#endif
2456
Bram Moolenaar071d4272004-06-13 20:20:40 +00002457 switch (thePart)
2458 {
2459 case (inDesk):
2460 /* TODO: what to do? */
2461 break;
2462
2463 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002464 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002465 break;
2466
2467 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002468 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002469 break;
2470
2471 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002472 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002473 break;
2474
2475 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002476 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002477 break;
2478
2479 case (inGoAway):
2480 if (TrackGoAway(whichWindow, theEvent->where))
2481 gui_shell_closed();
2482 break;
2483
2484 case (inZoomIn):
2485 case (inZoomOut):
Bram Moolenaar071d4272004-06-13 20:20:40 +00002486 gui_mac_doInZoomClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002487 break;
2488 }
2489}
2490
2491/*
2492 * Handle MouseMoved
2493 * [this event is a moving in and out of a region]
2494 */
2495 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002496gui_mac_doMouseMovedEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002497{
2498 Point thePoint;
2499 int_u vimModifiers;
2500
2501 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002502 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002503 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2504
2505 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002506 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002507 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002508 if (!clickIsPopup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002509 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2510 thePoint.v, FALSE, vimModifiers);
2511
2512 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002513 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002514 FILL_Y(Y_2_ROW(thePoint.v)),
2515 FILL_X(X_2_COL(thePoint.h)+1),
2516 FILL_Y(Y_2_ROW(thePoint.v)+1));
2517
2518 if (dragRectEnbl)
2519 dragRectControl = kCreateRect;
2520
2521}
2522
2523/*
2524 * Handle the mouse release
2525 */
2526 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002527gui_mac_doMouseUpEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002528{
2529 Point thePoint;
2530 int_u vimModifiers;
2531
2532 /* TODO: Properly convert the Contextual menu mouse-up */
2533 /* Potential source of the double menu */
2534 lastMouseTick = theEvent->when;
2535 dragRectEnbl = FALSE;
2536 dragRectControl = kCreateEmpty;
2537 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002538 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002539
2540 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002541 if (clickIsPopup)
2542 {
2543 vimModifiers &= ~MOUSE_CTRL;
2544 clickIsPopup = FALSE;
2545 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002546 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002547}
2548
Bram Moolenaar071d4272004-06-13 20:20:40 +00002549 static pascal OSStatus
2550gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2551 void *data)
2552{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002553 Point point;
2554 Rect bounds;
2555 UInt32 mod;
2556 SInt32 delta;
2557 int_u vim_mod;
Bram Moolenaar621e2fd2006-08-22 19:36:17 +00002558 EventMouseWheelAxis axis;
2559
2560 if (noErr == GetEventParameter(theEvent, kEventParamMouseWheelAxis,
2561 typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis)
2562 && axis != kEventMouseWheelAxisY)
2563 goto bail; /* Vim only does up-down scrolling */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002564
2565 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2566 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2567 goto bail;
2568 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2569 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2570 goto bail;
2571 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2572 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2573 goto bail;
2574
2575 vim_mod = 0;
2576 if (mod & shiftKey)
2577 vim_mod |= MOUSE_SHIFT;
2578 if (mod & controlKey)
2579 vim_mod |= MOUSE_CTRL;
2580 if (mod & optionKey)
2581 vim_mod |= MOUSE_ALT;
2582
Bram Moolenaar071d4272004-06-13 20:20:40 +00002583 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2584 {
2585 point.h -= bounds.left;
2586 point.v -= bounds.top;
2587 }
2588
2589 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2590 point.h, point.v, FALSE, vim_mod);
2591
Bram Moolenaarc236c162008-07-13 17:41:49 +00002592 /* post a bogus event to wake up WaitNextEvent */
2593 PostEvent(keyUp, 0);
2594
Bram Moolenaar071d4272004-06-13 20:20:40 +00002595 return noErr;
2596
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00002597bail:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002598 /*
2599 * when we fail give any additional callback handler a chance to perform
Bram Moolenaarc4568ab2018-11-16 16:21:05 +01002600 * its actions
Bram Moolenaar071d4272004-06-13 20:20:40 +00002601 */
2602 return CallNextEventHandler(nextHandler, theEvent);
2603}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002604
Bram Moolenaare00289d2010-08-14 21:56:42 +02002605 void
2606gui_mch_mousehide(int hide)
2607{
2608 /* TODO */
2609}
2610
Bram Moolenaar071d4272004-06-13 20:20:40 +00002611#if 0
2612
2613/*
2614 * This would be the normal way of invoking the contextual menu
2615 * but the Vim API doesn't seem to a support a request to get
2616 * the menu that we should display
2617 */
2618 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002619gui_mac_handle_contextual_menu(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002620{
2621/*
2622 * Clone PopUp to use menu
2623 * Create a object descriptor for the current selection
2624 * Call the procedure
2625 */
2626
2627// Call to Handle Popup
2628 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2629
2630 if (status != noErr)
2631 return;
2632
2633 if (CntxType == kCMMenuItemSelected)
2634 {
2635 /* Handle the menu CntxMenuID, CntxMenuItem */
2636 /* The submenu can be handle directly by gui_mac_handle_menu */
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002637 /* But what about the current menu, is the many changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002638 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002639 }
2640 else if (CntxMenuID == kCMShowHelpSelected)
2641 {
2642 /* Should come up with the help */
2643 }
2644
2645}
2646#endif
2647
2648/*
2649 * Handle menubar selection
2650 */
2651 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002652gui_mac_handle_menu(long menuChoice)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002653{
2654 short menu = HiWord(menuChoice);
2655 short item = LoWord(menuChoice);
2656 vimmenu_T *theVimMenu = root_menu;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002657
2658 if (menu == 256) /* TODO: use constant or gui.xyz */
2659 {
2660 if (item == 1)
2661 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002662 }
2663 else if (item != 0)
2664 {
2665 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2666
2667 if (theVimMenu)
2668 gui_menu_cb(theVimMenu);
2669 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002670 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002671}
2672
2673/*
2674 * Dispatch the event to proper handler
2675 */
2676
2677 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002678gui_mac_handle_event(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002679{
2680 OSErr error;
2681
2682 /* Handle contextual menu right now (if needed) */
Bram Moolenaare02d7b22007-06-19 14:29:43 +00002683 if (IsShowContextualMenuClick(event))
2684 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002685# if 0
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002686 gui_mac_handle_contextual_menu(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002687# else
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002688 gui_mac_doMouseDownEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002689# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002690 return;
Bram Moolenaare02d7b22007-06-19 14:29:43 +00002691 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002692
2693 /* Handle normal event */
2694 switch (event->what)
2695 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002696#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002697 case (keyDown):
2698 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002699 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002700 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002701#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002702 case (keyUp):
Bram Moolenaard68071d2006-05-02 22:08:30 +00002703 /* We don't care about when the key is released */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002704 break;
2705
2706 case (mouseDown):
2707 gui_mac_doMouseDownEvent(event);
2708 break;
2709
2710 case (mouseUp):
2711 gui_mac_doMouseUpEvent(event);
2712 break;
2713
2714 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002715 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002716 break;
2717
2718 case (diskEvt):
2719 /* We don't need special handling for disk insertion */
2720 break;
2721
2722 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002723 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002724 break;
2725
2726 case (osEvt):
2727 switch ((event->message >> 24) & 0xFF)
2728 {
2729 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002730 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002731 break;
2732 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002733 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002734 break;
2735 }
2736 break;
2737
2738#ifdef USE_AEVENT
2739 case (kHighLevelEvent):
2740 /* Someone's talking to us, through AppleEvents */
2741 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2742 break;
2743#endif
2744 }
2745}
2746
2747/*
2748 * ------------------------------------------------------------
2749 * Unknown Stuff
2750 * ------------------------------------------------------------
2751 */
2752
2753
2754 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002755gui_mac_find_font(char_u *font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002756{
2757 char_u c;
2758 char_u *p;
2759 char_u pFontName[256];
2760 Str255 systemFontname;
2761 short font_id;
2762 short size=9;
2763 GuiFont font;
2764#if 0
2765 char_u *fontNamePtr;
2766#endif
2767
2768 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2769 ;
2770
2771 c = *p;
2772 *p = 0;
2773
2774#if 1
2775 STRCPY(&pFontName[1], font_name);
2776 pFontName[0] = STRLEN(font_name);
2777 *p = c;
2778
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002779 /* Get the font name, minus the style suffix (:h, etc) */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002780 char_u fontName[256];
2781 char_u *styleStart = vim_strchr(font_name, ':');
2782 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
2783 vim_strncpy(fontName, font_name, fontNameLen);
2784
2785 ATSUFontID fontRef;
2786 FMFontStyle fontStyle;
2787 font_id = 0;
2788
2789 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
2790 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
2791 &fontRef) == noErr)
2792 {
2793 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2794 font_id = 0;
2795 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002796
2797 if (font_id == 0)
2798 {
2799 /*
2800 * Try again, this time replacing underscores in the font name
2801 * with spaces (:set guifont allows the two to be used
2802 * interchangeably; the Font Manager doesn't).
2803 */
2804 int i, changed = FALSE;
2805
2806 for (i = pFontName[0]; i > 0; --i)
2807 {
2808 if (pFontName[i] == '_')
2809 {
2810 pFontName[i] = ' ';
2811 changed = TRUE;
2812 }
2813 }
2814 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002815 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
2816 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
2817 kFontNoLanguageCode, &fontRef) == noErr)
2818 {
2819 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2820 font_id = 0;
2821 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002822 }
2823
Bram Moolenaar071d4272004-06-13 20:20:40 +00002824#else
2825 /* name = C2Pascal_save(menu->dname); */
2826 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2827
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002828 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002829#endif
2830
2831
2832 if (font_id == 0)
2833 {
2834 /* Oups, the system font was it the one the user want */
2835
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002836 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
2837 return NOFONT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002838 if (!EqualString(pFontName, systemFontname, false, false))
2839 return NOFONT;
2840 }
2841 if (*p == ':')
2842 {
2843 p++;
2844 /* Set the values found after ':' */
2845 while (*p)
2846 {
2847 switch (*p++)
2848 {
2849 case 'h':
2850 size = points_to_pixels(p, &p, TRUE);
2851 break;
2852 /*
2853 * TODO: Maybe accept width and styles
2854 */
2855 }
2856 while (*p == ':')
2857 p++;
2858 }
2859 }
2860
2861 if (size < 1)
2862 size = 1; /* Avoid having a size of 0 with system font */
2863
2864 font = (size << 16) + ((long) font_id & 0xFFFF);
2865
2866 return font;
2867}
2868
2869/*
2870 * ------------------------------------------------------------
Bram Moolenaar720c7102007-05-10 18:07:50 +00002871 * GUI_MCH functionality
Bram Moolenaar071d4272004-06-13 20:20:40 +00002872 * ------------------------------------------------------------
2873 */
2874
2875/*
2876 * Parse the GUI related command-line arguments. Any arguments used are
2877 * deleted from argv, and *argc is decremented accordingly. This is called
2878 * when vim is started, whether or not the GUI has been started.
2879 */
2880 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002881gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002882{
2883 /* TODO: Move most of this stuff toward gui_mch_init */
2884#ifdef USE_EXE_NAME
2885 FSSpec applDir;
2886# ifndef USE_FIND_BUNDLE_PATH
2887 short applVRefNum;
2888 long applDirID;
2889 Str255 volName;
2890# else
2891 ProcessSerialNumber psn;
2892 FSRef applFSRef;
2893# endif
2894#endif
2895
Bram Moolenaar071d4272004-06-13 20:20:40 +00002896#if 0
2897 InitCursor();
2898
Bram Moolenaar071d4272004-06-13 20:20:40 +00002899 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002900
2901#ifdef USE_AEVENT
2902 (void) InstallAEHandlers();
2903#endif
2904
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002905 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002906
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002907 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002908
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002909 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002910
2911 DrawMenuBar();
2912
2913
2914#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002915 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002916#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002917 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002918#endif
2919
2920
Bram Moolenaar071d4272004-06-13 20:20:40 +00002921 CreateNewWindow(kDocumentWindowClass,
2922 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002923 &windRect, &gui.VimWindow);
2924 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002925
2926 gui.char_width = 7;
2927 gui.char_height = 11;
2928 gui.char_ascent = 6;
2929 gui.num_rows = 24;
2930 gui.num_cols = 80;
2931 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2932
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002933 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2934 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002935
2936 dragRectEnbl = FALSE;
2937 dragRgn = NULL;
2938 dragRectControl = kCreateEmpty;
2939 cursorRgn = NewRgn();
2940#endif
2941#ifdef USE_EXE_NAME
2942# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002943 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002944 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002945 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002946# else
2947 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2948 * of TN2015
Bram Moolenaar071d4272004-06-13 20:20:40 +00002949 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002950 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002951 /* if (err != noErr) return err; */
2952
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002953 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002954 /* if (err != noErr) return err; */
2955
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002956 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002957
2958 /* This technic return NIL when we disallow_gui */
2959# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002960 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002961#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002962}
2963
2964#ifndef ALWAYS_USE_GUI
2965/*
2966 * Check if the GUI can be started. Called before gvimrc is sourced.
2967 * Return OK or FAIL.
2968 */
2969 int
2970gui_mch_init_check(void)
2971{
2972 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2973 * using the >console
2974 */
2975 if (disallow_gui) /* see main.c for reason to disallow */
2976 return FAIL;
2977 return OK;
2978}
2979#endif
2980
2981 static OSErr
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00002982receiveHandler(WindowRef theWindow, void *handlerRefCon, DragRef theDrag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002983{
2984 int x, y;
2985 int_u modifiers;
2986 char_u **fnames = NULL;
2987 int count;
2988 int i, j;
2989
2990 /* Get drop position, modifiers and count of items */
2991 {
2992 Point point;
2993 SInt16 mouseUpModifiers;
2994 UInt16 countItem;
2995
2996 GetDragMouse(theDrag, &point, NULL);
2997 GlobalToLocal(&point);
2998 x = point.h;
2999 y = point.v;
3000 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
3001 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
3002 CountDragItems(theDrag, &countItem);
3003 count = countItem;
3004 }
3005
3006 fnames = (char_u **)alloc(count * sizeof(char_u *));
3007 if (fnames == NULL)
3008 return dragNotAcceptedErr;
3009
3010 /* Get file names dropped */
3011 for (i = j = 0; i < count; ++i)
3012 {
3013 DragItemRef item;
3014 OSErr err;
3015 Size size;
3016 FlavorType type = flavorTypeHFS;
3017 HFSFlavor hfsFlavor;
3018
3019 fnames[i] = NULL;
3020 GetDragItemReferenceNumber(theDrag, i + 1, &item);
3021 err = GetFlavorDataSize(theDrag, item, type, &size);
3022 if (err != noErr || size > sizeof(hfsFlavor))
3023 continue;
3024 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
3025 if (err != noErr)
3026 continue;
3027 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
3028 }
3029 count = j;
3030
3031 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003032
3033 /* Fake mouse event to wake from stall */
3034 PostEvent(mouseUp, 0);
3035
Bram Moolenaar071d4272004-06-13 20:20:40 +00003036 return noErr;
3037}
3038
3039/*
3040 * Initialise the GUI. Create all the windows, set up all the call-backs
3041 * etc.
3042 */
3043 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003044gui_mch_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003045{
3046 /* TODO: Move most of this stuff toward gui_mch_init */
Bram Moolenaar39858af2008-03-12 20:48:13 +00003047 Rect windRect;
3048 MenuHandle pomme;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003049 EventHandlerRef mouseWheelHandlerRef;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003050 EventTypeSpec eventTypeSpec;
Bram Moolenaar39858af2008-03-12 20:48:13 +00003051 ControlRef rootControl;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003052
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003053 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003054 gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003055
Bram Moolenaar071d4272004-06-13 20:20:40 +00003056#if 1
3057 InitCursor();
3058
Bram Moolenaar071d4272004-06-13 20:20:40 +00003059 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003060
3061#ifdef USE_AEVENT
3062 (void) InstallAEHandlers();
3063#endif
3064
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003065 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003066
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003067 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003068
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003069 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003070
3071 DrawMenuBar();
3072
3073
3074#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003075 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003076#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003077 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003078#endif
3079
3080 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003081 zoomDocProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003082 (WindowPtr)-1L, true, 0);
Bram Moolenaare02d7b22007-06-19 14:29:43 +00003083 CreateRootControl(gui.VimWindow, &rootControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003084 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3085 gui.VimWindow, NULL);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003086 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003087
3088 gui.char_width = 7;
3089 gui.char_height = 11;
3090 gui.char_ascent = 6;
3091 gui.num_rows = 24;
3092 gui.num_cols = 80;
3093 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3094
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003095 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3096 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003097
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003098 /* Install Carbon event callbacks. */
3099 (void)InstallFontPanelHandler();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003100
3101 dragRectEnbl = FALSE;
3102 dragRgn = NULL;
3103 dragRectControl = kCreateEmpty;
3104 cursorRgn = NewRgn();
3105#endif
3106 /* Display any pending error messages */
3107 display_errors();
3108
3109 /* Get background/foreground colors from system */
Bram Moolenaar720c7102007-05-10 18:07:50 +00003110 /* TODO: do the appropriate call to get real defaults */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003111 gui.norm_pixel = 0x00000000;
3112 gui.back_pixel = 0x00FFFFFF;
3113
3114 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3115 * file). */
3116 set_normal_colors();
3117
3118 /*
3119 * Check that none of the colors are the same as the background color.
3120 * Then store the current values as the defaults.
3121 */
3122 gui_check_colors();
3123 gui.def_norm_pixel = gui.norm_pixel;
3124 gui.def_back_pixel = gui.back_pixel;
3125
3126 /* Get the colors for the highlight groups (gui_check_colors() might have
3127 * changed them) */
3128 highlight_gui_started();
3129
3130 /*
3131 * Setting the gui constants
3132 */
3133#ifdef FEAT_MENU
3134 gui.menu_height = 0;
3135#endif
3136 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3137 gui.border_offset = gui.border_width = 2;
3138
Bram Moolenaar720c7102007-05-10 18:07:50 +00003139 /* If Quartz-style text anti aliasing is available (see
Bram Moolenaar071d4272004-06-13 20:20:40 +00003140 gui_mch_draw_string() below), enable it for all font sizes. */
3141 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003142
Bram Moolenaar071d4272004-06-13 20:20:40 +00003143 eventTypeSpec.eventClass = kEventClassMouse;
3144 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3145 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3146 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3147 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3148 {
3149 mouseWheelHandlerRef = NULL;
3150 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3151 mouseWheelHandlerUPP = NULL;
3152 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003153
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003154#ifdef USE_CARBONKEYHANDLER
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003155 InterfaceTypeList supportedServices = { kUnicodeDocument };
3156 NewTSMDocument(1, supportedServices, &gTSMDocument, 0);
3157
3158 /* We don't support inline input yet, use input window by default */
3159 UseInputWindow(gTSMDocument, TRUE);
3160
3161 /* Should we activate the document by default? */
3162 // ActivateTSMDocument(gTSMDocument);
3163
3164 EventTypeSpec textEventTypes[] = {
3165 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea },
3166 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
3167 { kEventClassTextInput, kEventTextInputPosToOffset },
3168 { kEventClassTextInput, kEventTextInputOffsetToPos },
3169 };
3170
3171 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_text_input);
3172 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP,
3173 NR_ELEMS(textEventTypes),
3174 textEventTypes, NULL, NULL))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003175 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003176 DisposeEventHandlerUPP(keyEventHandlerUPP);
3177 keyEventHandlerUPP = NULL;
3178 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003179
3180 EventTypeSpec windowEventTypes[] = {
3181 { kEventClassWindow, kEventWindowActivated },
3182 { kEventClassWindow, kEventWindowDeactivated },
3183 };
3184
3185 /* Install window event handler to support TSMDocument activate and
3186 * deactivate */
3187 winEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_window_activate);
3188 if (noErr != InstallWindowEventHandler(gui.VimWindow,
3189 winEventHandlerUPP,
3190 NR_ELEMS(windowEventTypes),
3191 windowEventTypes, NULL, NULL))
3192 {
3193 DisposeEventHandlerUPP(winEventHandlerUPP);
3194 winEventHandlerUPP = NULL;
3195 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003196#endif
3197
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003198/*
3199#ifdef FEAT_MBYTE
3200 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3201#endif
3202*/
3203
Bram Moolenaar79ee3152007-04-26 16:20:50 +00003204#ifdef FEAT_GUI_TABLINE
3205 /*
3206 * Create the tabline
3207 */
3208 initialise_tabline();
3209#endif
3210
Bram Moolenaar071d4272004-06-13 20:20:40 +00003211 /* TODO: Load bitmap if using TOOLBAR */
3212 return OK;
3213}
3214
3215/*
3216 * Called when the foreground or background color has been changed.
3217 */
3218 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003219gui_mch_new_colors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003220{
3221 /* TODO:
3222 * This proc is called when Normal is set to a value
Bram Moolenaar68dfcdf2011-12-14 15:07:29 +01003223 * so what must be done? I don't know
Bram Moolenaar071d4272004-06-13 20:20:40 +00003224 */
3225}
3226
3227/*
3228 * Open the GUI window which was created by a call to gui_mch_init().
3229 */
3230 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003231gui_mch_open(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003232{
3233 ShowWindow(gui.VimWindow);
3234
3235 if (gui_win_x != -1 && gui_win_y != -1)
3236 gui_mch_set_winpos(gui_win_x, gui_win_y);
3237
Bram Moolenaar071d4272004-06-13 20:20:40 +00003238 /*
3239 * Make the GUI the foreground process (in case it was launched
3240 * from the Terminal or via :gui).
3241 */
3242 {
3243 ProcessSerialNumber psn;
3244 if (GetCurrentProcess(&psn) == noErr)
3245 SetFrontProcess(&psn);
3246 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003247
3248 return OK;
3249}
3250
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003251#ifdef USE_ATSUI_DRAWING
3252 static void
3253gui_mac_dispose_atsui_style(void)
3254{
3255 if (p_macatsui && gFontStyle)
3256 ATSUDisposeStyle(gFontStyle);
3257#ifdef FEAT_MBYTE
3258 if (p_macatsui && gWideFontStyle)
3259 ATSUDisposeStyle(gWideFontStyle);
3260#endif
3261}
3262#endif
3263
Bram Moolenaar071d4272004-06-13 20:20:40 +00003264 void
3265gui_mch_exit(int rc)
3266{
3267 /* TODO: find out all what is missing here? */
3268 DisposeRgn(cursorRgn);
3269
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003270#ifdef USE_CARBONKEYHANDLER
3271 if (keyEventHandlerUPP)
3272 DisposeEventHandlerUPP(keyEventHandlerUPP);
3273#endif
3274
Bram Moolenaar071d4272004-06-13 20:20:40 +00003275 if (mouseWheelHandlerUPP != NULL)
3276 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003277
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003278#ifdef USE_ATSUI_DRAWING
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003279 gui_mac_dispose_atsui_style();
3280#endif
3281
3282#ifdef USE_CARBONKEYHANDLER
3283 FixTSMDocument(gTSMDocument);
3284 DeactivateTSMDocument(gTSMDocument);
3285 DeleteTSMDocument(gTSMDocument);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003286#endif
3287
Bram Moolenaar071d4272004-06-13 20:20:40 +00003288 /* Exit to shell? */
3289 exit(rc);
3290}
3291
3292/*
3293 * Get the position of the top left corner of the window.
3294 */
3295 int
3296gui_mch_get_winpos(int *x, int *y)
3297{
3298 /* TODO */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003299 Rect bounds;
3300 OSStatus status;
3301
3302 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003303 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003304
3305 if (status != noErr)
3306 return FAIL;
3307 *x = bounds.left;
3308 *y = bounds.top;
3309 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003310}
3311
3312/*
3313 * Set the position of the top left corner of the window to the given
3314 * coordinates.
3315 */
3316 void
3317gui_mch_set_winpos(int x, int y)
3318{
3319 /* TODO: Should make sure the window is move within range
3320 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3321 */
Bram Moolenaarec831732007-08-30 10:51:14 +00003322 MoveWindowStructure(gui.VimWindow, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003323}
3324
3325 void
3326gui_mch_set_shellsize(
3327 int width,
3328 int height,
3329 int min_width,
3330 int min_height,
3331 int base_width,
Bram Moolenaarafa24992006-03-27 20:58:26 +00003332 int base_height,
3333 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003334{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003335 CGrafPtr VimPort;
3336 Rect VimBound;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003337
3338 if (gui.which_scrollbars[SBAR_LEFT])
3339 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003340 VimPort = GetWindowPort(gui.VimWindow);
3341 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003342 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003343 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003344 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003345 }
3346 else
3347 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003348 VimPort = GetWindowPort(gui.VimWindow);
3349 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003350 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003351 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003352 }
3353
3354 SizeWindow(gui.VimWindow, width, height, TRUE);
3355
3356 gui_resize_shell(width, height);
3357}
3358
3359/*
3360 * Get the screen dimensions.
3361 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3362 * Is there no way to find out how wide the borders really are?
Bram Moolenaar720c7102007-05-10 18:07:50 +00003363 * TODO: Add live update of those value on suspend/resume.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003364 */
3365 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003366gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003367{
3368 GDHandle dominantDevice = GetMainDevice();
3369 Rect screenRect = (**dominantDevice).gdRect;
3370
3371 *screen_w = screenRect.right - 10;
3372 *screen_h = screenRect.bottom - 40;
3373}
3374
3375
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003376/*
3377 * Open the Font Panel and wait for the user to select a font and
3378 * close the panel. Then fill the buffer pointed to by font_name with
3379 * the name and size of the selected font and return the font's handle,
3380 * or NOFONT in case of an error.
3381 */
3382 static GuiFont
3383gui_mac_select_font(char_u *font_name)
3384{
3385 GuiFont selected_font = NOFONT;
3386 OSStatus status;
3387 FontSelectionQDStyle curr_font;
3388
3389 /* Initialize the Font Panel with the current font. */
3390 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3391 curr_font.size = (gui.norm_font >> 16);
3392 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3393 curr_font.instance.fontStyle = 0;
3394 curr_font.hasColor = false;
3395 curr_font.version = 0; /* version number of the style structure */
3396 status = SetFontInfoForSelection(kFontSelectionQDType,
3397 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3398
3399 gFontPanelInfo.family = curr_font.instance.fontFamily;
3400 gFontPanelInfo.style = curr_font.instance.fontStyle;
3401 gFontPanelInfo.size = curr_font.size;
3402
3403 /* Pop up the Font Panel. */
3404 status = FPShowHideFontPanel();
3405 if (status == noErr)
3406 {
3407 /*
3408 * The Font Panel is modeless. We really need it to be modal,
3409 * so we spin in an event loop until the panel is closed.
3410 */
3411 gFontPanelInfo.isPanelVisible = true;
3412 while (gFontPanelInfo.isPanelVisible)
3413 {
3414 EventRecord e;
3415 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3416 }
3417
3418 GetFontPanelSelection(font_name);
3419 selected_font = gui_mac_find_font(font_name);
3420 }
3421 return selected_font;
3422}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003423
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003424#ifdef USE_ATSUI_DRAWING
3425 static void
3426gui_mac_create_atsui_style(void)
3427{
3428 if (p_macatsui && gFontStyle == NULL)
3429 {
3430 if (ATSUCreateStyle(&gFontStyle) != noErr)
3431 gFontStyle = NULL;
3432 }
3433#ifdef FEAT_MBYTE
3434 if (p_macatsui && gWideFontStyle == NULL)
3435 {
3436 if (ATSUCreateStyle(&gWideFontStyle) != noErr)
3437 gWideFontStyle = NULL;
3438 }
3439#endif
3440
3441 p_macatsui_last = p_macatsui;
3442}
3443#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003444
3445/*
3446 * Initialise vim to use the font with the given name. Return FAIL if the font
3447 * could not be loaded, OK otherwise.
3448 */
3449 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003450gui_mch_init_font(char_u *font_name, int fontset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003451{
3452 /* TODO: Add support for bold italic underline proportional etc... */
3453 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003454 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003455 FontInfo font_info;
3456 short font_id;
3457 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003458 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003459
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003460#ifdef USE_ATSUI_DRAWING
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003461 gui_mac_create_atsui_style();
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003462#endif
3463
Bram Moolenaar071d4272004-06-13 20:20:40 +00003464 if (font_name == NULL)
3465 {
3466 /* First try to get the suggested font */
3467 GetFNum(suggestedFont, &font_id);
3468
3469 if (font_id == 0)
3470 {
3471 /* Then pickup the standard application font */
3472 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003473 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003474 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003475 else
3476 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003477 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3478 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003479 else if (STRCMP(font_name, "*") == 0)
3480 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003481 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003482
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003483 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003484 if (font == NOFONT)
3485 return FAIL;
3486
3487 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003488 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003489 if (new_p_guifont != NULL)
3490 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003491 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003492 vim_free(p_guifont);
3493 p_guifont = new_p_guifont;
3494 /* Replace spaces in the font name with underscores. */
3495 for ( ; *new_p_guifont; ++new_p_guifont)
3496 {
3497 if (*new_p_guifont == ' ')
3498 *new_p_guifont = '_';
3499 }
3500 }
3501 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003502 else
3503 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003504 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003505 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003506
3507 if (font == NOFONT)
3508 return FAIL;
3509 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003510
Bram Moolenaar071d4272004-06-13 20:20:40 +00003511 gui.norm_font = font;
3512
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003513 hl_set_font_name(used_font_name);
3514
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003515 TextSize(font >> 16);
3516 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003517
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003518 GetFontInfo(&font_info);
3519
3520 gui.char_ascent = font_info.ascent;
3521 gui.char_width = CharWidth('_');
3522 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3523
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003524#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003525 if (p_macatsui && gFontStyle)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003526 gui_mac_set_font_attributes(font);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003527#endif
3528
Bram Moolenaar071d4272004-06-13 20:20:40 +00003529 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003530}
3531
Bram Moolenaar02743632005-07-25 20:42:36 +00003532/*
3533 * Adjust gui.char_height (after 'linespace' was changed).
3534 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003535 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003536gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003537{
3538 FontInfo font_info;
3539
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003540 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003541 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3542 gui.char_ascent = font_info.ascent + p_linespace / 2;
3543 return OK;
3544}
3545
3546/*
3547 * Get a font structure for highlighting.
3548 */
3549 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003550gui_mch_get_font(char_u *name, int giveErrorIfMissing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003551{
3552 GuiFont font;
3553
3554 font = gui_mac_find_font(name);
3555
3556 if (font == NOFONT)
3557 {
3558 if (giveErrorIfMissing)
3559 EMSG2(_(e_font), name);
3560 return NOFONT;
3561 }
3562 /*
3563 * TODO : Accept only monospace
3564 */
3565
3566 return font;
3567}
3568
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003569#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003570/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003571 * Return the name of font "font" in allocated memory.
3572 * Don't know how to get the actual name, thus use the provided name.
3573 */
3574 char_u *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003575gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003576{
3577 if (name == NULL)
3578 return NULL;
3579 return vim_strsave(name);
3580}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003581#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003582
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003583#ifdef USE_ATSUI_DRAWING
3584 static void
3585gui_mac_set_font_attributes(GuiFont font)
3586{
3587 ATSUFontID fontID;
3588 Fixed fontSize;
3589 Fixed fontWidth;
3590
3591 fontID = font & 0xFFFF;
3592 fontSize = Long2Fix(font >> 16);
3593 fontWidth = Long2Fix(gui.char_width);
3594
3595 ATSUAttributeTag attribTags[] =
3596 {
3597 kATSUFontTag, kATSUSizeTag, kATSUImposeWidthTag,
3598 kATSUMaxATSUITagValue + 1
3599 };
3600
3601 ByteCount attribSizes[] =
3602 {
3603 sizeof(ATSUFontID), sizeof(Fixed), sizeof(fontWidth),
3604 sizeof(font)
3605 };
3606
3607 ATSUAttributeValuePtr attribValues[] =
3608 {
3609 &fontID, &fontSize, &fontWidth, &font
3610 };
3611
3612 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3613 {
3614 if (ATSUSetAttributes(gFontStyle,
3615 (sizeof attribTags) / sizeof(ATSUAttributeTag),
3616 attribTags, attribSizes, attribValues) != noErr)
3617 {
3618# ifndef NDEBUG
3619 fprintf(stderr, "couldn't set font style\n");
3620# endif
3621 ATSUDisposeStyle(gFontStyle);
3622 gFontStyle = NULL;
3623 }
3624
3625#ifdef FEAT_MBYTE
3626 if (has_mbyte)
3627 {
3628 /* FIXME: we should use a more mbyte sensitive way to support
3629 * wide font drawing */
3630 fontWidth = Long2Fix(gui.char_width * 2);
3631
3632 if (ATSUSetAttributes(gWideFontStyle,
3633 (sizeof attribTags) / sizeof(ATSUAttributeTag),
3634 attribTags, attribSizes, attribValues) != noErr)
3635 {
3636 ATSUDisposeStyle(gWideFontStyle);
3637 gWideFontStyle = NULL;
3638 }
3639 }
3640#endif
3641 }
3642}
3643#endif
3644
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003645/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003646 * Set the current text font.
3647 */
3648 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003649gui_mch_set_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003650{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003651#ifdef USE_ATSUI_DRAWING
3652 GuiFont currFont;
3653 ByteCount actualFontByteCount;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003654
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003655 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003656 {
3657 /* Avoid setting same font again */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003658 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue + 1,
3659 sizeof(font), &currFont, &actualFontByteCount) == noErr
3660 && actualFontByteCount == (sizeof font))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003661 {
3662 if (currFont == font)
3663 return;
3664 }
3665
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003666 gui_mac_set_font_attributes(font);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003667 }
3668
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003669 if (p_macatsui && !gIsFontFallbackSet)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003670 {
3671 /* Setup automatic font substitution. The user's guifontwide
3672 * is tried first, then the system tries other fonts. */
3673/*
3674 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
3675 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
3676 ATSUCreateFontFallbacks(&gFontFallbacks);
3677 ATSUSetObjFontFallbacks(gFontFallbacks, );
3678*/
3679 if (gui.wide_font)
3680 {
3681 ATSUFontID fallbackFonts;
3682 gIsFontFallbackSet = TRUE;
3683
3684 if (FMGetFontFromFontFamilyInstance(
3685 (gui.wide_font & 0xFFFF),
3686 0,
3687 &fallbackFonts,
3688 NULL) == noErr)
3689 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003690 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID),
3691 &fallbackFonts,
3692 kATSUSequentialFallbacksPreferred);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003693 }
3694/*
3695 ATSUAttributeValuePtr fallbackValues[] = { };
3696*/
3697 }
3698 }
3699#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003700 TextSize(font >> 16);
3701 TextFont(font & 0xFFFF);
3702}
3703
Bram Moolenaar071d4272004-06-13 20:20:40 +00003704/*
3705 * If a font is not going to be used, free its structure.
3706 */
3707 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01003708gui_mch_free_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003709{
3710 /*
3711 * Free font when "font" is not 0.
3712 * Nothing to do in the current implementation, since
3713 * nothing is allocated for each font used.
3714 */
3715}
3716
Bram Moolenaar071d4272004-06-13 20:20:40 +00003717/*
3718 * Return the Pixel value (color) for the given color name. This routine was
3719 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3720 * Programmer's Guide.
3721 * Return INVALCOLOR when failed.
3722 */
3723 guicolor_T
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003724gui_mch_get_color(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003725{
3726 /* TODO: Add support for the new named color of MacOS 8
3727 */
3728 RGBColor MacColor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003729
Bram Moolenaarab302212016-04-26 20:59:29 +02003730 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003731 {
Bram Moolenaarab302212016-04-26 20:59:29 +02003732 LMGetHiliteRGB(&MacColor);
3733 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003734 }
Bram Moolenaarab302212016-04-26 20:59:29 +02003735 return gui_get_color_cmn(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003736}
3737
Bram Moolenaar26af85d2017-07-23 16:45:10 +02003738 guicolor_T
3739gui_mch_get_rgb_color(int r, int g, int b)
3740{
3741 return gui_get_rgb_color_cmn(r, g, b);
3742}
3743
Bram Moolenaar071d4272004-06-13 20:20:40 +00003744/*
3745 * Set the current text foreground color.
3746 */
3747 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003748gui_mch_set_fg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003749{
3750 RGBColor TheColor;
3751
3752 TheColor.red = Red(color) * 0x0101;
3753 TheColor.green = Green(color) * 0x0101;
3754 TheColor.blue = Blue(color) * 0x0101;
3755
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003756 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003757}
3758
3759/*
3760 * Set the current text background color.
3761 */
3762 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003763gui_mch_set_bg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003764{
3765 RGBColor TheColor;
3766
3767 TheColor.red = Red(color) * 0x0101;
3768 TheColor.green = Green(color) * 0x0101;
3769 TheColor.blue = Blue(color) * 0x0101;
3770
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003771 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003772}
3773
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003774RGBColor specialColor;
3775
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003776/*
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003777 * Set the current text special color.
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003778 */
3779 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003780gui_mch_set_sp_color(guicolor_T color)
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003781{
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003782 specialColor.red = Red(color) * 0x0101;
3783 specialColor.green = Green(color) * 0x0101;
3784 specialColor.blue = Blue(color) * 0x0101;
3785}
3786
3787/*
3788 * Draw undercurl at the bottom of the character cell.
3789 */
3790 static void
3791draw_undercurl(int flags, int row, int col, int cells)
3792{
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00003793 int x;
3794 int offset;
3795 const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 };
3796 int y = FILL_Y(row + 1) - 1;
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003797
3798 RGBForeColor(&specialColor);
3799
3800 offset = val[FILL_X(col) % 8];
3801 MoveTo(FILL_X(col), y - offset);
3802
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003803 for (x = FILL_X(col); x < FILL_X(col + cells); ++x)
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003804 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003805 offset = val[x % 8];
3806 LineTo(x, y - offset);
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003807 }
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003808}
3809
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003810
3811 static void
3812draw_string_QD(int row, int col, char_u *s, int len, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003813{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003814#ifdef FEAT_MBYTE
3815 char_u *tofree = NULL;
3816
3817 if (output_conv.vc_type != CONV_NONE)
3818 {
3819 tofree = string_convert(&output_conv, s, &len);
3820 if (tofree != NULL)
3821 s = tofree;
3822 }
3823#endif
3824
Bram Moolenaar071d4272004-06-13 20:20:40 +00003825 /*
3826 * On OS X, try using Quartz-style text antialiasing.
3827 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003828 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003829 {
3830 /* Quartz antialiasing is available only in OS 10.2 and later. */
3831 UInt32 qd_flags = (p_antialias ?
3832 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003833 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003834 }
3835
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003836 /*
3837 * When antialiasing we're using srcOr mode, we have to clear the block
3838 * before drawing the text.
3839 * Also needed when 'linespace' is non-zero to remove the cursor and
3840 * underlining.
3841 * But not when drawing transparently.
3842 * The following is like calling gui_mch_clear_block(row, col, row, col +
3843 * len - 1), but without setting the bg color to gui.back_pixel.
3844 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003845 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003846 && !(flags & DRAW_TRANSP))
3847 {
3848 Rect rc;
3849
3850 rc.left = FILL_X(col);
3851 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003852#ifdef FEAT_MBYTE
3853 /* Multibyte computation taken from gui_w32.c */
3854 if (has_mbyte)
3855 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003856 /* Compute the length in display cells. */
Bram Moolenaar72597a52010-07-18 15:31:08 +02003857 rc.right = FILL_X(col + mb_string2cells(s, len));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003858 }
3859 else
3860#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003861 rc.right = FILL_X(col + len) + (col + len == Columns);
3862 rc.bottom = FILL_Y(row + 1);
3863 EraseRect(&rc);
3864 }
3865
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003866 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003867 {
3868 StyleParameter face;
3869
3870 face = normal;
3871 if (flags & DRAW_BOLD)
3872 face |= bold;
3873 if (flags & DRAW_UNDERL)
3874 face |= underline;
3875 TextFace(face);
3876
3877 /* Quartz antialiasing works only in srcOr transfer mode. */
3878 TextMode(srcOr);
3879
Bram Moolenaar071d4272004-06-13 20:20:40 +00003880 MoveTo(TEXT_X(col), TEXT_Y(row));
3881 DrawText((char*)s, 0, len);
3882 }
3883 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003884 {
3885 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003886 TextMode(srcCopy);
3887 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003888
3889 /* SelectFont(hdc, gui.currFont); */
3890
3891 if (flags & DRAW_TRANSP)
3892 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003893 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003894 }
3895
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003896 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003897 DrawText((char *)s, 0, len);
3898
3899 if (flags & DRAW_BOLD)
3900 {
3901 TextMode(srcOr);
3902 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3903 DrawText((char *)s, 0, len);
3904 }
3905
3906 if (flags & DRAW_UNDERL)
3907 {
3908 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3909 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
3910 }
Bram Moolenaarcf4b00c2017-09-02 18:33:56 +02003911 if (flags & DRAW_STRIKE)
3912 {
3913 MoveTo(FILL_X(col), FILL_Y(row + 1) - gui.char_height/2);
3914 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - gui.char_height/2);
3915 }
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003916 }
3917
3918 if (flags & DRAW_UNDERC)
3919 draw_undercurl(flags, row, col, len);
3920
3921#ifdef FEAT_MBYTE
3922 vim_free(tofree);
3923#endif
3924}
3925
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003926#ifdef USE_ATSUI_DRAWING
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003927
3928 static void
3929draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
3930{
3931 /* ATSUI requires utf-16 strings */
3932 UniCharCount utf16_len;
3933 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
3934 utf16_len /= sizeof(UniChar);
3935
3936 /* - ATSUI automatically antialiases text (Someone)
3937 * - for some reason it does not work... (Jussi) */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003938#ifdef MAC_ATSUI_DEBUG
3939 fprintf(stderr, "row = %d, col = %d, len = %d: '%c'\n",
3940 row, col, len, len == 1 ? s[0] : ' ');
3941#endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003942 /*
3943 * When antialiasing we're using srcOr mode, we have to clear the block
3944 * before drawing the text.
3945 * Also needed when 'linespace' is non-zero to remove the cursor and
3946 * underlining.
3947 * But not when drawing transparently.
3948 * The following is like calling gui_mch_clear_block(row, col, row, col +
3949 * len - 1), but without setting the bg color to gui.back_pixel.
3950 */
3951 if ((flags & DRAW_TRANSP) == 0)
3952 {
3953 Rect rc;
3954
3955 rc.left = FILL_X(col);
3956 rc.top = FILL_Y(row);
3957 /* Multibyte computation taken from gui_w32.c */
3958 if (has_mbyte)
3959 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003960 /* Compute the length in display cells. */
Bram Moolenaar72597a52010-07-18 15:31:08 +02003961 rc.right = FILL_X(col + mb_string2cells(s, len));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003962 }
3963 else
3964 rc.right = FILL_X(col + len) + (col + len == Columns);
3965
3966 rc.bottom = FILL_Y(row + 1);
3967 EraseRect(&rc);
3968 }
3969
3970 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003971 TextMode(srcCopy);
3972 TextFace(normal);
3973
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003974 /* SelectFont(hdc, gui.currFont); */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003975 if (flags & DRAW_TRANSP)
3976 {
3977 TextMode(srcOr);
3978 }
3979
3980 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003981
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003982 if (gFontStyle && flags & DRAW_BOLD)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003983 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003984 Boolean attValue = true;
3985 ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag };
3986 ByteCount attribSizes[] = { sizeof(Boolean) };
3987 ATSUAttributeValuePtr attribValues[] = { &attValue };
3988
3989 ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, attribValues);
3990 }
3991
Bram Moolenaar76b96fc2010-07-17 16:44:59 +02003992 UInt32 useAntialias = p_antialias ? kATSStyleApplyAntiAliasing
3993 : kATSStyleNoAntiAliasing;
3994 if (useAntialias != useAntialias_cached)
3995 {
3996 ATSUAttributeTag attribTags[] = { kATSUStyleRenderingOptionsTag };
3997 ByteCount attribSizes[] = { sizeof(UInt32) };
3998 ATSUAttributeValuePtr attribValues[] = { &useAntialias };
3999
4000 if (gFontStyle)
4001 ATSUSetAttributes(gFontStyle, 1, attribTags,
4002 attribSizes, attribValues);
4003 if (gWideFontStyle)
4004 ATSUSetAttributes(gWideFontStyle, 1, attribTags,
4005 attribSizes, attribValues);
4006
4007 useAntialias_cached = useAntialias;
4008 }
4009
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004010#ifdef FEAT_MBYTE
4011 if (has_mbyte)
4012 {
4013 int n, width_in_cell, last_width_in_cell;
4014 UniCharArrayOffset offset = 0;
4015 UniCharCount yet_to_draw = 0;
4016 ATSUTextLayout textLayout;
4017 ATSUStyle textStyle;
4018
4019 last_width_in_cell = 1;
4020 ATSUCreateTextLayout(&textLayout);
4021 ATSUSetTextPointerLocation(textLayout, tofree,
4022 kATSUFromTextBeginning,
4023 kATSUToTextEnd, utf16_len);
4024 /*
4025 ATSUSetRunStyle(textLayout, gFontStyle,
4026 kATSUFromTextBeginning, kATSUToTextEnd); */
4027
4028 /* Compute the length in display cells. */
4029 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
4030 {
4031 width_in_cell = (*mb_ptr2cells)(s + n);
4032
4033 /* probably we are switching from single byte character
4034 * to multibyte characters (which requires more than one
4035 * cell to draw) */
4036 if (width_in_cell != last_width_in_cell)
4037 {
4038#ifdef MAC_ATSUI_DEBUG
4039 fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n",
4040 n, last_width_in_cell, width_in_cell, offset, yet_to_draw);
4041#endif
4042 textStyle = last_width_in_cell > 1 ? gWideFontStyle
4043 : gFontStyle;
4044
4045 ATSUSetRunStyle(textLayout, textStyle, offset, yet_to_draw);
4046 offset += yet_to_draw;
4047 yet_to_draw = 0;
4048 last_width_in_cell = width_in_cell;
4049 }
4050
4051 yet_to_draw++;
4052 }
4053
4054 if (yet_to_draw)
4055 {
4056#ifdef MAC_ATSUI_DEBUG
4057 fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n",
4058 n, last_width_in_cell, width_in_cell, offset, yet_to_draw);
4059#endif
4060 /* finish the rest style */
4061 textStyle = width_in_cell > 1 ? gWideFontStyle : gFontStyle;
4062 ATSUSetRunStyle(textLayout, textStyle, offset, kATSUToTextEnd);
4063 }
4064
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004065 ATSUSetTransientFontMatching(textLayout, TRUE);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004066 ATSUDrawText(textLayout,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004067 kATSUFromTextBeginning, kATSUToTextEnd,
4068 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004069 ATSUDisposeTextLayout(textLayout);
4070 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004071 else
4072#endif
4073 {
4074 ATSUTextLayout textLayout;
4075
4076 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4077 kATSUFromTextBeginning, kATSUToTextEnd,
4078 utf16_len,
4079 (gFontStyle ? 1 : 0), &utf16_len,
4080 (gFontStyle ? &gFontStyle : NULL),
4081 &textLayout) == noErr)
4082 {
4083 ATSUSetTransientFontMatching(textLayout, TRUE);
4084
4085 ATSUDrawText(textLayout,
4086 kATSUFromTextBeginning, kATSUToTextEnd,
4087 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4088
4089 ATSUDisposeTextLayout(textLayout);
4090 }
4091 }
4092
4093 /* drawing is done, now reset bold to normal */
4094 if (gFontStyle && flags & DRAW_BOLD)
4095 {
4096 Boolean attValue = false;
4097
4098 ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag };
4099 ByteCount attribSizes[] = { sizeof(Boolean) };
4100 ATSUAttributeValuePtr attribValues[] = { &attValue };
4101
4102 ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes,
4103 attribValues);
4104 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004105 }
4106
Bram Moolenaar5fe38612005-11-26 23:45:02 +00004107 if (flags & DRAW_UNDERC)
4108 draw_undercurl(flags, row, col, len);
4109
Bram Moolenaar071d4272004-06-13 20:20:40 +00004110 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004111}
4112#endif
4113
4114 void
4115gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
4116{
4117#if defined(USE_ATSUI_DRAWING)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004118 if (p_macatsui == 0 && p_macatsui_last != 0)
4119 /* switch from macatsui to nomacatsui */
4120 gui_mac_dispose_atsui_style();
4121 else if (p_macatsui != 0 && p_macatsui_last == 0)
4122 /* switch from nomacatsui to macatsui */
4123 gui_mac_create_atsui_style();
4124
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004125 if (p_macatsui)
4126 draw_string_ATSUI(row, col, s, len, flags);
4127 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004128#endif
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004129 draw_string_QD(row, col, s, len, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004130}
4131
4132/*
4133 * Return OK if the key with the termcap name "name" is supported.
4134 */
4135 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004136gui_mch_haskey(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004137{
4138 int i;
4139
4140 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4141 if (name[0] == special_keys[i].vim_code0 &&
4142 name[1] == special_keys[i].vim_code1)
4143 return OK;
4144 return FAIL;
4145}
4146
4147 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004148gui_mch_beep(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004149{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004150 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004151}
4152
4153 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004154gui_mch_flash(int msec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004155{
4156 /* Do a visual beep by reversing the foreground and background colors */
4157 Rect rc;
4158
4159 /*
4160 * Note: InvertRect() excludes right and bottom of rectangle.
4161 */
4162 rc.left = 0;
4163 rc.top = 0;
4164 rc.right = gui.num_cols * gui.char_width;
4165 rc.bottom = gui.num_rows * gui.char_height;
4166 InvertRect(&rc);
4167
4168 ui_delay((long)msec, TRUE); /* wait for some msec */
4169
4170 InvertRect(&rc);
4171}
4172
4173/*
4174 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4175 */
4176 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004177gui_mch_invert_rectangle(int r, int c, int nr, int nc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004178{
4179 Rect rc;
4180
4181 /*
4182 * Note: InvertRect() excludes right and bottom of rectangle.
4183 */
4184 rc.left = FILL_X(c);
4185 rc.top = FILL_Y(r);
4186 rc.right = rc.left + nc * gui.char_width;
4187 rc.bottom = rc.top + nr * gui.char_height;
4188 InvertRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004189}
4190
4191/*
4192 * Iconify the GUI window.
4193 */
4194 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004195gui_mch_iconify(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004196{
4197 /* TODO: find out what could replace iconify
4198 * -window shade?
4199 * -hide application?
4200 */
4201}
4202
4203#if defined(FEAT_EVAL) || defined(PROTO)
4204/*
4205 * Bring the Vim window to the foreground.
4206 */
4207 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004208gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004209{
4210 /* TODO */
4211}
4212#endif
4213
4214/*
4215 * Draw a cursor without focus.
4216 */
4217 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004218gui_mch_draw_hollow_cursor(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004219{
4220 Rect rc;
4221
Bram Moolenaar071d4272004-06-13 20:20:40 +00004222 /*
4223 * Note: FrameRect() excludes right and bottom of rectangle.
4224 */
4225 rc.left = FILL_X(gui.col);
4226 rc.top = FILL_Y(gui.row);
4227 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004228#ifdef FEAT_MBYTE
4229 if (mb_lefthalve(gui.row, gui.col))
4230 rc.right += gui.char_width;
4231#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004232 rc.bottom = rc.top + gui.char_height;
4233
4234 gui_mch_set_fg_color(color);
4235
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004236 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004237}
4238
4239/*
4240 * Draw part of a cursor, only w pixels wide, and h pixels high.
4241 */
4242 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004243gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004244{
4245 Rect rc;
4246
4247#ifdef FEAT_RIGHTLEFT
4248 /* vertical line should be on the right of current point */
4249 if (CURSOR_BAR_RIGHT)
4250 rc.left = FILL_X(gui.col + 1) - w;
4251 else
4252#endif
4253 rc.left = FILL_X(gui.col);
4254 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4255 rc.right = rc.left + w;
4256 rc.bottom = rc.top + h;
4257
4258 gui_mch_set_fg_color(color);
4259
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004260 FrameRect(&rc);
4261// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004262}
4263
4264
4265
4266/*
4267 * Catch up with any queued X events. This may put keyboard input into the
4268 * input buffer, call resize call-backs, trigger timers etc. If there is
4269 * nothing in the X event queue (& no timers pending), then we return
4270 * immediately.
4271 */
4272 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004273gui_mch_update(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004274{
4275 /* TODO: find what to do
4276 * maybe call gui_mch_wait_for_chars (0)
4277 * more like look at EventQueue then
4278 * call heart of gui_mch_wait_for_chars;
4279 *
4280 * if (eventther)
4281 * gui_mac_handle_event(&event);
4282 */
4283 EventRecord theEvent;
4284
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004285 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004286 if (theEvent.what != nullEvent)
4287 gui_mch_wait_for_chars(0);
4288}
4289
4290/*
4291 * Simple wrapper to neglect more easily the time
4292 * spent inside WaitNextEvent while profiling.
4293 */
4294
Bram Moolenaar071d4272004-06-13 20:20:40 +00004295 pascal
4296 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004297WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004298{
4299 if (((long) sleep) < -1)
4300 sleep = 32767;
4301 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4302}
4303
4304/*
4305 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4306 * from the keyboard.
4307 * wtime == -1 Wait forever.
4308 * wtime == 0 This should never happen.
4309 * wtime > 0 Wait wtime milliseconds for a character.
4310 * Returns OK if a character was found to be available within the given time,
4311 * or FAIL otherwise.
4312 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004313 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004314gui_mch_wait_for_chars(int wtime)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004315{
4316 EventMask mask = (everyEvent);
4317 EventRecord event;
4318 long entryTick;
4319 long currentTick;
4320 long sleeppyTick;
4321
4322 /* If we are providing life feedback with the scrollbar,
4323 * we don't want to try to wait for an event, or else
4324 * there won't be any life feedback.
4325 */
4326 if (dragged_sb != NULL)
4327 return FAIL;
4328 /* TODO: Check if FAIL is the proper return code */
4329
4330 entryTick = TickCount();
4331
4332 allow_scrollbar = TRUE;
4333
4334 do
4335 {
4336/* if (dragRectControl == kCreateEmpty)
4337 {
4338 dragRgn = NULL;
4339 dragRectControl = kNothing;
4340 }
4341 else*/ if (dragRectControl == kCreateRect)
4342 {
4343 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004344 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004345 dragRectControl = kNothing;
4346 }
4347 /*
4348 * Don't use gui_mch_update() because then we will spin-lock until a
4349 * char arrives, instead we use WaitNextEventWrp() to hang until an
4350 * event arrives. No need to check for input_buf_full because we are
4351 * returning as soon as it contains a single char.
4352 */
Bram Moolenaarb05034a2010-09-21 17:34:31 +02004353 /* TODO: reduce wtime accordingly??? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004354 if (wtime > -1)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004355 sleeppyTick = 60 * wtime / 1000;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004356 else
4357 sleeppyTick = 32767;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004358
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004359 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004360 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004361 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004362 if (input_available())
4363 {
4364 allow_scrollbar = FALSE;
4365 return OK;
4366 }
4367 }
4368 currentTick = TickCount();
4369 }
4370 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4371
4372 allow_scrollbar = FALSE;
4373 return FAIL;
4374}
4375
Bram Moolenaar071d4272004-06-13 20:20:40 +00004376/*
4377 * Output routines.
4378 */
4379
4380/* Flush any output to the screen */
4381 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004382gui_mch_flush(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004383{
4384 /* TODO: Is anything needed here? */
4385}
4386
4387/*
4388 * Clear a rectangular region of the screen from text pos (row1, col1) to
4389 * (row2, col2) inclusive.
4390 */
4391 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004392gui_mch_clear_block(int row1, int col1, int row2, int col2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004393{
4394 Rect rc;
4395
4396 /*
4397 * Clear one extra pixel at the far right, for when bold characters have
4398 * spilled over to the next column.
4399 */
4400 rc.left = FILL_X(col1);
4401 rc.top = FILL_Y(row1);
4402 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4403 rc.bottom = FILL_Y(row2 + 1);
4404
4405 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004406 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004407}
4408
4409/*
4410 * Clear the whole text window.
4411 */
4412 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004413gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004414{
4415 Rect rc;
4416
4417 rc.left = 0;
4418 rc.top = 0;
4419 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4420 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4421
4422 gui_mch_set_bg_color(gui.back_pixel);
4423 EraseRect(&rc);
4424/* gui_mch_set_fg_color(gui.norm_pixel);
4425 FrameRect(&rc);
4426*/
4427}
4428
4429/*
4430 * Delete the given number of lines from the given row, scrolling up any
4431 * text further down within the scroll region.
4432 */
4433 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004434gui_mch_delete_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004435{
4436 Rect rc;
4437
4438 /* changed without checking! */
4439 rc.left = FILL_X(gui.scroll_region_left);
4440 rc.right = FILL_X(gui.scroll_region_right + 1);
4441 rc.top = FILL_Y(row);
4442 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4443
4444 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004445 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004446
4447 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4448 gui.scroll_region_left,
4449 gui.scroll_region_bot, gui.scroll_region_right);
4450}
4451
4452/*
4453 * Insert the given number of lines before the given row, scrolling down any
4454 * following text within the scroll region.
4455 */
4456 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004457gui_mch_insert_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004458{
4459 Rect rc;
4460
4461 rc.left = FILL_X(gui.scroll_region_left);
4462 rc.right = FILL_X(gui.scroll_region_right + 1);
4463 rc.top = FILL_Y(row);
4464 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4465
4466 gui_mch_set_bg_color(gui.back_pixel);
4467
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004468 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004469
4470 /* Update gui.cursor_row if the cursor scrolled or copied over */
4471 if (gui.cursor_row >= gui.row
4472 && gui.cursor_col >= gui.scroll_region_left
4473 && gui.cursor_col <= gui.scroll_region_right)
4474 {
4475 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4476 gui.cursor_row += num_lines;
4477 else if (gui.cursor_row <= gui.scroll_region_bot)
4478 gui.cursor_is_valid = FALSE;
4479 }
4480
4481 gui_clear_block(row, gui.scroll_region_left,
4482 row + num_lines - 1, gui.scroll_region_right);
4483}
4484
4485 /*
4486 * TODO: add a vim format to the clipboard which remember
4487 * LINEWISE, CHARWISE, BLOCKWISE
4488 */
4489
4490 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004491clip_mch_request_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004492{
4493
4494 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004495 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004496 Size scrapSize;
4497 ScrapFlavorFlags scrapFlags;
4498 ScrapRef scrap = nil;
4499 OSStatus error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004500 int type;
4501 char *searchCR;
4502 char_u *tempclip;
4503
4504
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004505 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004506 if (error != noErr)
4507 return;
4508
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004509 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4510 if (error == noErr)
4511 {
4512 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4513 if (error == noErr && scrapSize > 1)
4514 flavor = 1;
4515 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004516
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004517 if (flavor == 0)
4518 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004519 error = GetScrapFlavorFlags(scrap, SCRAPTEXTFLAVOR, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004520 if (error != noErr)
4521 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004522
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004523 error = GetScrapFlavorSize(scrap, SCRAPTEXTFLAVOR, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004524 if (error != noErr)
4525 return;
4526 }
4527
4528 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004529
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004530 /* In CARBON we don't need a Handle, a pointer is good */
4531 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004532
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004533 /* tempclip = lalloc(scrapSize+1, TRUE); */
4534 HLock(textOfClip);
4535 error = GetScrapFlavorData(scrap,
4536 flavor ? VIMSCRAPFLAVOR : SCRAPTEXTFLAVOR,
4537 &scrapSize, *textOfClip);
4538 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004539
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004540 if (flavor)
4541 type = **textOfClip;
4542 else
Bram Moolenaard44347f2011-06-19 01:14:29 +02004543 type = MAUTO;
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004544
4545 tempclip = lalloc(scrapSize + 1, TRUE);
4546 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4547 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004548
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004549#ifdef MACOS_CONVERT
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004550 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004551 /* Convert from utf-16 (clipboard) */
4552 size_t encLen = 0;
4553 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004554
4555 if (to != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004556 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004557 scrapSize = encLen;
4558 vim_free(tempclip);
4559 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004560 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004561 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004562#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004563
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004564 searchCR = (char *)tempclip;
4565 while (searchCR != NULL)
4566 {
4567 searchCR = strchr(searchCR, '\r');
4568 if (searchCR != NULL)
4569 *searchCR = '\n';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004570 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004571
4572 clip_yank_selection(type, tempclip, scrapSize, cbd);
4573
4574 vim_free(tempclip);
4575 HUnlock(textOfClip);
4576
4577 DisposeHandle(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004578}
4579
4580 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004581clip_mch_lose_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004582{
4583 /*
4584 * TODO: Really nothing to do?
4585 */
4586}
4587
4588 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004589clip_mch_own_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004590{
4591 return OK;
4592}
4593
4594/*
4595 * Send the current selection to the clipboard.
4596 */
4597 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004598clip_mch_set_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004599{
4600 Handle textOfClip;
4601 long scrapSize;
4602 int type;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004603 ScrapRef scrap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604
4605 char_u *str = NULL;
4606
4607 if (!cbd->owned)
4608 return;
4609
4610 clip_get_selection(cbd);
4611
4612 /*
4613 * Once we set the clipboard, lose ownership. If another application sets
4614 * the clipboard, we don't want to think that we still own it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004615 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004616 cbd->owned = FALSE;
4617
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004618 type = clip_convert_selection(&str, (long_u *)&scrapSize, cbd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004619
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004620#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004621 size_t utf16_len = 0;
4622 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
4623 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004624 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004625 scrapSize = utf16_len;
4626 vim_free(str);
4627 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004628 }
4629#endif
4630
4631 if (type >= 0)
4632 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004633 ClearCurrentScrap();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004634
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004635 textOfClip = NewHandle(scrapSize + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004636 HLock(textOfClip);
4637
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004638 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004639 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004640 GetCurrentScrap(&scrap);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004641 PutScrapFlavor(scrap, SCRAPTEXTFLAVOR, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004642 scrapSize, *textOfClip + 1);
4643 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4644 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004645 HUnlock(textOfClip);
4646 DisposeHandle(textOfClip);
4647 }
4648
4649 vim_free(str);
4650}
4651
4652 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004653gui_mch_set_text_area_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004654{
4655 Rect VimBound;
4656
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004657/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004658 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004659
4660 if (gui.which_scrollbars[SBAR_LEFT])
4661 {
4662 VimBound.left = -gui.scrollbar_width + 1;
4663 }
4664 else
4665 {
4666 VimBound.left = 0;
4667 }
4668
Bram Moolenaar071d4272004-06-13 20:20:40 +00004669 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004670
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004671 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004672}
4673
4674/*
4675 * Menu stuff.
4676 */
4677
4678 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004679gui_mch_enable_menu(int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004680{
4681 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004682 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004683 */
4684}
4685
4686 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004687gui_mch_set_menu_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004688{
4689 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004690 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004691 */
4692}
4693
4694/*
4695 * Add a sub menu to the menu bar.
4696 */
4697 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004698gui_mch_add_menu(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004699{
4700 /*
4701 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4702 * TODO: use menu->mnemonic and menu->actext
4703 * TODO: Try to reuse menu id
4704 * Carbon Help suggest to use only id between 1 and 235
4705 */
4706 static long next_avail_id = 128;
4707 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004708#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004709 CFStringRef name;
4710#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004711 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004712#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004713 short index;
4714 vimmenu_T *parent = menu->parent;
4715 vimmenu_T *brother = menu->next;
4716
4717 /* Cannot add a menu if ... */
4718 if ((parent != NULL && parent->submenu_id == 0))
4719 return;
4720
4721 /* menu ID greater than 1024 are reserved for ??? */
4722 if (next_avail_id == 1024)
4723 return;
4724
4725 /* My brother could be the PopUp, find my real brother */
4726 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4727 brother = brother->next;
4728
4729 /* Find where to insert the menu (for MenuBar) */
4730 if ((parent == NULL) && (brother != NULL))
4731 menu_after_me = brother->submenu_id;
4732
4733 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4734 if (!menu_is_menubar(menu->name))
4735 menu_after_me = hierMenu;
4736
4737 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004738#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004739 name = menu_title_removing_mnemonic(menu);
4740#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004741 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004742#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004743 if (name == NULL)
4744 return;
4745
4746 /* Create the menu unless it's the help menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004747 {
4748 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004749 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4750 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004751 */
4752 menu->submenu_id = next_avail_id;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004753#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004754 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
4755 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
4756#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004757 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004758#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004759 next_avail_id++;
4760 }
4761
4762 if (parent == NULL)
4763 {
4764 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4765
4766 /* TODO: Verify if we could only Insert Menu if really part of the
4767 * menubar The Inserted menu are scanned or the Command-key combos
4768 */
4769
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004770 /* Insert the menu */
4771 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004772#if 1
4773 /* Vim should normally update it. TODO: verify */
4774 DrawMenuBar();
4775#endif
4776 }
4777 else
4778 {
4779 /* Adding as a submenu */
4780
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004781 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004782
4783 /* Call InsertMenuItem followed by SetMenuItemText
4784 * to avoid special character recognition by InsertMenuItem
4785 */
4786 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004787#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004788 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4789#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004790 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004791#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004792 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4793 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4794 InsertMenu(menu->submenu_handle, hierMenu);
4795 }
4796
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004797#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004798 CFRelease(name);
4799#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004800 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004801#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004802
4803#if 0
4804 /* Done by Vim later on */
4805 DrawMenuBar();
4806#endif
4807}
4808
4809/*
4810 * Add a menu item to a menu
4811 */
4812 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004813gui_mch_add_menu_item(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004814{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004815#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004816 CFStringRef name;
4817#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004818 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004819#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004820 vimmenu_T *parent = menu->parent;
4821 int menu_inserted;
4822
4823 /* Cannot add item, if the menu have not been created */
4824 if (parent->submenu_id == 0)
4825 return;
4826
4827 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4828 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4829
4830 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004831#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004832 name = menu_title_removing_mnemonic(menu);
4833#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004834 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004835#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004836
4837 /* Where are just a menu item, so no handle, no id */
4838 menu->submenu_id = 0;
4839 menu->submenu_handle = NULL;
4840
Bram Moolenaar071d4272004-06-13 20:20:40 +00004841 menu_inserted = 0;
4842 if (menu->actext)
4843 {
4844 /* If the accelerator text for the menu item looks like it describes
4845 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4846 * item's command equivalent.
4847 */
4848 int key = 0;
4849 int modifiers = 0;
4850 char_u *p_actext;
4851
4852 p_actext = menu->actext;
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +02004853 key = find_special_key(&p_actext, &modifiers, FALSE, FALSE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004854 if (*p_actext != 0)
4855 key = 0; /* error: trailing text */
4856 /* find_special_key() returns a keycode with as many of the
4857 * specified modifiers as appropriate already applied (e.g., for
4858 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4859 * as the only modifier). Since we want to display all of the
4860 * modifiers, we need to convert the keycode back to a printable
4861 * character plus modifiers.
4862 * TODO: Write an alternative find_special_key() that doesn't
4863 * apply modifiers.
4864 */
4865 if (key > 0 && key < 32)
4866 {
4867 /* Convert a control key to an uppercase letter. Note that
4868 * by this point it is no longer possible to distinguish
4869 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4870 */
4871 modifiers |= MOD_MASK_CTRL;
4872 key += '@';
4873 }
4874 /* If the keycode is an uppercase letter, set the Shift modifier.
4875 * If it is a lowercase letter, don't set the modifier, but convert
4876 * the letter to uppercase for display in the menu.
4877 */
4878 else if (key >= 'A' && key <= 'Z')
4879 modifiers |= MOD_MASK_SHIFT;
4880 else if (key >= 'a' && key <= 'z')
4881 key += 'A' - 'a';
4882 /* Note: keycodes below 0x22 are reserved by Apple. */
4883 if (key >= 0x22 && vim_isprintc_strict(key))
4884 {
4885 int valid = 1;
4886 char_u mac_mods = kMenuNoModifiers;
4887 /* Convert Vim modifier codes to Menu Manager equivalents. */
4888 if (modifiers & MOD_MASK_SHIFT)
4889 mac_mods |= kMenuShiftModifier;
4890 if (modifiers & MOD_MASK_CTRL)
4891 mac_mods |= kMenuControlModifier;
4892 if (!(modifiers & MOD_MASK_CMD))
4893 mac_mods |= kMenuNoCommandModifier;
4894 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4895 valid = 0; /* TODO: will Alt someday map to Option? */
4896 if (valid)
4897 {
4898 char_u item_txt[10];
4899 /* Insert the menu item after idx, with its command key. */
4900 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4901 item_txt[3] = key;
4902 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4903 /* Set the modifier keys. */
4904 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4905 menu_inserted = 1;
4906 }
4907 }
4908 }
4909 /* Call InsertMenuItem followed by SetMenuItemText
4910 * to avoid special character recognition by InsertMenuItem
4911 */
4912 if (!menu_inserted)
4913 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4914 /* Set the menu item name. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004915#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004916 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4917#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004918 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004919#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004920
4921#if 0
4922 /* Called by Vim */
4923 DrawMenuBar();
4924#endif
4925
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004926#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004927 CFRelease(name);
4928#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004929 /* TODO: Can name be freed? */
4930 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004931#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004932}
4933
4934 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004935gui_mch_toggle_tearoffs(int enable)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004936{
4937 /* no tearoff menus */
4938}
4939
4940/*
4941 * Destroy the machine specific menu widget.
4942 */
4943 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004944gui_mch_destroy_menu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004945{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004946 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004947
4948 if (index > 0)
4949 {
4950 if (menu->parent)
4951 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004952 {
4953 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004954 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004955
4956 /* Delete the Menu if it was a hierarchical Menu */
4957 if (menu->submenu_id != 0)
4958 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004959 DeleteMenu(menu->submenu_id);
4960 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004961 }
4962 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004963 }
4964#ifdef DEBUG_MAC_MENU
4965 else
4966 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004967 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004968 }
4969#endif
4970 }
4971 else
4972 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004973 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004974 DeleteMenu(menu->submenu_id);
4975 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004976 }
4977 }
4978 /* Shouldn't this be already done by Vim. TODO: Check */
4979 DrawMenuBar();
4980}
4981
4982/*
4983 * Make a menu either grey or not grey.
4984 */
4985 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004986gui_mch_menu_grey(vimmenu_T *menu, int grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004987{
4988 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004989 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004990/*
4991 index = menu->index;
4992*/
4993 if (grey)
4994 {
4995 if (menu->children)
4996 DisableMenuItem(menu->submenu_handle, index);
4997 if (menu->parent)
4998 if (menu->parent->submenu_handle)
4999 DisableMenuItem(menu->parent->submenu_handle, index);
5000 }
5001 else
5002 {
5003 if (menu->children)
5004 EnableMenuItem(menu->submenu_handle, index);
5005 if (menu->parent)
5006 if (menu->parent->submenu_handle)
5007 EnableMenuItem(menu->parent->submenu_handle, index);
5008 }
5009}
5010
5011/*
5012 * Make menu item hidden or not hidden
5013 */
5014 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005015gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005016{
5017 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005018 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005019}
5020
5021
5022/*
5023 * This is called after setting all the menus to grey/hidden or not.
5024 */
5025 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005026gui_mch_draw_menubar(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005027{
5028 DrawMenuBar();
5029}
5030
5031
5032/*
5033 * Scrollbar stuff.
5034 */
5035
5036 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005037gui_mch_enable_scrollbar(
5038 scrollbar_T *sb,
5039 int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005040{
5041 if (flag)
5042 ShowControl(sb->id);
5043 else
5044 HideControl(sb->id);
5045
5046#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005047 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005048#endif
5049}
5050
5051 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005052gui_mch_set_scrollbar_thumb(
5053 scrollbar_T *sb,
5054 long val,
5055 long size,
5056 long max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005057{
5058 SetControl32BitMaximum (sb->id, max);
5059 SetControl32BitMinimum (sb->id, 0);
5060 SetControl32BitValue (sb->id, val);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00005061 SetControlViewSize (sb->id, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005062#ifdef DEBUG_MAC_SB
Bram Moolenaarea034592016-06-02 22:27:08 +02005063 printf("thumb_sb (%x) %lx, %lx,%lx\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005064#endif
5065}
5066
5067 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005068gui_mch_set_scrollbar_pos(
5069 scrollbar_T *sb,
5070 int x,
5071 int y,
5072 int w,
5073 int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005074{
5075 gui_mch_set_bg_color(gui.back_pixel);
5076/* if (gui.which_scrollbars[SBAR_LEFT])
5077 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005078 MoveControl(sb->id, x-16, y);
5079 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005080 }
5081 else
5082 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005083 MoveControl(sb->id, x, y);
5084 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005085 }*/
5086 if (sb == &gui.bottom_sbar)
5087 h += 1;
5088 else
5089 w += 1;
5090
5091 if (gui.which_scrollbars[SBAR_LEFT])
5092 x -= 15;
5093
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005094 MoveControl(sb->id, x, y);
5095 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005096#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005097 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005098#endif
5099}
5100
5101 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005102gui_mch_create_scrollbar(
5103 scrollbar_T *sb,
5104 int orient) /* SBAR_VERT or SBAR_HORIZ */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005105{
5106 Rect bounds;
5107
5108 bounds.top = -16;
5109 bounds.bottom = -10;
5110 bounds.right = -10;
5111 bounds.left = -16;
5112
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005113 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005114 &bounds,
5115 "\pScrollBar",
5116 TRUE,
5117 0, /* current*/
5118 0, /* top */
5119 0, /* bottom */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005120 kControlScrollBarLiveProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005121 (long) sb->ident);
5122#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005123 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005124#endif
5125}
5126
5127 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005128gui_mch_destroy_scrollbar(scrollbar_T *sb)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005129{
5130 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005131 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005132#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005133 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005134#endif
5135}
5136
Bram Moolenaar703a8042016-06-04 16:24:32 +02005137 int
5138gui_mch_is_blinking(void)
5139{
5140 return FALSE;
5141}
Bram Moolenaar071d4272004-06-13 20:20:40 +00005142
Bram Moolenaar9d5d3c92016-07-07 16:43:02 +02005143 int
5144gui_mch_is_blink_off(void)
5145{
5146 return FALSE;
5147}
5148
Bram Moolenaar071d4272004-06-13 20:20:40 +00005149/*
5150 * Cursor blink functions.
5151 *
5152 * This is a simple state machine:
5153 * BLINK_NONE not blinking at all
5154 * BLINK_OFF blinking, cursor is not shown
5155 * BLINK_ON blinking, cursor is shown
5156 */
5157 void
5158gui_mch_set_blinking(long wait, long on, long off)
5159{
5160 /* TODO: TODO: TODO: TODO: */
5161/* blink_waittime = wait;
5162 blink_ontime = on;
5163 blink_offtime = off;*/
5164}
5165
5166/*
5167 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5168 */
5169 void
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +01005170gui_mch_stop_blink(int may_call_gui_update_cursor)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005171{
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +01005172 if (may_call_gui_update_cursor)
5173 gui_update_cursor(TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005174 /* TODO: TODO: TODO: TODO: */
5175/* gui_w32_rm_blink_timer();
5176 if (blink_state == BLINK_OFF)
5177 gui_update_cursor(TRUE, FALSE);
5178 blink_state = BLINK_NONE;*/
5179}
5180
5181/*
5182 * Start the cursor blinking. If it was already blinking, this restarts the
5183 * waiting time and shows the cursor.
5184 */
5185 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005186gui_mch_start_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005187{
5188 gui_update_cursor(TRUE, FALSE);
5189 /* TODO: TODO: TODO: TODO: */
5190/* gui_w32_rm_blink_timer(); */
5191
5192 /* Only switch blinking on if none of the times is zero */
5193/* if (blink_waittime && blink_ontime && blink_offtime)
5194 {
5195 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5196 (TIMERPROC)_OnBlinkTimer);
5197 blink_state = BLINK_ON;
5198 gui_update_cursor(TRUE, FALSE);
5199 }*/
5200}
5201
5202/*
5203 * Return the RGB value of a pixel as long.
5204 */
Bram Moolenaar1b58cdd2016-08-22 23:04:33 +02005205 guicolor_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00005206gui_mch_get_rgb(guicolor_T pixel)
5207{
Bram Moolenaar1b58cdd2016-08-22 23:04:33 +02005208 return (guicolor_T)((Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005209}
5210
5211
5212
5213#ifdef FEAT_BROWSE
5214/*
5215 * Pop open a file browser and return the file selected, in allocated memory,
5216 * or NULL if Cancel is hit.
5217 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5218 * title - Title message for the file browser dialog.
5219 * dflt - Default name of file.
5220 * ext - Default extension to be added to files without extensions.
5221 * initdir - directory in which to open the browser (NULL = current dir)
5222 * filter - Filter for matched files to choose from.
5223 * Has a format like this:
5224 * "C Files (*.c)\0*.c\0"
5225 * "All Files\0*.*\0\0"
5226 * If these two strings were concatenated, then a choice of two file
5227 * filters will be selectable to the user. Then only matching files will
5228 * be shown in the browser. If NULL, the default allows all files.
5229 *
5230 * *NOTE* - the filter string must be terminated with TWO nulls.
5231 */
5232 char_u *
5233gui_mch_browse(
5234 int saving,
5235 char_u *title,
5236 char_u *dflt,
5237 char_u *ext,
5238 char_u *initdir,
5239 char_u *filter)
5240{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005241 /* TODO: Add Ammon's safety check (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005242 NavReplyRecord reply;
5243 char_u *fname = NULL;
5244 char_u **fnames = NULL;
5245 long numFiles;
5246 NavDialogOptions navOptions;
5247 OSErr error;
5248
5249 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005250 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005251
5252
5253 /* TODO: If we get a :browse args, set the Multiple bit. */
5254 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5255 | kNavDontAutoTranslate
5256 | kNavDontAddTranslateItems
5257 /* | kNavAllowMultipleFiles */
5258 | kNavAllowStationery;
5259
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005260 (void) C2PascalString(title, &navOptions.message);
5261 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005262 /* Could set clientName?
5263 * windowTitle? (there's no title bar?)
5264 */
5265
5266 if (saving)
5267 {
5268 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005269 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005270 if (!reply.validRecord)
5271 return NULL;
5272 }
5273 else
5274 {
5275 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5276 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5277 if (!reply.validRecord)
5278 return NULL;
5279 }
5280
5281 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5282
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005283 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005284
5285 if (fnames)
5286 {
5287 fname = fnames[0];
5288 vim_free(fnames);
5289 }
5290
5291 /* TODO: Shorten the file name if possible */
5292 return fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005293}
5294#endif /* FEAT_BROWSE */
5295
5296#ifdef FEAT_GUI_DIALOG
5297/*
5298 * Stuff for dialogues
5299 */
5300
5301/*
5302 * Create a dialogue dynamically from the parameter strings.
5303 * type = type of dialogue (question, alert, etc.)
5304 * title = dialogue title. may be NULL for default title.
5305 * message = text to display. Dialogue sizes to accommodate it.
5306 * buttons = '\n' separated list of button captions, default first.
5307 * dfltbutton = number of default button.
5308 *
5309 * This routine returns 1 if the first button is pressed,
5310 * 2 for the second, etc.
5311 *
5312 * 0 indicates Esc was pressed.
5313 * -1 for unexpected error
5314 *
5315 * If stubbing out this fn, return 1.
5316 */
5317
5318typedef struct
5319{
5320 short idx;
5321 short width; /* Size of the text in pixel */
5322 Rect box;
5323} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5324
5325#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5326
5327 static void
5328macMoveDialogItem(
5329 DialogRef theDialog,
5330 short itemNumber,
5331 short X,
5332 short Y,
5333 Rect *inBox)
5334{
5335#if 0 /* USE_CARBONIZED */
5336 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005337 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005338 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005339 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005340#else
5341 short itemType;
5342 Handle itemHandle;
5343 Rect localBox;
5344 Rect *itemBox = &localBox;
5345
5346 if (inBox != nil)
5347 itemBox = inBox;
5348
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005349 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5350 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5351 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005352 /* To move a control (like a button) we need to call both
5353 * MoveControl and SetDialogItem. FAQ 6-18 */
5354 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005355 MoveControl((ControlRef) itemHandle, X, Y);
5356 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005357#endif
5358}
5359
5360 static void
5361macSizeDialogItem(
5362 DialogRef theDialog,
5363 short itemNumber,
5364 short width,
5365 short height)
5366{
5367 short itemType;
5368 Handle itemHandle;
5369 Rect itemBox;
5370
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005371 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005372
5373 /* When width or height is zero do not change it */
5374 if (width == 0)
5375 width = itemBox.right - itemBox.left;
5376 if (height == 0)
5377 height = itemBox.bottom - itemBox.top;
5378
5379#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005380 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005381#else
5382 /* Resize the bounding box */
5383 itemBox.right = itemBox.left + width;
5384 itemBox.bottom = itemBox.top + height;
5385
5386 /* To resize a control (like a button) we need to call both
5387 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5388 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005389 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005390
5391 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005392 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005393#endif
5394}
5395
5396 static void
5397macSetDialogItemText(
5398 DialogRef theDialog,
5399 short itemNumber,
5400 Str255 itemName)
5401{
5402 short itemType;
5403 Handle itemHandle;
5404 Rect itemBox;
5405
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005406 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005407
5408 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005409 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005410 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005411 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005412}
5413
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005414
5415/* ModalDialog() handler for message dialogs that have hotkey accelerators.
5416 * Expects a mapping of hotkey char to control index in gDialogHotKeys;
5417 * setting gDialogHotKeys to NULL disables any hotkey handling.
5418 */
5419 static pascal Boolean
5420DialogHotkeyFilterProc (
5421 DialogRef theDialog,
5422 EventRecord *event,
5423 DialogItemIndex *itemHit)
5424{
5425 char_u keyHit;
5426
5427 if (event->what == keyDown || event->what == autoKey)
5428 {
5429 keyHit = (event->message & charCodeMask);
5430
5431 if (gDialogHotKeys && gDialogHotKeys[keyHit])
5432 {
5433#ifdef DEBUG_MAC_DIALOG_HOTKEYS
5434 printf("user pressed hotkey '%c' --> item %d\n", keyHit, gDialogHotKeys[keyHit]);
5435#endif
5436 *itemHit = gDialogHotKeys[keyHit];
5437
5438 /* When handing off to StdFilterProc, pretend that the user
5439 * clicked the control manually. Note that this is also supposed
5440 * to cause the button to hilite briefly (to give some user
5441 * feedback), but this seems not to actually work (or it's too
5442 * fast to be seen).
5443 */
5444 event->what = kEventControlSimulateHit;
5445
5446 return true; /* we took care of it */
5447 }
5448
5449 /* Defer to the OS's standard behavior for this event.
5450 * This ensures that Enter will still activate the default button. */
5451 return StdFilterProc(theDialog, event, itemHit);
5452 }
5453 return false; /* Let ModalDialog deal with it */
5454}
5455
5456
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005457/* TODO: There have been some crashes with dialogs, check your inbox
5458 * (Jussi)
5459 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005460 int
5461gui_mch_dialog(
5462 int type,
5463 char_u *title,
5464 char_u *message,
5465 char_u *buttons,
5466 int dfltbutton,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01005467 char_u *textfield,
5468 int ex_cmd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005469{
5470 Handle buttonDITL;
5471 Handle iconDITL;
5472 Handle inputDITL;
5473 Handle messageDITL;
5474 Handle itemHandle;
5475 Handle iconHandle;
5476 DialogPtr theDialog;
5477 char_u len;
5478 char_u PascalTitle[256]; /* place holder for the title */
5479 char_u name[256];
5480 GrafPtr oldPort;
5481 short itemHit;
5482 char_u *buttonChar;
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005483 short hotKeys[256]; /* map of hotkey -> control ID */
5484 char_u aHotKey;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005485 Rect box;
5486 short button;
5487 short lastButton;
5488 short itemType;
5489 short useIcon;
5490 short width;
Bram Moolenaarec831732007-08-30 10:51:14 +00005491 short totalButtonWidth = 0; /* the width of all buttons together
Bram Moolenaar720c7102007-05-10 18:07:50 +00005492 including spacing */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005493 short widestButton = 0;
5494 short dfltButtonEdge = 20; /* gut feeling */
5495 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5496 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5497 short maximumWidth = 400; /* gut feeling */
5498 short maxButtonWidth = 175; /* gut feeling */
5499
5500 short vertical;
5501 short dialogHeight;
5502 short messageLines = 3;
5503 FontInfo textFontInfo;
5504
5505 vgmDlgItm iconItm;
5506 vgmDlgItm messageItm;
5507 vgmDlgItm inputItm;
5508 vgmDlgItm buttonItm;
5509
5510 WindowRef theWindow;
5511
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005512 ModalFilterUPP dialogUPP;
5513
Bram Moolenaar071d4272004-06-13 20:20:40 +00005514 /* Check 'v' flag in 'guioptions': vertical button placement. */
5515 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5516
5517 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005518 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005519
5520 /* Get the WindowRef */
5521 theWindow = GetDialogWindow(theDialog);
5522
5523 /* Hide the window.
5524 * 1. to avoid seeing slow drawing
5525 * 2. to prevent a problem seen while moving dialog item
5526 * within a visible window. (non-Carbon MacOS 9)
5527 * Could be avoided by changing the resource.
5528 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005529 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005530
5531 /* Change the graphical port to the dialog,
5532 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005533 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005534 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005535
5536 /* Get the info about the default text,
5537 * used to calculate the height of the message
5538 * and of the text field */
5539 GetFontInfo(&textFontInfo);
5540
5541 /* Set the dialog title */
5542 if (title != NULL)
5543 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005544 (void) C2PascalString(title, &PascalTitle);
5545 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005546 }
5547
5548 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005549 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005550 buttonChar = buttons;
5551 button = 0;
5552
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005553 /* initialize the hotkey mapping */
Bram Moolenaar7db5fc82010-05-24 11:59:29 +02005554 vim_memset(hotKeys, 0, sizeof(hotKeys));
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005555
Bram Moolenaar071d4272004-06-13 20:20:40 +00005556 for (;*buttonChar != 0;)
5557 {
5558 /* Get the name of the button */
5559 button++;
5560 len = 0;
5561 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5562 {
5563 if (*buttonChar != DLG_HOTKEY_CHAR)
5564 name[++len] = *buttonChar;
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005565 else
5566 {
5567 aHotKey = (char_u)*(buttonChar+1);
5568 if (aHotKey >= 'A' && aHotKey <= 'Z')
5569 aHotKey = (char_u)((int)aHotKey + (int)'a' - (int)'A');
5570 hotKeys[aHotKey] = button;
5571#ifdef DEBUG_MAC_DIALOG_HOTKEYS
5572 printf("### hotKey for button %d is '%c'\n", button, aHotKey);
5573#endif
5574 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005575 }
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005576
Bram Moolenaar071d4272004-06-13 20:20:40 +00005577 if (*buttonChar != 0)
5578 buttonChar++;
5579 name[0] = len;
5580
5581 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005582 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005583
5584 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005585 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005586
5587 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005588 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005589 /* Limit the size of any button to an acceptable value. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005590 /* TODO: Should be based on the message width */
5591 if (width > maxButtonWidth)
5592 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005593 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005594
5595 totalButtonWidth += width;
5596
5597 if (width > widestButton)
5598 widestButton = width;
5599 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005600 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005601 lastButton = button;
5602
5603 /* Add the icon to the Dialog Box. */
5604 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005605 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005606 switch (type)
5607 {
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005608 case VIM_GENERIC:
5609 case VIM_INFO:
5610 case VIM_QUESTION: useIcon = kNoteIcon; break;
5611 case VIM_WARNING: useIcon = kCautionIcon; break;
5612 case VIM_ERROR: useIcon = kStopIcon; break;
Bram Moolenaar8d4eecc2012-11-20 17:19:01 +01005613 default: useIcon = kStopIcon;
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005614 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005615 AppendDITL(theDialog, iconDITL, overlayDITL);
5616 ReleaseResource(iconDITL);
5617 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005618 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005619 iconHandle = GetIcon(useIcon);
5620 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005621
5622 /* Add the message to the Dialog box. */
5623 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005624 messageDITL = GetResource('DITL', 132);
5625 AppendDITL(theDialog, messageDITL, overlayDITL);
5626 ReleaseResource(messageDITL);
5627 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5628 (void) C2PascalString(message, &name);
5629 SetDialogItemText(itemHandle, name);
5630 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005631
5632 /* Add the input box if needed */
5633 if (textfield != NULL)
5634 {
Bram Moolenaard68071d2006-05-02 22:08:30 +00005635 /* Cheat for now reuse the message and convert to text edit */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005636 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005637 inputDITL = GetResource('DITL', 132);
5638 AppendDITL(theDialog, inputDITL, overlayDITL);
5639 ReleaseResource(inputDITL);
5640 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5641/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5642 (void) C2PascalString(textfield, &name);
5643 SetDialogItemText(itemHandle, name);
5644 inputItm.width = StringWidth(name);
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005645
5646 /* Hotkeys don't make sense if there's a text field */
5647 gDialogHotKeys = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005648 }
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005649 else
5650 /* Install hotkey table */
5651 gDialogHotKeys = (short *)&hotKeys;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005652
5653 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005654 SetDialogDefaultItem(theDialog, dfltbutton);
5655 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005656
5657 /* Reposition element */
5658
5659 /* Check if we need to force vertical */
5660 if (totalButtonWidth > maximumWidth)
5661 vertical = TRUE;
5662
5663 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005664 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005665 iconItm.box.right = box.right;
5666 iconItm.box.bottom = box.bottom;
5667
5668 /* Place Message */
5669 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005670 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5671 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005672
5673 /* Place Input */
5674 if (textfield != NULL)
5675 {
5676 inputItm.box.left = messageItm.box.left;
5677 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005678 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5679 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005680 /* Convert the static text into a text edit.
5681 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005682 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5683 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005684 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5685 }
5686
5687 /* Place Button */
5688 if (textfield != NULL)
5689 {
5690 buttonItm.box.left = inputItm.box.left;
5691 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5692 }
5693 else
5694 {
5695 buttonItm.box.left = messageItm.box.left;
5696 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5697 }
5698
5699 for (button=1; button <= lastButton; button++)
5700 {
5701
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005702 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaarec831732007-08-30 10:51:14 +00005703 /* With vertical, it's better to have all buttons the same length */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005704 if (vertical)
5705 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005706 macSizeDialogItem(theDialog, button, widestButton, 0);
5707 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005708 }
5709 /* Calculate position of next button */
5710 if (vertical)
5711 buttonItm.box.top = box.bottom + dfltElementSpacing;
5712 else
5713 buttonItm.box.left = box.right + dfltElementSpacing;
5714 }
5715
5716 /* Resize the dialog box */
5717 dialogHeight = box.bottom + dfltElementSpacing;
5718 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5719
Bram Moolenaar071d4272004-06-13 20:20:40 +00005720 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005721 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005722 /* Need a horizontal resize anyway so not that useful */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005723
5724 /* Display it */
5725 ShowWindow(theWindow);
5726/* BringToFront(theWindow); */
5727 SelectWindow(theWindow);
5728
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005729/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005730#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005731 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005732 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005733#endif
5734
Bram Moolenaard68071d2006-05-02 22:08:30 +00005735#ifdef USE_CARBONKEYHANDLER
5736 /* Avoid that we use key events for the main window. */
5737 dialog_busy = TRUE;
5738#endif
5739
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005740 /* Prepare the shortcut-handling filterProc for handing to the dialog */
5741 dialogUPP = NewModalFilterUPP(DialogHotkeyFilterProc);
5742
Bram Moolenaar071d4272004-06-13 20:20:40 +00005743 /* Hang until one of the button is hit */
5744 do
5745 {
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005746 ModalDialog(dialogUPP, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005747 } while ((itemHit < 1) || (itemHit > lastButton));
5748
Bram Moolenaard68071d2006-05-02 22:08:30 +00005749#ifdef USE_CARBONKEYHANDLER
5750 dialog_busy = FALSE;
5751#endif
5752
Bram Moolenaar071d4272004-06-13 20:20:40 +00005753 /* Copy back the text entered by the user into the param */
5754 if (textfield != NULL)
5755 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005756 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5757 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005758#if IOSIZE < 256
5759 /* Truncate the name to IOSIZE if needed */
5760 if (name[0] > IOSIZE)
5761 name[0] = IOSIZE - 1;
5762#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005763 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005764 }
5765
5766 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005767 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005768
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005769 /* Free the modal filterProc */
5770 DisposeRoutineDescriptor(dialogUPP);
5771
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005772 /* Get ride of the dialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005773 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005774
5775 return itemHit;
5776/*
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005777 * Useful thing which could be used
Bram Moolenaar071d4272004-06-13 20:20:40 +00005778 * SetDialogTimeout(): Auto click a button after timeout
5779 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5780 * MoveDialogItem(): Probably better than SetDialogItem
5781 * SizeDialogItem(): (but is it Carbon Only?)
Bram Moolenaar14d0e792007-08-30 08:35:35 +00005782 * AutoSizeDialog(): Magic resize of dialog based on text length
Bram Moolenaar071d4272004-06-13 20:20:40 +00005783 */
5784}
5785#endif /* FEAT_DIALOG_GUI */
5786
5787/*
5788 * Display the saved error message(s).
5789 */
5790#ifdef USE_MCH_ERRMSG
5791 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005792display_errors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005793{
5794 char *p;
5795 char_u pError[256];
5796
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005797 if (error_ga.ga_data == NULL)
5798 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005799
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005800 /* avoid putting up a message box with blanks only */
5801 for (p = (char *)error_ga.ga_data; *p; ++p)
5802 if (!isspace(*p))
5803 {
5804 if (STRLEN(p) > 255)
5805 pError[0] = 255;
5806 else
5807 pError[0] = STRLEN(p);
5808
5809 STRNCPY(&pError[1], p, pError[0]);
5810 ParamText(pError, nil, nil, nil);
5811 Alert(128, nil);
5812 break;
5813 /* TODO: handled message longer than 256 chars
5814 * use auto-sizeable alert
5815 * or dialog with scrollbars (TextEdit zone)
5816 */
5817 }
5818 ga_clear(&error_ga);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005819}
5820#endif
5821
5822/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005823 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005824 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00005825 void
5826gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005827{
5828 Point where;
5829
5830 GetMouse(&where);
5831
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005832 *x = where.h;
5833 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005834}
5835
5836 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005837gui_mch_setmouse(int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005838{
5839 /* TODO */
5840#if 0
5841 /* From FAQ 3-11 */
5842
5843 CursorDevicePtr myMouse;
5844 Point where;
5845
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005846 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5847 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005848 {
5849 /* New way */
5850
5851 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005852 * Get first device with one button.
5853 * This will probably be the standard mouse
5854 * start at head of cursor dev list
Bram Moolenaar071d4272004-06-13 20:20:40 +00005855 *
5856 */
5857
5858 myMouse = nil;
5859
5860 do
5861 {
5862 /* Get the next cursor device */
5863 CursorDeviceNextDevice(&myMouse);
5864 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005865 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005866
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005867 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005868 }
5869 else
5870 {
5871 /* Old way */
5872 where.h = x;
5873 where.v = y;
5874
5875 *(Point *)RawMouse = where;
5876 *(Point *)MTemp = where;
5877 *(Ptr) CrsrNew = 0xFFFF;
5878 }
5879#endif
5880}
5881
5882 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005883gui_mch_show_popupmenu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005884{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005885/*
5886 * Clone PopUp to use menu
5887 * Create a object descriptor for the current selection
5888 * Call the procedure
5889 */
5890
5891 MenuHandle CntxMenu;
5892 Point where;
5893 OSStatus status;
5894 UInt32 CntxType;
5895 SInt16 CntxMenuID;
5896 UInt16 CntxMenuItem;
5897 Str255 HelpName = "";
5898 GrafPtr savePort;
5899
5900 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005901 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005902
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005903 GetMouse(&where);
5904 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005905 CntxMenu = menu->submenu_handle;
5906
5907 /* TODO: Get the text selection from Vim */
5908
5909 /* Call to Handle Popup */
Bram Moolenaar48c2c9a2007-03-08 19:34:12 +00005910 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemRemoveHelp,
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005911 HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005912
5913 if (status == noErr)
5914 {
5915 if (CntxType == kCMMenuItemSelected)
5916 {
5917 /* Handle the menu CntxMenuID, CntxMenuItem */
5918 /* The submenu can be handle directly by gui_mac_handle_menu */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005919 /* But what about the current menu, is the menu changed by
5920 * ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005921 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005922 }
5923 else if (CntxMenuID == kCMShowHelpSelected)
5924 {
5925 /* Should come up with the help */
5926 }
5927 }
5928
5929 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005930 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005931}
5932
5933#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5934/* TODO: Is it need for MACOS_X? (Dany) */
5935 void
5936mch_post_buffer_write(buf_T *buf)
5937{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005938 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5939 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005940}
5941#endif
5942
5943#ifdef FEAT_TITLE
5944/*
5945 * Set the window title and icon.
5946 * (The icon is not taken care of).
5947 */
5948 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005949gui_mch_settitle(char_u *title, char_u *icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005950{
5951 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5952 * that 256. Even better get it to fit nicely in the titlebar.
5953 */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005954#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005955 CFStringRef windowTitle;
5956 size_t windowTitleLen;
5957#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005958 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005959#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005960
5961 if (title == NULL) /* nothing to do */
5962 return;
5963
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005964#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005965 windowTitleLen = STRLEN(title);
Bram Moolenaar446cb832008-06-24 21:56:24 +00005966 windowTitle = (CFStringRef)mac_enc_to_cfstring(title, windowTitleLen);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005967
5968 if (windowTitle)
5969 {
5970 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
5971 CFRelease(windowTitle);
5972 }
5973#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005974 pascalTitle = C2Pascal_save(title);
5975 if (pascalTitle != NULL)
5976 {
5977 SetWTitle(gui.VimWindow, pascalTitle);
5978 vim_free(pascalTitle);
5979 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005980#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005981}
5982#endif
5983
5984/*
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005985 * Transferred from os_mac.c for MacOS X using os_unix.c prep work
Bram Moolenaar071d4272004-06-13 20:20:40 +00005986 */
5987
5988 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005989C2PascalString(char_u *CString, Str255 *PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005990{
5991 char_u *PascalPtr = (char_u *) PascalString;
5992 int len;
5993 int i;
5994
5995 PascalPtr[0] = 0;
5996 if (CString == NULL)
5997 return 0;
5998
5999 len = STRLEN(CString);
6000 if (len > 255)
6001 len = 255;
6002
6003 for (i = 0; i < len; i++)
6004 PascalPtr[i+1] = CString[i];
6005
6006 PascalPtr[0] = len;
6007
6008 return 0;
6009}
6010
6011 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006012GetFSSpecFromPath(char_u *file, FSSpec *fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006013{
6014 /* From FAQ 8-12 */
6015 Str255 filePascal;
6016 CInfoPBRec myCPB;
6017 OSErr err;
6018
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006019 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006020
6021 myCPB.dirInfo.ioNamePtr = filePascal;
6022 myCPB.dirInfo.ioVRefNum = 0;
6023 myCPB.dirInfo.ioFDirIndex = 0;
6024 myCPB.dirInfo.ioDrDirID = 0;
6025
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006026 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006027
6028 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006029 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006030
6031 /* TODO: Use an error code mechanism */
6032 return 0;
6033}
6034
6035/*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006036 * Convert a FSSpec to a full path
Bram Moolenaar071d4272004-06-13 20:20:40 +00006037 */
6038
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006039char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006040{
6041 /*
6042 * TODO: Add protection for 256 char max.
6043 */
6044
6045 CInfoPBRec theCPB;
6046 char_u fname[256];
6047 char_u *filenamePtr = fname;
6048 OSErr error;
6049 int folder = 1;
6050#ifdef USE_UNIXFILENAME
6051 SInt16 dfltVol_vRefNum;
6052 SInt32 dfltVol_dirID;
6053 FSRef refFile;
6054 OSStatus status;
6055 UInt32 pathSize = 256;
6056 char_u pathname[256];
6057 char_u *path = pathname;
6058#else
6059 Str255 directoryName;
6060 char_u temporary[255];
6061 char_u *temporaryPtr = temporary;
6062#endif
6063
6064#ifdef USE_UNIXFILENAME
6065 /* Get the default volume */
6066 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006067 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006068
6069 if (error)
6070 return NULL;
6071#endif
6072
6073 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006074 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006075
6076 /* Get the info about the file specified in FSSpec */
6077 theCPB.dirInfo.ioFDirIndex = 0;
6078 theCPB.dirInfo.ioNamePtr = file.name;
6079 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006080 /*theCPB.hFileInfo.ioDirID = 0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006081 theCPB.dirInfo.ioDrDirID = file.parID;
6082
6083 /* As ioFDirIndex = 0, get the info of ioNamePtr,
6084 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006085 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006086
6087 /* If we are called for a new file we expect fnfErr */
6088 if ((error) && (error != fnfErr))
6089 return NULL;
6090
6091 /* Check if it's a file or folder */
6092 /* default to file if file don't exist */
6093 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
6094 folder = 0; /* It's not a folder */
6095 else
6096 folder = 1;
6097
6098#ifdef USE_UNIXFILENAME
6099 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006100 * The functions used here are available in Carbon, but do nothing on
6101 * MacOS 8 and 9.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006102 */
6103 if (error == fnfErr)
6104 {
6105 /* If the file to be saved does not already exist, it isn't possible
6106 to convert its FSSpec into an FSRef. But we can construct an
6107 FSSpec for the file's parent folder (since we have its volume and
6108 directory IDs), and since that folder does exist, we can convert
6109 that FSSpec into an FSRef, convert the FSRef in turn into a path,
6110 and, finally, append the filename. */
6111 FSSpec dirSpec;
6112 FSRef dirRef;
6113 Str255 emptyFilename = "\p";
6114 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
6115 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
6116 if (error)
6117 return NULL;
6118
6119 error = FSpMakeFSRef(&dirSpec, &dirRef);
6120 if (error)
6121 return NULL;
6122
6123 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
6124 if (status)
6125 return NULL;
6126
6127 STRCAT(path, "/");
6128 STRCAT(path, filenamePtr);
6129 }
6130 else
6131 {
6132 /* If the file to be saved already exists, we can get its full path
6133 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006134 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006135 if (error)
6136 return NULL;
6137
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006138 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006139 if (status)
6140 return NULL;
6141 }
6142
6143 /* Add a slash at the end if needed */
6144 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006145 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006146
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006147 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006148#else
6149 /* TODO: Get rid of all USE_UNIXFILENAME below */
6150 /* Set ioNamePtr, it's the same area which is always reused. */
6151 theCPB.dirInfo.ioNamePtr = directoryName;
6152
6153 /* Trick for first entry, set ioDrParID to the first value
6154 * we want for ioDrDirID*/
6155 theCPB.dirInfo.ioDrParID = file.parID;
6156 theCPB.dirInfo.ioDrDirID = file.parID;
6157
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006158 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006159 do
6160 {
6161 theCPB.dirInfo.ioFDirIndex = -1;
6162 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6163 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar720c7102007-05-10 18:07:50 +00006164 /* theCPB.dirInfo.ioDirID = irrelevant when ioFDirIndex = -1 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006165 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6166
6167 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6168 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006169 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006170
6171 if (error)
6172 return NULL;
6173
6174 /* Put the new directoryName in front of the current fname */
6175 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006176 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006177 STRCAT(filenamePtr, ":");
6178 STRCAT(filenamePtr, temporaryPtr);
6179 }
6180#if 1 /* def USE_UNIXFILENAME */
6181 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6182 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6183#else
6184 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6185#endif
6186
6187 /* Get the information about the volume on which the file reside */
6188 theCPB.dirInfo.ioFDirIndex = -1;
6189 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6190 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar720c7102007-05-10 18:07:50 +00006191 /* theCPB.dirInfo.ioDirID = irrelevant when ioFDirIndex = -1 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006192 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6193
6194 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6195 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006196 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006197
6198 if (error)
6199 return NULL;
6200
6201 /* For MacOS Classic always add the volume name */
6202 /* For MacOS X add the volume name preceded by "Volumes" */
Bram Moolenaar720c7102007-05-10 18:07:50 +00006203 /* when we are not referring to the boot volume */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006204#ifdef USE_UNIXFILENAME
6205 if (file.vRefNum != dfltVol_vRefNum)
6206#endif
6207 {
6208 /* Add the volume name */
6209 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006210 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006211 STRCAT(filenamePtr, ":");
6212 STRCAT(filenamePtr, temporaryPtr);
6213
6214#ifdef USE_UNIXFILENAME
6215 STRCPY(temporaryPtr, filenamePtr);
6216 filenamePtr[0] = 0; /* NULL terminate the string */
6217 STRCAT(filenamePtr, "Volumes:");
6218 STRCAT(filenamePtr, temporaryPtr);
6219#endif
6220 }
6221
6222 /* Append final path separator if it's a folder */
6223 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006224 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006225
6226 /* As we use Unix File Name for MacOS X convert it */
6227#ifdef USE_UNIXFILENAME
6228 /* Need to insert leading / */
6229 /* TODO: get the above code to use directly the / */
6230 STRCPY(&temporaryPtr[1], filenamePtr);
6231 temporaryPtr[0] = '/';
6232 STRCPY(filenamePtr, temporaryPtr);
6233 {
6234 char *p;
6235 for (p = fname; *p; p++)
6236 if (*p == ':')
6237 *p = '/';
6238 }
6239#endif
6240
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006241 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006242#endif
6243}
6244
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01006245#if (defined(FEAT_MBYTE) && defined(USE_CARBONKEYHANDLER)) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006246/*
6247 * Input Method Control functions.
6248 */
6249
6250/*
6251 * Notify cursor position to IM.
6252 */
6253 void
6254im_set_position(int row, int col)
6255{
Bram Moolenaar259f26a2018-05-15 22:25:40 +02006256# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00006257 /* TODO: Implement me! */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006258 im_start_row = row;
6259 im_start_col = col;
Bram Moolenaar259f26a2018-05-15 22:25:40 +02006260# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006261}
6262
6263static ScriptLanguageRecord gTSLWindow;
6264static ScriptLanguageRecord gTSLInsert;
6265static ScriptLanguageRecord gTSLDefault = { 0, 0 };
6266
6267static Component gTSCWindow;
6268static Component gTSCInsert;
6269static Component gTSCDefault;
6270
6271static int im_initialized = 0;
6272
6273 static void
6274im_on_window_switch(int active)
6275{
6276 ScriptLanguageRecord *slptr = NULL;
6277 OSStatus err;
6278
6279 if (! gui.in_use)
6280 return;
6281
6282 if (im_initialized == 0)
6283 {
6284 im_initialized = 1;
6285
6286 /* save default TSM component (should be U.S.) to default */
6287 GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault,
6288 kKeyboardInputMethodClass);
6289 }
6290
6291 if (active == TRUE)
6292 {
6293 im_is_active = TRUE;
6294 ActivateTSMDocument(gTSMDocument);
6295 slptr = &gTSLWindow;
6296
6297 if (slptr)
6298 {
6299 err = SetDefaultInputMethodOfClass(gTSCWindow, slptr,
6300 kKeyboardInputMethodClass);
6301 if (err == noErr)
6302 err = SetTextServiceLanguage(slptr);
6303
6304 if (err == noErr)
6305 KeyScript(slptr->fScript | smKeyForceKeyScriptMask);
6306 }
6307 }
6308 else
6309 {
6310 err = GetTextServiceLanguage(&gTSLWindow);
6311 if (err == noErr)
6312 slptr = &gTSLWindow;
6313
6314 if (slptr)
6315 GetDefaultInputMethodOfClass(&gTSCWindow, slptr,
6316 kKeyboardInputMethodClass);
6317
6318 im_is_active = FALSE;
6319 DeactivateTSMDocument(gTSMDocument);
6320 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006321}
6322
6323/*
6324 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6325 */
6326 void
6327im_set_active(int active)
6328{
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006329 ScriptLanguageRecord *slptr = NULL;
6330 OSStatus err;
6331
Bram Moolenaar819edbe2017-11-25 17:14:33 +01006332 if (!gui.in_use)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006333 return;
6334
6335 if (im_initialized == 0)
6336 {
6337 im_initialized = 1;
6338
6339 /* save default TSM component (should be U.S.) to default */
6340 GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault,
6341 kKeyboardInputMethodClass);
6342 }
6343
6344 if (active == TRUE)
6345 {
6346 im_is_active = TRUE;
6347 ActivateTSMDocument(gTSMDocument);
6348 slptr = &gTSLInsert;
6349
6350 if (slptr)
6351 {
6352 err = SetDefaultInputMethodOfClass(gTSCInsert, slptr,
6353 kKeyboardInputMethodClass);
6354 if (err == noErr)
6355 err = SetTextServiceLanguage(slptr);
6356
6357 if (err == noErr)
6358 KeyScript(slptr->fScript | smKeyForceKeyScriptMask);
6359 }
6360 }
6361 else
6362 {
6363 err = GetTextServiceLanguage(&gTSLInsert);
6364 if (err == noErr)
6365 slptr = &gTSLInsert;
6366
6367 if (slptr)
6368 GetDefaultInputMethodOfClass(&gTSCInsert, slptr,
6369 kKeyboardInputMethodClass);
6370
6371 /* restore to default when switch to normal mode, so than we could
6372 * enter commands easier */
6373 SetDefaultInputMethodOfClass(gTSCDefault, &gTSLDefault,
6374 kKeyboardInputMethodClass);
6375 SetTextServiceLanguage(&gTSLDefault);
6376
6377 im_is_active = FALSE;
6378 DeactivateTSMDocument(gTSMDocument);
6379 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006380}
6381
6382/*
6383 * Get IM status. When IM is on, return not 0. Else return 0.
6384 */
6385 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006386im_get_status(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006387{
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006388 if (! gui.in_use)
6389 return 0;
6390
6391 return im_is_active;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006392}
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006393
Bram Moolenaar819edbe2017-11-25 17:14:33 +01006394#endif /* defined(FEAT_MBYTE) || defined(PROTO) */
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006395
6396
6397
6398
6399#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
6400// drawer implementation
6401static MenuRef contextMenu = NULL;
6402enum
6403{
Bram Moolenaar43acbce2016-02-27 15:21:32 +01006404 kTabContextMenuId = 42
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006405};
6406
6407// the caller has to CFRelease() the returned string
6408 static CFStringRef
6409getTabLabel(tabpage_T *page)
6410{
6411 get_tabline_label(page, FALSE);
6412#ifdef MACOS_CONVERT
Bram Moolenaar446cb832008-06-24 21:56:24 +00006413 return (CFStringRef)mac_enc_to_cfstring(NameBuff, STRLEN(NameBuff));
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006414#else
6415 // TODO: check internal encoding?
6416 return CFStringCreateWithCString(kCFAllocatorDefault, (char *)NameBuff,
6417 kCFStringEncodingMacRoman);
6418#endif
6419}
6420
6421
6422#define DRAWER_SIZE 150
6423#define DRAWER_INSET 16
6424
6425static ControlRef dataBrowser = NULL;
6426
6427// when the tabline is hidden, vim doesn't call update_tabline(). When
Bram Moolenaarb05034a2010-09-21 17:34:31 +02006428// the tabline is shown again, show_tabline() is called before update_tabline(),
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006429// and because of this, the tab labels and vim's internal tabs are out of sync
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006430// for a very short time. to prevent inconsistent state, we store the labels
6431// of the tabs, not pointers to the tabs (which are invalid for a short time).
6432static CFStringRef *tabLabels = NULL;
6433static int tabLabelsSize = 0;
6434
6435enum
6436{
6437 kTabsColumn = 'Tabs'
6438};
6439
6440 static int
6441getTabCount(void)
6442{
6443 tabpage_T *tp;
6444 int numTabs = 0;
6445
Bram Moolenaar29323592016-07-24 22:04:11 +02006446 FOR_ALL_TABPAGES(tp)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006447 ++numTabs;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006448 return numTabs;
6449}
6450
6451// data browser item display callback
6452 static OSStatus
6453dbItemDataCallback(ControlRef browser,
6454 DataBrowserItemID itemID,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006455 DataBrowserPropertyID property /* column id */,
6456 DataBrowserItemDataRef itemData,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006457 Boolean changeValue)
6458{
6459 OSStatus status = noErr;
6460
6461 // assert(property == kTabsColumn); // why is this violated??
6462
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006463 // changeValue is true if we have a modifiable list and data was changed.
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006464 // In our case, it's always false.
6465 // (that is: if (changeValue) updateInternalData(); else return
6466 // internalData();
6467 if (!changeValue)
6468 {
6469 CFStringRef str;
6470
6471 assert(itemID - 1 >= 0 && itemID - 1 < tabLabelsSize);
6472 str = tabLabels[itemID - 1];
6473 status = SetDataBrowserItemDataText(itemData, str);
6474 }
6475 else
6476 status = errDataBrowserPropertyNotSupported;
6477
6478 return status;
6479}
6480
6481// data browser action callback
6482 static void
6483dbItemNotificationCallback(ControlRef browser,
6484 DataBrowserItemID item,
6485 DataBrowserItemNotification message)
6486{
6487 switch (message)
6488 {
6489 case kDataBrowserItemSelected:
6490 send_tabline_event(item);
6491 break;
6492 }
6493}
6494
6495// callbacks needed for contextual menu:
6496 static void
6497dbGetContextualMenuCallback(ControlRef browser,
6498 MenuRef *menu,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006499 UInt32 *helpType,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006500 CFStringRef *helpItemString,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006501 AEDesc *selection)
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006502{
6503 // on mac os 9: kCMHelpItemNoHelp, but it's not the same
6504 *helpType = kCMHelpItemRemoveHelp; // OS X only ;-)
6505 *helpItemString = NULL;
6506
6507 *menu = contextMenu;
6508}
6509
6510 static void
6511dbSelectContextualMenuCallback(ControlRef browser,
6512 MenuRef menu,
6513 UInt32 selectionType,
6514 SInt16 menuID,
6515 MenuItemIndex menuItem)
6516{
6517 if (selectionType == kCMMenuItemSelected)
6518 {
6519 MenuCommand command;
6520 GetMenuItemCommandID(menu, menuItem, &command);
6521
6522 // get tab that was selected when the context menu appeared
6523 // (there is always one tab selected). TODO: check if the context menu
6524 // isn't opened on an item but on empty space (has to be possible some
6525 // way, the finder does it too ;-) )
6526 Handle items = NewHandle(0);
6527 if (items != NULL)
6528 {
6529 int numItems;
6530
6531 GetDataBrowserItems(browser, kDataBrowserNoItem, false,
6532 kDataBrowserItemIsSelected, items);
6533 numItems = GetHandleSize(items) / sizeof(DataBrowserItemID);
6534 if (numItems > 0)
6535 {
6536 int idx;
6537 DataBrowserItemID *itemsPtr;
6538
6539 HLock(items);
6540 itemsPtr = (DataBrowserItemID *)*items;
6541 idx = itemsPtr[0];
6542 HUnlock(items);
6543 send_tabline_menu_event(idx, command);
6544 }
6545 DisposeHandle(items);
6546 }
6547 }
6548}
6549
6550// focus callback of the data browser to always leave focus in vim
6551 static OSStatus
6552dbFocusCallback(EventHandlerCallRef handler, EventRef event, void *data)
6553{
6554 assert(GetEventClass(event) == kEventClassControl
6555 && GetEventKind(event) == kEventControlSetFocusPart);
6556
6557 return paramErr;
6558}
6559
6560
6561// drawer callback to resize data browser to drawer size
6562 static OSStatus
6563drawerCallback(EventHandlerCallRef handler, EventRef event, void *data)
6564{
6565 switch (GetEventKind(event))
6566 {
6567 case kEventWindowBoundsChanged: // move or resize
6568 {
6569 UInt32 attribs;
6570 GetEventParameter(event, kEventParamAttributes, typeUInt32,
6571 NULL, sizeof(attribs), NULL, &attribs);
6572 if (attribs & kWindowBoundsChangeSizeChanged) // resize
6573 {
6574 Rect r;
6575 GetWindowBounds(drawer, kWindowContentRgn, &r);
6576 SetRect(&r, 0, 0, r.right - r.left, r.bottom - r.top);
6577 SetControlBounds(dataBrowser, &r);
6578 SetDataBrowserTableViewNamedColumnWidth(dataBrowser,
6579 kTabsColumn, r.right);
6580 }
6581 }
6582 break;
6583 }
6584
6585 return eventNotHandledErr;
6586}
6587
6588// Load DataBrowserChangeAttributes() dynamically on tiger (and better).
6589// This way the code works on 10.2 and 10.3 as well (it doesn't have the
6590// blue highlights in the list view on these systems, though. Oh well.)
6591
6592
6593#import <mach-o/dyld.h>
6594
6595enum { kMyDataBrowserAttributeListViewAlternatingRowColors = (1 << 1) };
6596
6597 static OSStatus
6598myDataBrowserChangeAttributes(ControlRef inDataBrowser,
6599 OptionBits inAttributesToSet,
6600 OptionBits inAttributesToClear)
6601{
6602 long osVersion;
6603 char *symbolName;
6604 NSSymbol symbol = NULL;
6605 OSStatus (*dataBrowserChangeAttributes)(ControlRef inDataBrowser,
6606 OptionBits inAttributesToSet, OptionBits inAttributesToClear);
6607
6608 Gestalt(gestaltSystemVersion, &osVersion);
6609 if (osVersion < 0x1040) // only supported for 10.4 (and up)
6610 return noErr;
6611
6612 // C name mangling...
6613 symbolName = "_DataBrowserChangeAttributes";
6614 if (!NSIsSymbolNameDefined(symbolName)
6615 || (symbol = NSLookupAndBindSymbol(symbolName)) == NULL)
6616 return noErr;
6617
6618 dataBrowserChangeAttributes = NSAddressOfSymbol(symbol);
6619 if (dataBrowserChangeAttributes == NULL)
6620 return noErr; // well...
6621 return dataBrowserChangeAttributes(inDataBrowser,
6622 inAttributesToSet, inAttributesToClear);
6623}
6624
6625 static void
6626initialise_tabline(void)
6627{
6628 Rect drawerRect = { 0, 0, 0, DRAWER_SIZE };
6629 DataBrowserCallbacks dbCallbacks;
6630 EventTypeSpec focusEvent = {kEventClassControl, kEventControlSetFocusPart};
6631 EventTypeSpec resizeEvent = {kEventClassWindow, kEventWindowBoundsChanged};
6632 DataBrowserListViewColumnDesc colDesc;
6633
6634 // drawers have to have compositing enabled
6635 CreateNewWindow(kDrawerWindowClass,
6636 kWindowStandardHandlerAttribute
6637 | kWindowCompositingAttribute
6638 | kWindowResizableAttribute
6639 | kWindowLiveResizeAttribute,
6640 &drawerRect, &drawer);
6641
6642 SetThemeWindowBackground(drawer, kThemeBrushDrawerBackground, true);
6643 SetDrawerParent(drawer, gui.VimWindow);
6644 SetDrawerOffsets(drawer, kWindowOffsetUnchanged, DRAWER_INSET);
6645
6646
6647 // create list view embedded in drawer
6648 CreateDataBrowserControl(drawer, &drawerRect, kDataBrowserListView,
6649 &dataBrowser);
6650
6651 dbCallbacks.version = kDataBrowserLatestCallbacks;
6652 InitDataBrowserCallbacks(&dbCallbacks);
6653 dbCallbacks.u.v1.itemDataCallback =
6654 NewDataBrowserItemDataUPP(dbItemDataCallback);
6655 dbCallbacks.u.v1.itemNotificationCallback =
6656 NewDataBrowserItemNotificationUPP(dbItemNotificationCallback);
6657 dbCallbacks.u.v1.getContextualMenuCallback =
6658 NewDataBrowserGetContextualMenuUPP(dbGetContextualMenuCallback);
6659 dbCallbacks.u.v1.selectContextualMenuCallback =
6660 NewDataBrowserSelectContextualMenuUPP(dbSelectContextualMenuCallback);
6661
6662 SetDataBrowserCallbacks(dataBrowser, &dbCallbacks);
6663
6664 SetDataBrowserListViewHeaderBtnHeight(dataBrowser, 0); // no header
6665 SetDataBrowserHasScrollBars(dataBrowser, false, true); // only vertical
6666 SetDataBrowserSelectionFlags(dataBrowser,
6667 kDataBrowserSelectOnlyOne | kDataBrowserNeverEmptySelectionSet);
6668 SetDataBrowserTableViewHiliteStyle(dataBrowser,
6669 kDataBrowserTableViewFillHilite);
6670 Boolean b = false;
6671 SetControlData(dataBrowser, kControlEntireControl,
6672 kControlDataBrowserIncludesFrameAndFocusTag, sizeof(b), &b);
6673
6674 // enable blue background in data browser (this is only in 10.4 and vim
6675 // has to support older osx versions as well, so we have to load this
6676 // function dynamically)
6677 myDataBrowserChangeAttributes(dataBrowser,
6678 kMyDataBrowserAttributeListViewAlternatingRowColors, 0);
6679
6680 // install callback that keeps focus in vim and away from the data browser
6681 InstallControlEventHandler(dataBrowser, dbFocusCallback, 1, &focusEvent,
6682 NULL, NULL);
6683
6684 // install callback that keeps data browser at the size of the drawer
6685 InstallWindowEventHandler(drawer, drawerCallback, 1, &resizeEvent,
6686 NULL, NULL);
6687
6688 // add "tabs" column to data browser
6689 colDesc.propertyDesc.propertyID = kTabsColumn;
6690 colDesc.propertyDesc.propertyType = kDataBrowserTextType;
6691
6692 // add if items can be selected (?): kDataBrowserListViewSelectionColumn
6693 colDesc.propertyDesc.propertyFlags = kDataBrowserDefaultPropertyFlags;
6694
6695 colDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
6696 colDesc.headerBtnDesc.minimumWidth = 100;
6697 colDesc.headerBtnDesc.maximumWidth = 150;
6698 colDesc.headerBtnDesc.titleOffset = 0;
6699 colDesc.headerBtnDesc.titleString = CFSTR("Tabs");
6700 colDesc.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing;
6701 colDesc.headerBtnDesc.btnFontStyle.flags = 0; // use default font
6702 colDesc.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
6703
6704 AddDataBrowserListViewColumn(dataBrowser, &colDesc, 0);
6705
6706 // create tabline popup menu required by vim docs (see :he tabline-menu)
6707 CreateNewMenu(kTabContextMenuId, 0, &contextMenu);
Bram Moolenaar7098ee52015-06-09 19:14:24 +02006708 if (first_tabpage->tp_next != NULL)
6709 AppendMenuItemTextWithCFString(contextMenu, CFSTR("Close Tab"), 0,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006710 TABLINE_MENU_CLOSE, NULL);
6711 AppendMenuItemTextWithCFString(contextMenu, CFSTR("New Tab"), 0,
6712 TABLINE_MENU_NEW, NULL);
6713 AppendMenuItemTextWithCFString(contextMenu, CFSTR("Open Tab..."), 0,
6714 TABLINE_MENU_OPEN, NULL);
6715}
6716
6717
6718/*
6719 * Show or hide the tabline.
6720 */
6721 void
6722gui_mch_show_tabline(int showit)
6723{
6724 if (showit == 0)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006725 CloseDrawer(drawer, true);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006726 else
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006727 OpenDrawer(drawer, kWindowEdgeRight, true);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006728}
6729
6730/*
6731 * Return TRUE when tabline is displayed.
6732 */
6733 int
6734gui_mch_showing_tabline(void)
6735{
6736 WindowDrawerState state = GetDrawerState(drawer);
6737
6738 return state == kWindowDrawerOpen || state == kWindowDrawerOpening;
6739}
6740
6741/*
6742 * Update the labels of the tabline.
6743 */
6744 void
6745gui_mch_update_tabline(void)
6746{
6747 tabpage_T *tp;
6748 int numTabs = getTabCount();
6749 int nr = 1;
6750 int curtabidx = 1;
6751
6752 // adjust data browser
6753 if (tabLabels != NULL)
6754 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006755 int i;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006756
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006757 for (i = 0; i < tabLabelsSize; ++i)
6758 CFRelease(tabLabels[i]);
6759 free(tabLabels);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006760 }
6761 tabLabels = (CFStringRef *)malloc(numTabs * sizeof(CFStringRef));
6762 tabLabelsSize = numTabs;
6763
6764 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
6765 {
6766 if (tp == curtab)
6767 curtabidx = nr;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006768 tabLabels[nr-1] = getTabLabel(tp);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006769 }
6770
6771 RemoveDataBrowserItems(dataBrowser, kDataBrowserNoItem, 0, NULL,
6772 kDataBrowserItemNoProperty);
6773 // data browser uses ids 1, 2, 3, ... numTabs per default, so we
6774 // can pass NULL for the id array
6775 AddDataBrowserItems(dataBrowser, kDataBrowserNoItem, numTabs, NULL,
6776 kDataBrowserItemNoProperty);
6777
6778 DataBrowserItemID item = curtabidx;
6779 SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
6780}
6781
6782/*
6783 * Set the current tab to "nr". First tab is 1.
6784 */
6785 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01006786gui_mch_set_curtab(int nr)
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006787{
6788 DataBrowserItemID item = nr;
6789 SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
6790
6791 // TODO: call something like this?: (or restore scroll position, or...)
6792 RevealDataBrowserItem(dataBrowser, item, kTabsColumn,
6793 kDataBrowserRevealOnly);
6794}
6795
6796#endif // FEAT_GUI_TABLINE